summaryrefslogtreecommitdiff
path: root/frontends
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2016-05-05 22:28:51 +0100
committerVincent Sanders <vince@kyllikki.org>2016-05-15 13:44:34 +0100
commitd21447d096a320a08b3efb2b8768fad0dcdcfd64 (patch)
tree1a83814b7c9e94b2f13c473261f23dd3a17dee64 /frontends
parent2cbb337756d9af5bda4d594964d446439f602551 (diff)
downloadnetsurf-d21447d096a320a08b3efb2b8768fad0dcdcfd64.tar.gz
netsurf-d21447d096a320a08b3efb2b8768fad0dcdcfd64.tar.bz2
move frontends into sub directory
Diffstat (limited to 'frontends')
-rw-r--r--frontends/Makefile9
-rw-r--r--frontends/amiga/Makefile122
-rw-r--r--frontends/amiga/Makefile.defaults42
-rw-r--r--frontends/amiga/agclass/amigaguide_class.c394
-rwxr-xr-xfrontends/amiga/agclass/amigaguide_class.h43
-rw-r--r--frontends/amiga/arexx.c636
-rwxr-xr-xfrontends/amiga/arexx.h32
-rw-r--r--frontends/amiga/bitmap.c706
-rwxr-xr-xfrontends/amiga/bitmap.h192
-rw-r--r--frontends/amiga/clipboard.c374
-rwxr-xr-xfrontends/amiga/clipboard.h42
-rwxr-xr-xfrontends/amiga/cookies.c39
-rwxr-xr-xfrontends/amiga/cookies.h28
-rw-r--r--frontends/amiga/ctxmenu.c607
-rw-r--r--frontends/amiga/ctxmenu.h92
-rw-r--r--frontends/amiga/datatypes.c40
-rw-r--r--frontends/amiga/datatypes.h41
-rwxr-xr-xfrontends/amiga/dist/Install397
-rw-r--r--frontends/amiga/dist/Install.infobin0 -> 8892 bytes
-rwxr-xr-xfrontends/amiga/dist/NetSurf.guide411
-rw-r--r--frontends/amiga/dist/NetSurf.guide.infobin0 -> 6741 bytes
-rw-r--r--frontends/amiga/dist/Rexx.infobin0 -> 6206 bytes
-rw-r--r--frontends/amiga/dist/Rexx/CloseTabs.nsrx47
-rw-r--r--frontends/amiga/dist/Rexx/SMTube.nsrx29
-rw-r--r--frontends/amiga/dist/Rexx/ShowTitles.nsrx18
-rwxr-xr-xfrontends/amiga/dist/Rexx/viewsource.nsrx24
-rw-r--r--frontends/amiga/download.c451
-rwxr-xr-xfrontends/amiga/download.h44
-rw-r--r--frontends/amiga/drag.c352
-rw-r--r--frontends/amiga/drag.h45
-rw-r--r--frontends/amiga/dt_anim.c365
-rw-r--r--frontends/amiga/dt_picture.c294
-rw-r--r--frontends/amiga/dt_sound.c278
-rw-r--r--frontends/amiga/file.c293
-rw-r--r--frontends/amiga/file.h45
-rw-r--r--frontends/amiga/filetype.c647
-rw-r--r--frontends/amiga/filetype.h51
-rw-r--r--frontends/amiga/font.c152
-rwxr-xr-xfrontends/amiga/font.h63
-rw-r--r--frontends/amiga/font_bullet.c895
-rw-r--r--frontends/amiga/font_bullet.h32
-rw-r--r--frontends/amiga/font_cache.c206
-rw-r--r--frontends/amiga/font_cache.h54
-rw-r--r--frontends/amiga/font_diskfont.c292
-rw-r--r--frontends/amiga/font_diskfont.h23
-rw-r--r--frontends/amiga/font_scan.c522
-rwxr-xr-xfrontends/amiga/font_scan.h39
-rw-r--r--frontends/amiga/gui.c5740
-rw-r--r--frontends/amiga/gui.h246
-rwxr-xr-xfrontends/amiga/gui_options.c2316
-rwxr-xr-xfrontends/amiga/gui_options.h32
-rw-r--r--frontends/amiga/hash/xxhash.c962
-rw-r--r--frontends/amiga/hash/xxhash.h192
-rwxr-xr-xfrontends/amiga/help.c85
-rwxr-xr-xfrontends/amiga/help.h38
-rwxr-xr-xfrontends/amiga/history.c41
-rwxr-xr-xfrontends/amiga/history.h29
-rwxr-xr-xfrontends/amiga/history_local.c341
-rwxr-xr-xfrontends/amiga/history_local.h45
-rwxr-xr-xfrontends/amiga/hotlist.c119
-rwxr-xr-xfrontends/amiga/hotlist.h34
-rw-r--r--frontends/amiga/icon.c545
-rw-r--r--frontends/amiga/icon.h47
-rwxr-xr-xfrontends/amiga/iff_cset.h33
-rw-r--r--frontends/amiga/iff_dr2d.c422
-rw-r--r--frontends/amiga/iff_dr2d.h107
-rwxr-xr-xfrontends/amiga/launch.c179
-rwxr-xr-xfrontends/amiga/launch.h33
-rw-r--r--frontends/amiga/libs.c326
-rw-r--r--frontends/amiga/libs.h82
-rwxr-xr-xfrontends/amiga/login.c238
-rwxr-xr-xfrontends/amiga/login.h31
-rw-r--r--frontends/amiga/menu.c1146
-rwxr-xr-xfrontends/amiga/menu.h150
-rwxr-xr-xfrontends/amiga/misc.c506
-rw-r--r--frontends/amiga/misc.h52
-rwxr-xr-xfrontends/amiga/object.c136
-rwxr-xr-xfrontends/amiga/object.h65
-rw-r--r--frontends/amiga/options.h95
-rw-r--r--frontends/amiga/os3support.c431
-rw-r--r--frontends/amiga/os3support.h254
-rwxr-xr-xfrontends/amiga/pkg/AutoInstall3
-rw-r--r--frontends/amiga/pkg/drawer.infobin0 -> 17208 bytes
-rwxr-xr-xfrontends/amiga/pkg/makepackage34
-rwxr-xr-xfrontends/amiga/pkg/makereslinks28
-rwxr-xr-xfrontends/amiga/pkg/netsurf.readme25
-rw-r--r--frontends/amiga/pkg/netsurf.readme.infobin0 -> 6238 bytes
-rw-r--r--frontends/amiga/pkg/netsurf_os3.readme28
-rw-r--r--frontends/amiga/pkg/netsurf_os3.readme.infobin0 -> 6238 bytes
-rw-r--r--frontends/amiga/plotters.c920
-rw-r--r--frontends/amiga/plotters.h55
-rw-r--r--frontends/amiga/plugin_hack.c274
-rw-r--r--frontends/amiga/plugin_hack.h28
-rw-r--r--frontends/amiga/print.c589
-rwxr-xr-xfrontends/amiga/print.h40
l---------frontends/amiga/resources/AdBlock.css1
-rw-r--r--frontends/amiga/resources/LangNames74
-rwxr-xr-xfrontends/amiga/resources/Pointers/Blank33
-rw-r--r--frontends/amiga/resources/Pointers/Blank.infobin0 -> 1719 bytes
-rwxr-xr-xfrontends/amiga/resources/Pointers/Caret33
-rw-r--r--frontends/amiga/resources/Pointers/Caret.infobin0 -> 1605 bytes
-rw-r--r--frontends/amiga/resources/Pointers/Cross.infobin0 -> 2046 bytes
-rwxr-xr-xfrontends/amiga/resources/Pointers/Default33
-rw-r--r--frontends/amiga/resources/Pointers/Default.infobin0 -> 2045 bytes
-rw-r--r--frontends/amiga/resources/Pointers/Down.infobin0 -> 1719 bytes
-rw-r--r--frontends/amiga/resources/Pointers/Drag.infobin0 -> 2302 bytes
-rw-r--r--frontends/amiga/resources/Pointers/Help.infobin0 -> 2775 bytes
-rw-r--r--frontends/amiga/resources/Pointers/Left.infobin0 -> 1587 bytes
-rw-r--r--frontends/amiga/resources/Pointers/LeftDown.infobin0 -> 1765 bytes
-rw-r--r--frontends/amiga/resources/Pointers/LeftUp.infobin0 -> 1695 bytes
-rwxr-xr-xfrontends/amiga/resources/Pointers/Menu33
-rw-r--r--frontends/amiga/resources/Pointers/Menu.infobin0 -> 2577 bytes
-rwxr-xr-xfrontends/amiga/resources/Pointers/Move33
-rw-r--r--frontends/amiga/resources/Pointers/Move.infobin0 -> 2840 bytes
-rw-r--r--frontends/amiga/resources/Pointers/NoDrop.infobin0 -> 2801 bytes
-rw-r--r--frontends/amiga/resources/Pointers/NotAllowed.infobin0 -> 2533 bytes
-rwxr-xr-xfrontends/amiga/resources/Pointers/Point33
-rw-r--r--frontends/amiga/resources/Pointers/Point.infobin0 -> 2755 bytes
-rw-r--r--frontends/amiga/resources/Pointers/Progress.infobin0 -> 2851 bytes
-rw-r--r--frontends/amiga/resources/Pointers/Right.infobin0 -> 1609 bytes
-rw-r--r--frontends/amiga/resources/Pointers/RightDown.infobin0 -> 1669 bytes
-rw-r--r--frontends/amiga/resources/Pointers/RightUp.infobin0 -> 1687 bytes
-rw-r--r--frontends/amiga/resources/Pointers/Up.infobin0 -> 1617 bytes
-rwxr-xr-xfrontends/amiga/resources/Pointers/Wait33
-rw-r--r--frontends/amiga/resources/Pointers/Wait.infobin0 -> 2449 bytes
-rw-r--r--frontends/amiga/resources/Resource.map4
-rw-r--r--frontends/amiga/resources/SearchEngines22
-rw-r--r--frontends/amiga/resources/Themes/AISS/NetSurf.infobin0 -> 23778 bytes
-rw-r--r--frontends/amiga/resources/Themes/AISS/Resource.map8
-rwxr-xr-xfrontends/amiga/resources/Themes/AISS/Theme75
-rw-r--r--frontends/amiga/resources/Themes/AISS/Throbberbin0 -> 5443 bytes
-rw-r--r--frontends/amiga/resources/Themes/Default/NetSurf.infobin0 -> 14818 bytes
-rwxr-xr-xfrontends/amiga/resources/Themes/Default/Theme88
-rw-r--r--frontends/amiga/resources/Themes/Default/Throbberbin0 -> 6479 bytes
-rwxr-xr-xfrontends/amiga/resources/Themes/Default/back.pngbin0 -> 653 bytes
-rw-r--r--frontends/amiga/resources/Themes/Default/back_g.pngbin0 -> 306 bytes
-rw-r--r--frontends/amiga/resources/Themes/Default/back_h.pngbin0 -> 607 bytes
-rw-r--r--frontends/amiga/resources/Themes/Default/closetab.pngbin0 -> 266 bytes
-rw-r--r--frontends/amiga/resources/Themes/Default/closetab_g.pngbin0 -> 169 bytes
-rwxr-xr-xfrontends/amiga/resources/Themes/Default/forward.pngbin0 -> 697 bytes
-rw-r--r--frontends/amiga/resources/Themes/Default/forward_g.pngbin0 -> 538 bytes
-rw-r--r--frontends/amiga/resources/Themes/Default/forward_h.pngbin0 -> 635 bytes
-rwxr-xr-xfrontends/amiga/resources/Themes/Default/home.pngbin0 -> 745 bytes
-rw-r--r--frontends/amiga/resources/Themes/Default/home_g.pngbin0 -> 576 bytes
-rw-r--r--frontends/amiga/resources/Themes/Default/home_h.pngbin0 -> 751 bytes
-rwxr-xr-xfrontends/amiga/resources/Themes/Default/reload.pngbin0 -> 1062 bytes
-rw-r--r--frontends/amiga/resources/Themes/Default/reload_g.pngbin0 -> 814 bytes
-rw-r--r--frontends/amiga/resources/Themes/Default/reload_h.pngbin0 -> 1046 bytes
-rw-r--r--frontends/amiga/resources/Themes/Default/search.pngbin0 -> 662 bytes
-rwxr-xr-xfrontends/amiga/resources/Themes/Default/stop.pngbin0 -> 1135 bytes
-rw-r--r--frontends/amiga/resources/Themes/Default/stop_g.pngbin0 -> 850 bytes
-rw-r--r--frontends/amiga/resources/Themes/Default/stop_h.pngbin0 -> 1119 bytes
-rw-r--r--frontends/amiga/resources/blankspace.pngbin0 -> 85 bytes
l---------frontends/amiga/resources/ca-bundle1
l---------frontends/amiga/resources/de1
-rw-r--r--frontends/amiga/resources/default.css7
-rw-r--r--frontends/amiga/resources/default.css.infobin0 -> 5082 bytes
l---------frontends/amiga/resources/en1
-rw-r--r--frontends/amiga/resources/favicon.pngbin0 -> 685 bytes
l---------frontends/amiga/resources/fr1
l---------frontends/amiga/resources/it1
-rw-r--r--frontends/amiga/resources/mimetypes112
l---------frontends/amiga/resources/nl1
l---------frontends/amiga/resources/nsdefault.css1
l---------frontends/amiga/resources/quirks.css1
-rw-r--r--frontends/amiga/resources/splash.pngbin0 -> 29458 bytes
-rw-r--r--frontends/amiga/rtg.c72
-rw-r--r--frontends/amiga/rtg.h37
-rw-r--r--frontends/amiga/save_pdf.c59
-rw-r--r--frontends/amiga/save_pdf.h31
-rwxr-xr-xfrontends/amiga/schedule.c353
-rwxr-xr-xfrontends/amiga/schedule.h57
-rwxr-xr-xfrontends/amiga/search.c339
-rwxr-xr-xfrontends/amiga/search.h37
-rw-r--r--frontends/amiga/selectmenu.c200
-rwxr-xr-xfrontends/amiga/selectmenu.h39
-rw-r--r--frontends/amiga/sslcert.c50
-rw-r--r--frontends/amiga/sslcert.h28
-rwxr-xr-xfrontends/amiga/stringview/stringview.c870
-rwxr-xr-xfrontends/amiga/stringview/stringview.h60
-rw-r--r--frontends/amiga/stringview/urlhistory.c124
-rw-r--r--frontends/amiga/stringview/urlhistory.h33
-rw-r--r--frontends/amiga/theme.c513
-rw-r--r--frontends/amiga/theme.h50
-rw-r--r--frontends/amiga/tree.c1473
-rwxr-xr-xfrontends/amiga/tree.h48
-rwxr-xr-xfrontends/amiga/utf8.c104
-rwxr-xr-xfrontends/amiga/utf8.h31
-rw-r--r--frontends/amiga/version.c39
-rw-r--r--frontends/atari/Makefile208
-rw-r--r--frontends/atari/Makefile.defaults58
-rw-r--r--frontends/atari/about.c206
-rw-r--r--frontends/atari/about.h24
-rw-r--r--frontends/atari/bitmap.c455
-rw-r--r--frontends/atari/bitmap.h137
-rw-r--r--frontends/atari/certview.c296
-rw-r--r--frontends/atari/certview.h51
-rw-r--r--frontends/atari/clipboard.c88
-rw-r--r--frontends/atari/clipboard.h25
-rw-r--r--frontends/atari/cookies.c220
-rw-r--r--frontends/atari/cookies.h39
-rw-r--r--frontends/atari/ctxmenu.c321
-rw-r--r--frontends/atari/ctxmenu.h24
-rw-r--r--frontends/atari/deskmenu.c828
-rw-r--r--frontends/atari/deskmenu.h11
-rwxr-xr-xfrontends/atari/doc/DejaVu.txt99
-rwxr-xr-xfrontends/atari/doc/bugs4
-rwxr-xr-xfrontends/atari/doc/changes.txt53
-rwxr-xr-xfrontends/atari/doc/faq.txt74
-rwxr-xr-xfrontends/atari/doc/readme.txt125
-rwxr-xr-xfrontends/atari/doc/todo.txt18
-rw-r--r--frontends/atari/download.c453
-rw-r--r--frontends/atari/download.h63
-rw-r--r--frontends/atari/encoding.c81
-rw-r--r--frontends/atari/encoding.h35
-rwxr-xr-xfrontends/atari/extract.php10
-rw-r--r--frontends/atari/file.c294
-rw-r--r--frontends/atari/file.h27
-rw-r--r--frontends/atari/filetype.c91
-rw-r--r--frontends/atari/filetype.h24
-rw-r--r--frontends/atari/findfile.c144
-rw-r--r--frontends/atari/findfile.h26
-rw-r--r--frontends/atari/font.c156
-rw-r--r--frontends/atari/font.h25
-rw-r--r--frontends/atari/gemtk/aestabs.c191
-rw-r--r--frontends/atari/gemtk/aestabs.h56
-rwxr-xr-xfrontends/atari/gemtk/dragdrop.c515
-rwxr-xr-xfrontends/atari/gemtk/dragdrop.h4
-rw-r--r--frontends/atari/gemtk/gemtk.h298
-rw-r--r--frontends/atari/gemtk/guiwin.c1430
-rw-r--r--frontends/atari/gemtk/guiwin.h4
-rw-r--r--frontends/atari/gemtk/msgbox.c110
-rw-r--r--frontends/atari/gemtk/msgbox.h5
-rw-r--r--frontends/atari/gemtk/objc.c522
-rw-r--r--frontends/atari/gemtk/objc.h7
-rw-r--r--frontends/atari/gemtk/redrawslots.c123
-rw-r--r--frontends/atari/gemtk/redrawslots.h25
-rw-r--r--frontends/atari/gemtk/utils.c144
-rw-r--r--frontends/atari/gemtk/utils.h5
-rw-r--r--frontends/atari/gemtk/vaproto.c170
-rw-r--r--frontends/atari/gemtk/vaproto.h121
-rw-r--r--frontends/atari/gui.c1217
-rw-r--r--frontends/atari/gui.h183
-rw-r--r--frontends/atari/history.c191
-rw-r--r--frontends/atari/history.h39
-rw-r--r--frontends/atari/hotlist.c315
-rw-r--r--frontends/atari/hotlist.h52
-rw-r--r--frontends/atari/login.c71
-rw-r--r--frontends/atari/login.h26
-rw-r--r--frontends/atari/misc.c408
-rw-r--r--frontends/atari/misc.h106
-rw-r--r--frontends/atari/options.h48
-rw-r--r--frontends/atari/osspec.c132
-rw-r--r--frontends/atari/osspec.h45
-rw-r--r--frontends/atari/plot/eddi.h54
-rw-r--r--frontends/atari/plot/eddi.s42
-rw-r--r--frontends/atari/plot/font_freetype.c714
-rw-r--r--frontends/atari/plot/font_freetype.h52
-rw-r--r--frontends/atari/plot/font_internal.c2386
-rw-r--r--frontends/atari/plot/font_internal.h37
-rw-r--r--frontends/atari/plot/font_vdi.c310
-rw-r--r--frontends/atari/plot/font_vdi.h26
-rw-r--r--frontends/atari/plot/fontplot.c132
-rw-r--r--frontends/atari/plot/fontplot.h86
-rw-r--r--frontends/atari/plot/plot.c2247
-rw-r--r--frontends/atari/plot/plot.h158
-rw-r--r--frontends/atari/redrawslots.c125
-rw-r--r--frontends/atari/redrawslots.h54
-rw-r--r--frontends/atari/res/blank39
-rw-r--r--frontends/atari/res/favicon.icobin0 -> 9862 bytes
-rw-r--r--frontends/atari/res/icons/toolbar/atfact/main.pngbin0 -> 12555 bytes
-rw-r--r--frontends/atari/res/icons/toolbar/atfact/throbber.pngbin0 -> 6135 bytes
-rw-r--r--frontends/atari/res/icons/toolbar/default/main.pngbin0 -> 46417 bytes
-rw-r--r--frontends/atari/res/icons/toolbar/default/main.xcfbin0 -> 16404 bytes
-rw-r--r--frontends/atari/res/icons/toolbar/default/throbber.pngbin0 -> 20960 bytes
-rw-r--r--frontends/atari/res/icons/toolbar/default/throbber.xcfbin0 -> 10231 bytes
-rw-r--r--frontends/atari/res/languages261
-rwxr-xr-xfrontends/atari/res/netsurf.rscbin0 -> 38896 bytes
-rwxr-xr-xfrontends/atari/res/netsurf.rsh241
-rwxr-xr-xfrontends/atari/res/netsurf.rsm225
-rw-r--r--frontends/atari/rootwin.c1540
-rw-r--r--frontends/atari/rootwin.h97
-rw-r--r--frontends/atari/save.h22
-rw-r--r--frontends/atari/schedule.c228
-rw-r--r--frontends/atari/schedule.h48
-rwxr-xr-xfrontends/atari/scripts/env-v4e.sh7
-rwxr-xr-xfrontends/atari/scripts/env-x86.sh9
-rw-r--r--frontends/atari/search.c303
-rw-r--r--frontends/atari/search.h53
-rw-r--r--frontends/atari/settings.c990
-rw-r--r--frontends/atari/settings.h26
-rw-r--r--frontends/atari/statusbar.c232
-rw-r--r--frontends/atari/statusbar.h40
-rw-r--r--frontends/atari/toolbar.c1041
-rw-r--r--frontends/atari/toolbar.h96
-rw-r--r--frontends/atari/treeview.c794
-rw-r--r--frontends/atari/treeview.h124
-rw-r--r--frontends/atari/verify_ssl.c269
-rw-r--r--frontends/atari/verify_ssl.h24
-rw-r--r--frontends/beos/Makefile102
-rw-r--r--frontends/beos/Makefile.defaults30
-rw-r--r--frontends/beos/WindowStack.h45
-rw-r--r--frontends/beos/about.cpp57
-rw-r--r--frontends/beos/about.h24
-rw-r--r--frontends/beos/beos_res.rsrcbin0 -> 11584 bytes
-rw-r--r--frontends/beos/bitmap.cpp556
-rw-r--r--frontends/beos/bitmap.h33
-rw-r--r--frontends/beos/cookies.cpp417
-rw-r--r--frontends/beos/cookies.h24
-rw-r--r--frontends/beos/download.cpp264
-rw-r--r--frontends/beos/download.h19
-rw-r--r--frontends/beos/fetch_rsrc.cpp396
-rw-r--r--frontends/beos/fetch_rsrc.h35
-rw-r--r--frontends/beos/filetype.cpp138
-rw-r--r--frontends/beos/filetype.h21
-rw-r--r--frontends/beos/font.cpp374
-rw-r--r--frontends/beos/font.h37
-rw-r--r--frontends/beos/gui.cpp1109
-rw-r--r--frontends/beos/gui.h88
-rw-r--r--frontends/beos/gui_options.cpp50
-rw-r--r--frontends/beos/gui_options.h31
-rw-r--r--frontends/beos/login.cpp196
-rw-r--r--frontends/beos/options.h30
-rw-r--r--frontends/beos/plotters.cpp659
-rw-r--r--frontends/beos/plotters.h48
-rw-r--r--frontends/beos/res.h18
-rw-r--r--frontends/beos/res.rdef242
l---------frontends/beos/res/SearchEngines1
l---------frontends/beos/res/adblock.css1
-rw-r--r--frontends/beos/res/beosdefault.css22
l---------frontends/beos/res/ca-bundle.txt1
l---------frontends/beos/res/credits.html1
l---------frontends/beos/res/de/welcome.html1
l---------frontends/beos/res/default.css1
l---------frontends/beos/res/en/credits.html1
l---------frontends/beos/res/en/licence.html1
l---------frontends/beos/res/en/maps.html1
l---------frontends/beos/res/en/welcome.html1
l---------frontends/beos/res/favicon.png1
l---------frontends/beos/res/icons1
l---------frontends/beos/res/internal.css1
l---------frontends/beos/res/it/credits.html1
l---------frontends/beos/res/it/licence.html1
l---------frontends/beos/res/it/welcome.html1
l---------frontends/beos/res/ja/welcome.html1
l---------frontends/beos/res/licence.html1
-rw-r--r--frontends/beos/res/license332
l---------frontends/beos/res/maps.html1
l---------frontends/beos/res/netsurf.png1
l---------frontends/beos/res/quirks.css1
-rw-r--r--frontends/beos/res/throbber/throbber0.pngbin0 -> 521 bytes
-rw-r--r--frontends/beos/res/throbber/throbber1.pngbin0 -> 820 bytes
-rw-r--r--frontends/beos/res/throbber/throbber2.pngbin0 -> 812 bytes
-rw-r--r--frontends/beos/res/throbber/throbber3.pngbin0 -> 826 bytes
-rw-r--r--frontends/beos/res/throbber/throbber4.pngbin0 -> 818 bytes
-rw-r--r--frontends/beos/res/throbber/throbber5.pngbin0 -> 815 bytes
-rw-r--r--frontends/beos/res/throbber/throbber6.pngbin0 -> 839 bytes
-rw-r--r--frontends/beos/res/throbber/throbber7.pngbin0 -> 811 bytes
-rw-r--r--frontends/beos/res/throbber/throbber8.pngbin0 -> 833 bytes
l---------frontends/beos/res/welcome.html1
-rw-r--r--frontends/beos/scaffolding.cpp2332
-rw-r--r--frontends/beos/scaffolding.h210
-rw-r--r--frontends/beos/schedule.cpp142
-rw-r--r--frontends/beos/schedule.h29
-rw-r--r--frontends/beos/search.cpp76
-rw-r--r--frontends/beos/throbber.cpp118
-rw-r--r--frontends/beos/throbber.h36
-rw-r--r--frontends/beos/window.cpp1382
-rw-r--r--frontends/beos/window.h83
-rw-r--r--frontends/cocoa/ArrowBox.h34
-rw-r--r--frontends/cocoa/ArrowBox.m163
-rw-r--r--frontends/cocoa/ArrowWindow.h32
-rw-r--r--frontends/cocoa/ArrowWindow.m239
-rw-r--r--frontends/cocoa/BlackScroller.h20
-rw-r--r--frontends/cocoa/BlackScroller.m154
-rw-r--r--frontends/cocoa/BookmarksController.h41
-rw-r--r--frontends/cocoa/BookmarksController.m223
-rw-r--r--frontends/cocoa/BrowserView.h53
-rw-r--r--frontends/cocoa/BrowserView.m757
-rw-r--r--frontends/cocoa/BrowserViewController.h75
-rw-r--r--frontends/cocoa/BrowserViewController.m378
-rw-r--r--frontends/cocoa/BrowserWindow.h26
-rw-r--r--frontends/cocoa/BrowserWindow.m29
-rw-r--r--frontends/cocoa/BrowserWindowController.h57
-rw-r--r--frontends/cocoa/BrowserWindowController.m266
-rw-r--r--frontends/cocoa/DownloadWindowController.h53
-rw-r--r--frontends/cocoa/DownloadWindowController.m415
-rw-r--r--frontends/cocoa/FormSelectMenu.h32
-rw-r--r--frontends/cocoa/FormSelectMenu.m113
-rw-r--r--frontends/cocoa/HistoryView.h35
-rw-r--r--frontends/cocoa/HistoryView.m151
-rw-r--r--frontends/cocoa/HistoryWindowController.h31
-rw-r--r--frontends/cocoa/HistoryWindowController.m52
-rw-r--r--frontends/cocoa/LocalHistoryController.h40
-rw-r--r--frontends/cocoa/LocalHistoryController.m119
-rw-r--r--frontends/cocoa/Makefile249
-rw-r--r--frontends/cocoa/Makefile.defaults30
-rw-r--r--frontends/cocoa/NetSurf.xcodeproj/project.pbxproj1023
-rw-r--r--frontends/cocoa/NetSurfAppDelegate.h42
-rw-r--r--frontends/cocoa/NetSurfAppDelegate.m200
-rw-r--r--frontends/cocoa/NetsurfApp.h31
-rw-r--r--frontends/cocoa/NetsurfApp.m302
-rw-r--r--frontends/cocoa/PSMTabBarControl/Images/AquaTabCloseDirty_Front.pngbin0 -> 292 bytes
-rw-r--r--frontends/cocoa/PSMTabBarControl/Images/AquaTabCloseDirty_Front_Pressed.pngbin0 -> 292 bytes
-rw-r--r--frontends/cocoa/PSMTabBarControl/Images/AquaTabCloseDirty_Front_Rollover.pngbin0 -> 297 bytes
-rw-r--r--frontends/cocoa/PSMTabBarControl/Images/AquaTabClose_Front.pngbin0 -> 307 bytes
-rw-r--r--frontends/cocoa/PSMTabBarControl/Images/AquaTabClose_Front_Pressed.pngbin0 -> 310 bytes
-rw-r--r--frontends/cocoa/PSMTabBarControl/Images/AquaTabClose_Front_Rollover.pngbin0 -> 317 bytes
-rw-r--r--frontends/cocoa/PSMTabBarControl/Images/AquaTabNew.pngbin0 -> 371 bytes
-rw-r--r--frontends/cocoa/PSMTabBarControl/Images/AquaTabNewPressed.pngbin0 -> 380 bytes
-rw-r--r--frontends/cocoa/PSMTabBarControl/Images/AquaTabNewRollover.pngbin0 -> 380 bytes
-rw-r--r--frontends/cocoa/PSMTabBarControl/Images/overflowImage.pngbin0 -> 256 bytes
-rw-r--r--frontends/cocoa/PSMTabBarControl/Images/overflowImagePressed.pngbin0 -> 250 bytes
-rw-r--r--frontends/cocoa/PSMTabBarControl/Images/pi.pngbin0 -> 564 bytes
-rw-r--r--frontends/cocoa/PSMTabBarControl/NSBezierPath_AMShading.h23
-rw-r--r--frontends/cocoa/PSMTabBarControl/NSBezierPath_AMShading.m119
-rw-r--r--frontends/cocoa/PSMTabBarControl/NSString_AITruncation.h12
-rw-r--r--frontends/cocoa/PSMTabBarControl/NSString_AITruncation.m32
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMOverflowPopUpButton.h28
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMOverflowPopUpButton.m152
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMProgressIndicator.h15
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMProgressIndicator.m40
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMRolloverButton.h28
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMRolloverButton.m170
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMTabBarCell.h116
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMTabBarCell.m489
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMTabBarControl.h241
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMTabBarControl.m1995
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMTabBarController.h38
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMTabBarController.m643
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMTabDragAssistant.h101
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMTabDragAssistant.m834
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMTabDragView.h21
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMTabDragView.m62
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMTabDragWindow.h20
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMTabDragWindow.m48
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMTabDragWindowController.h33
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMTabDragWindowController.m111
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMTabStyle.h57
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMUnifiedTabStyle.h29
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMUnifiedTabStyle.m573
-rw-r--r--frontends/cocoa/PSMTabBarControl/ReadMe.rtfd/TXT.rtf186
-rw-r--r--frontends/cocoa/PSMTabBarControl/ReadMe.rtfd/startpage.gifbin0 -> 11246 bytes
-rw-r--r--frontends/cocoa/PreferencesWindowController.h29
-rw-r--r--frontends/cocoa/PreferencesWindowController.m57
-rw-r--r--frontends/cocoa/Prefix.pch11
-rw-r--r--frontends/cocoa/ScrollableView.h31
-rw-r--r--frontends/cocoa/ScrollableView.m71
-rw-r--r--frontends/cocoa/SearchWindowController.h54
-rw-r--r--frontends/cocoa/SearchWindowController.m119
-rw-r--r--frontends/cocoa/Tree.h56
-rw-r--r--frontends/cocoa/Tree.m147
-rw-r--r--frontends/cocoa/TreeView.h34
-rw-r--r--frontends/cocoa/TreeView.m249
-rw-r--r--frontends/cocoa/URLFieldCell.h31
-rw-r--r--frontends/cocoa/URLFieldCell.m208
-rw-r--r--frontends/cocoa/apple_image.h39
-rw-r--r--frontends/cocoa/apple_image.m255
-rw-r--r--frontends/cocoa/bitmap.h28
-rw-r--r--frontends/cocoa/bitmap.m282
-rwxr-xr-xfrontends/cocoa/compile-xib.sh20
-rw-r--r--frontends/cocoa/coordinates.h108
-rwxr-xr-xfrontends/cocoa/extract-strings.sh11
-rw-r--r--frontends/cocoa/fetch.h19
-rw-r--r--frontends/cocoa/fetch.m113
-rw-r--r--frontends/cocoa/font.h28
-rw-r--r--frontends/cocoa/font.m243
-rw-r--r--frontends/cocoa/gui.h35
-rw-r--r--frontends/cocoa/gui.m335
-rw-r--r--frontends/cocoa/plotter.h34
-rw-r--r--frontends/cocoa/plotter.m335
-rw-r--r--frontends/cocoa/res/BookmarksWindow.xib610
-rw-r--r--frontends/cocoa/res/Browser.xib399
-rw-r--r--frontends/cocoa/res/BrowserWindow.xib1395
-rw-r--r--frontends/cocoa/res/DownloadWindow.xib493
-rw-r--r--frontends/cocoa/res/HistoryWindow.xib338
-rw-r--r--frontends/cocoa/res/HomeTemplate.pdf106
l---------frontends/cocoa/res/Icons1
-rw-r--r--frontends/cocoa/res/LocalHistoryPanel.xib357
-rw-r--r--frontends/cocoa/res/MainMenu.xib2369
-rw-r--r--frontends/cocoa/res/NetSurf-Info.plist111
-rw-r--r--frontends/cocoa/res/NetSurf.icnsbin0 -> 203268 bytes
-rw-r--r--frontends/cocoa/res/PreferencesWindow.xib512
-rw-r--r--frontends/cocoa/res/SearchWindow.xib614
l---------frontends/cocoa/res/adblock.css1
l---------frontends/cocoa/res/ca-bundle1
-rw-r--r--frontends/cocoa/res/de.lproj/BookmarksWindow.xib.stringsbin0 -> 366 bytes
-rw-r--r--frontends/cocoa/res/de.lproj/BrowserWindow.xib.stringsbin0 -> 1892 bytes
-rw-r--r--frontends/cocoa/res/de.lproj/DownloadWindow.xib.stringsbin0 -> 536 bytes
-rw-r--r--frontends/cocoa/res/de.lproj/HistoryWindow.xib.stringsbin0 -> 172 bytes
-rw-r--r--frontends/cocoa/res/de.lproj/Localizable.strings78
-rw-r--r--frontends/cocoa/res/de.lproj/MainMenu.xib.stringsbin0 -> 11982 bytes
l---------frontends/cocoa/res/de.lproj/Messages1
-rw-r--r--frontends/cocoa/res/de.lproj/PreferencesWindow.xib.stringsbin0 -> 1206 bytes
-rw-r--r--frontends/cocoa/res/de.lproj/SearchWindow.xib.stringsbin0 -> 1148 bytes
l---------frontends/cocoa/res/default.css1
-rw-r--r--frontends/cocoa/res/en.lproj/Localizable.stringsbin0 -> 3322 bytes
l---------frontends/cocoa/res/en.lproj/Messages1
-rw-r--r--frontends/cocoa/res/fr.lproj/Localizable.stringsbin0 -> 3322 bytes
l---------frontends/cocoa/res/fr.lproj/Messages1
l---------frontends/cocoa/res/internal.css1
-rw-r--r--frontends/cocoa/res/it.lproj/Localizable.stringsbin0 -> 3496 bytes
l---------frontends/cocoa/res/it.lproj/Messages1
l---------frontends/cocoa/res/netsurf.png1
-rw-r--r--frontends/cocoa/res/nl.lproj/Localizable.stringsbin0 -> 3322 bytes
l---------frontends/cocoa/res/nl.lproj/Messages1
l---------frontends/cocoa/res/quirks.css1
-rw-r--r--frontends/cocoa/schedule.h19
-rw-r--r--frontends/cocoa/schedule.m90
-rw-r--r--frontends/cocoa/selection.h19
-rw-r--r--frontends/cocoa/selection.m104
-rw-r--r--frontends/framebuffer/Makefile184
-rw-r--r--frontends/framebuffer/Makefile.defaults47
-rw-r--r--frontends/framebuffer/bitmap.c352
-rw-r--r--frontends/framebuffer/bitmap.h26
-rw-r--r--frontends/framebuffer/clipboard.c105
-rw-r--r--frontends/framebuffer/clipboard.h24
-rw-r--r--frontends/framebuffer/convert_font.c1215
-rw-r--r--frontends/framebuffer/convert_image.c315
-rw-r--r--frontends/framebuffer/fb_search.c74
-rw-r--r--frontends/framebuffer/fbtk.h616
-rw-r--r--frontends/framebuffer/fbtk/bitmap.c136
-rw-r--r--frontends/framebuffer/fbtk/event.c349
-rw-r--r--frontends/framebuffer/fbtk/fbtk.c830
-rw-r--r--frontends/framebuffer/fbtk/fill.c81
-rw-r--r--frontends/framebuffer/fbtk/osk.c199
-rw-r--r--frontends/framebuffer/fbtk/scroll.c589
-rw-r--r--frontends/framebuffer/fbtk/text.c640
-rw-r--r--frontends/framebuffer/fbtk/user.c64
-rw-r--r--frontends/framebuffer/fbtk/widget.h259
-rw-r--r--frontends/framebuffer/fbtk/window.c91
-rw-r--r--frontends/framebuffer/fetch.c98
-rw-r--r--frontends/framebuffer/fetch.h25
-rw-r--r--frontends/framebuffer/findfile.c56
-rw-r--r--frontends/framebuffer/findfile.h32
-rw-r--r--frontends/framebuffer/font.h68
-rw-r--r--frontends/framebuffer/font_freetype.c566
-rw-r--r--frontends/framebuffer/font_freetype.h30
-rw-r--r--frontends/framebuffer/font_internal.c491
-rw-r--r--frontends/framebuffer/font_internal.h49
-rw-r--r--frontends/framebuffer/framebuffer.c467
-rw-r--r--frontends/framebuffer/framebuffer.h40
-rw-r--r--frontends/framebuffer/gui.c2226
-rw-r--r--frontends/framebuffer/gui.h84
-rw-r--r--frontends/framebuffer/image_data.h60
-rw-r--r--frontends/framebuffer/localhistory.c144
-rw-r--r--frontends/framebuffer/options.h70
l---------frontends/framebuffer/res/Messages1
l---------frontends/framebuffer/res/adblock.css1
l---------frontends/framebuffer/res/credits.html1
l---------frontends/framebuffer/res/default.css1
l---------frontends/framebuffer/res/favicon.png1
-rw-r--r--frontends/framebuffer/res/fonts/glyph_data9508
-rw-r--r--frontends/framebuffer/res/icons/back.pngbin0 -> 741 bytes
-rw-r--r--frontends/framebuffer/res/icons/back_g.pngbin0 -> 701 bytes
-rw-r--r--frontends/framebuffer/res/icons/forward.pngbin0 -> 672 bytes
-rw-r--r--frontends/framebuffer/res/icons/forward_g.pngbin0 -> 702 bytes
-rw-r--r--frontends/framebuffer/res/icons/history.pngbin0 -> 884 bytes
-rw-r--r--frontends/framebuffer/res/icons/history_g.pngbin0 -> 798 bytes
-rw-r--r--frontends/framebuffer/res/icons/home.pngbin0 -> 818 bytes
-rw-r--r--frontends/framebuffer/res/icons/home_g.pngbin0 -> 798 bytes
-rw-r--r--frontends/framebuffer/res/icons/osk.pngbin0 -> 262 bytes
-rw-r--r--frontends/framebuffer/res/icons/reload.pngbin0 -> 1075 bytes
-rw-r--r--frontends/framebuffer/res/icons/reload_g.pngbin0 -> 1109 bytes
-rw-r--r--frontends/framebuffer/res/icons/scrolld.pngbin0 -> 294 bytes
-rw-r--r--frontends/framebuffer/res/icons/scrolll.pngbin0 -> 307 bytes
-rw-r--r--frontends/framebuffer/res/icons/scrollr.pngbin0 -> 286 bytes
-rw-r--r--frontends/framebuffer/res/icons/scrollu.pngbin0 -> 280 bytes
-rw-r--r--frontends/framebuffer/res/icons/stop.pngbin0 -> 1023 bytes
-rw-r--r--frontends/framebuffer/res/icons/stop_g.pngbin0 -> 1050 bytes
l---------frontends/framebuffer/res/internal.css1
l---------frontends/framebuffer/res/licence.html1
l---------frontends/framebuffer/res/maps.html1
l---------frontends/framebuffer/res/netsurf.png1
-rw-r--r--frontends/framebuffer/res/pointers/caret.pngbin0 -> 146 bytes
-rw-r--r--frontends/framebuffer/res/pointers/cross.pngbin0 -> 144 bytes
-rw-r--r--frontends/framebuffer/res/pointers/default.pngbin0 -> 179 bytes
-rw-r--r--frontends/framebuffer/res/pointers/help.pngbin0 -> 209 bytes
-rw-r--r--frontends/framebuffer/res/pointers/left-right.pngbin0 -> 163 bytes
-rw-r--r--frontends/framebuffer/res/pointers/lu-rd.pngbin0 -> 170 bytes
-rw-r--r--frontends/framebuffer/res/pointers/menu.pngbin0 -> 220 bytes
-rw-r--r--frontends/framebuffer/res/pointers/move.pngbin0 -> 183 bytes
-rw-r--r--frontends/framebuffer/res/pointers/no_drop.pngbin0 -> 224 bytes
-rw-r--r--frontends/framebuffer/res/pointers/not_allowed.pngbin0 -> 197 bytes
-rw-r--r--frontends/framebuffer/res/pointers/point.pngbin0 -> 181 bytes
-rw-r--r--frontends/framebuffer/res/pointers/progress.pngbin0 -> 213 bytes
-rw-r--r--frontends/framebuffer/res/pointers/ru-ld.pngbin0 -> 171 bytes
-rw-r--r--frontends/framebuffer/res/pointers/up-down.pngbin0 -> 167 bytes
-rw-r--r--frontends/framebuffer/res/pointers/wait.pngbin0 -> 211 bytes
l---------frontends/framebuffer/res/quirks.css1
l---------frontends/framebuffer/res/throbber1
l---------frontends/framebuffer/res/welcome.html1
-rw-r--r--frontends/framebuffer/schedule.c221
-rw-r--r--frontends/framebuffer/schedule.h45
-rw-r--r--frontends/gtk/Makefile205
-rw-r--r--frontends/gtk/Makefile.defaults42
-rw-r--r--frontends/gtk/about.c157
-rw-r--r--frontends/gtk/about.h24
-rw-r--r--frontends/gtk/bitmap.c540
-rw-r--r--frontends/gtk/bitmap.h35
-rw-r--r--frontends/gtk/compat.c640
-rw-r--r--frontends/gtk/compat.h296
-rw-r--r--frontends/gtk/completion.c157
-rw-r--r--frontends/gtk/completion.h46
-rw-r--r--frontends/gtk/cookies.c219
-rw-r--r--frontends/gtk/cookies.h37
-rw-r--r--frontends/gtk/download.c865
-rw-r--r--frontends/gtk/download.h41
-rw-r--r--frontends/gtk/fetch.c260
-rw-r--r--frontends/gtk/fetch.h28
-rw-r--r--frontends/gtk/gdk.c124
-rw-r--r--frontends/gtk/gdk.h35
-rw-r--r--frontends/gtk/gettext.c43
-rw-r--r--frontends/gtk/gettext.h32
-rw-r--r--frontends/gtk/gui.c1161
-rw-r--r--frontends/gtk/gui.h45
-rw-r--r--frontends/gtk/history.c273
-rw-r--r--frontends/gtk/history.h39
-rw-r--r--frontends/gtk/hotlist.c280
-rw-r--r--frontends/gtk/hotlist.h40
-rw-r--r--frontends/gtk/layout_pango.c309
-rw-r--r--frontends/gtk/layout_pango.h43
-rw-r--r--frontends/gtk/login.c232
-rw-r--r--frontends/gtk/login.h31
-rw-r--r--frontends/gtk/menu.c585
-rw-r--r--frontends/gtk/menu.h227
-rw-r--r--frontends/gtk/options.h72
-rw-r--r--frontends/gtk/plotters.c538
-rw-r--r--frontends/gtk/plotters.h40
-rw-r--r--frontends/gtk/preferences.c1030
-rw-r--r--frontends/gtk/preferences.h28
-rw-r--r--frontends/gtk/print.c613
-rw-r--r--frontends/gtk/print.h50
l---------frontends/gtk/res/Messages1
l---------frontends/gtk/res/SearchEngines1
l---------frontends/gtk/res/adblock.css1
-rw-r--r--frontends/gtk/res/arrow_down_8x32.pngbin0 -> 206 bytes
l---------frontends/gtk/res/ca-bundle.txt1
-rw-r--r--frontends/gtk/res/cookies.gtk2.ui174
-rw-r--r--frontends/gtk/res/cookies.gtk3.ui206
l---------frontends/gtk/res/credits.html1
l---------frontends/gtk/res/de/welcome.html1
l---------frontends/gtk/res/default.css1
-rw-r--r--frontends/gtk/res/default.icobin0 -> 1406 bytes
-rw-r--r--frontends/gtk/res/downloads.gtk2.ui175
-rw-r--r--frontends/gtk/res/downloads.gtk3.ui175
l---------frontends/gtk/res/en/credits.html1
l---------frontends/gtk/res/en/licence.html1
l---------frontends/gtk/res/en/maps.html1
l---------frontends/gtk/res/en/welcome.html1
l---------frontends/gtk/res/favicon.png1
-rw-r--r--frontends/gtk/res/history.gtk2.ui242
-rw-r--r--frontends/gtk/res/history.gtk3.ui238
-rw-r--r--frontends/gtk/res/hotlist.gtk2.ui217
-rw-r--r--frontends/gtk/res/hotlist.gtk3.ui255
l---------frontends/gtk/res/icons1
l---------frontends/gtk/res/internal.css1
l---------frontends/gtk/res/it/credits.html1
l---------frontends/gtk/res/it/licence.html1
l---------frontends/gtk/res/it/welcome.html1
l---------frontends/gtk/res/ja/welcome.html1
-rw-r--r--frontends/gtk/res/languages261
l---------frontends/gtk/res/licence.html1
-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/menu_cursor.pngbin0 -> 255 bytes
-rw-r--r--frontends/gtk/res/menu_cursor.xbm6
-rw-r--r--frontends/gtk/res/menu_cursor_mask.xbm6
-rw-r--r--frontends/gtk/res/menu_cursor_mask.xpm22
-rw-r--r--frontends/gtk/res/messages.gresource.xml10
-rw-r--r--frontends/gtk/res/netsurf-16x16.xpm211
-rw-r--r--frontends/gtk/res/netsurf-gtk.desktop68
-rw-r--r--frontends/gtk/res/netsurf.gresource.xml70
-rw-r--r--frontends/gtk/res/netsurf.gtk2.ui212
-rw-r--r--frontends/gtk/res/netsurf.gtk3.ui207
l---------frontends/gtk/res/netsurf.png1
-rw-r--r--frontends/gtk/res/netsurf.xpm317
l---------frontends/gtk/res/nl/credits.html1
l---------frontends/gtk/res/nl/licence.html1
l---------frontends/gtk/res/nl/welcome.html1
-rw-r--r--frontends/gtk/res/options.gtk2.ui3004
-rw-r--r--frontends/gtk/res/options.gtk3.ui3057
-rw-r--r--frontends/gtk/res/password.gtk2.ui415
-rw-r--r--frontends/gtk/res/password.gtk3.ui415
l---------frontends/gtk/res/quirks.css1
-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/throbber/throbber0.pngbin0 -> 507 bytes
-rw-r--r--frontends/gtk/res/throbber/throbber1.pngbin0 -> 802 bytes
-rw-r--r--frontends/gtk/res/throbber/throbber2.pngbin0 -> 790 bytes
-rw-r--r--frontends/gtk/res/throbber/throbber3.pngbin0 -> 808 bytes
-rw-r--r--frontends/gtk/res/throbber/throbber4.pngbin0 -> 797 bytes
-rw-r--r--frontends/gtk/res/throbber/throbber5.pngbin0 -> 797 bytes
-rw-r--r--frontends/gtk/res/throbber/throbber6.pngbin0 -> 819 bytes
-rw-r--r--frontends/gtk/res/throbber/throbber7.pngbin0 -> 792 bytes
-rw-r--r--frontends/gtk/res/throbber/throbber8.pngbin0 -> 814 bytes
-rw-r--r--frontends/gtk/res/toolbar.gtk2.ui189
-rw-r--r--frontends/gtk/res/toolbar.gtk3.ui189
-rw-r--r--frontends/gtk/res/viewdata.gtk2.ui204
-rw-r--r--frontends/gtk/res/viewdata.gtk3.ui239
-rw-r--r--frontends/gtk/res/warning.gtk2.ui77
-rw-r--r--frontends/gtk/res/warning.gtk3.ui77
l---------frontends/gtk/res/welcome.html1
-rw-r--r--frontends/gtk/resources.c600
-rw-r--r--frontends/gtk/resources.h109
-rw-r--r--frontends/gtk/scaffolding.c2811
-rw-r--r--frontends/gtk/scaffolding.h252
-rw-r--r--frontends/gtk/schedule.c136
-rw-r--r--frontends/gtk/schedule.h26
-rw-r--r--frontends/gtk/search.c245
-rw-r--r--frontends/gtk/search.h36
-rw-r--r--frontends/gtk/selection.c96
-rw-r--r--frontends/gtk/selection.h24
-rw-r--r--frontends/gtk/sexy_icon_entry.c982
-rw-r--r--frontends/gtk/sexy_icon_entry.h100
-rw-r--r--frontends/gtk/ssl_cert.c135
-rw-r--r--frontends/gtk/ssl_cert.h36
-rw-r--r--frontends/gtk/tabs.c416
-rw-r--r--frontends/gtk/tabs.h42
-rw-r--r--frontends/gtk/throbber.c91
-rw-r--r--frontends/gtk/throbber.h35
-rw-r--r--frontends/gtk/toolbar.c1416
-rw-r--r--frontends/gtk/toolbar.h96
-rw-r--r--frontends/gtk/treeview.c586
-rw-r--r--frontends/gtk/treeview.h38
-rw-r--r--frontends/gtk/viewdata.c990
-rw-r--r--frontends/gtk/viewdata.h48
-rw-r--r--frontends/gtk/viewsource.c82
-rw-r--r--frontends/gtk/viewsource.h25
-rw-r--r--frontends/gtk/warn.h32
-rw-r--r--frontends/gtk/window.c1337
-rw-r--r--frontends/gtk/window.h48
-rw-r--r--frontends/monkey/401login.c55
-rw-r--r--frontends/monkey/401login.h9
-rw-r--r--frontends/monkey/Makefile55
-rw-r--r--frontends/monkey/Makefile.defaults13
-rw-r--r--frontends/monkey/bitmap.c150
-rw-r--r--frontends/monkey/bitmap.h24
-rw-r--r--frontends/monkey/browser.c527
-rw-r--r--frontends/monkey/browser.h48
-rw-r--r--frontends/monkey/cert.c58
-rw-r--r--frontends/monkey/cert.h28
-rw-r--r--frontends/monkey/dispatch.c105
-rw-r--r--frontends/monkey/dispatch.h28
-rw-r--r--frontends/monkey/download.c94
-rw-r--r--frontends/monkey/fetch.c53
-rw-r--r--frontends/monkey/fetch.h24
-rw-r--r--frontends/monkey/filetype.c215
-rw-r--r--frontends/monkey/filetype.h22
-rw-r--r--frontends/monkey/layout.c117
-rw-r--r--frontends/monkey/layout.h24
-rw-r--r--frontends/monkey/main.c398
-rw-r--r--frontends/monkey/options.h43
-rw-r--r--frontends/monkey/plot.c111
-rw-r--r--frontends/monkey/plot.h26
l---------frontends/monkey/res1
-rw-r--r--frontends/monkey/schedule.c223
-rw-r--r--frontends/monkey/schedule.h48
-rw-r--r--frontends/riscos/401login.c236
-rw-r--r--frontends/riscos/Makefile153
-rw-r--r--frontends/riscos/Makefile.defaults37
-rw-r--r--frontends/riscos/assert.c44
-rw-r--r--frontends/riscos/bitmap.c876
-rw-r--r--frontends/riscos/bitmap.h116
-rw-r--r--frontends/riscos/buffer.c396
-rw-r--r--frontends/riscos/buffer.h31
-rw-r--r--frontends/riscos/configure.c410
-rw-r--r--frontends/riscos/configure.h34
-rw-r--r--frontends/riscos/configure/con_cache.c107
-rw-r--r--frontends/riscos/configure/con_connect.c220
-rw-r--r--frontends/riscos/configure/con_content.c107
-rw-r--r--frontends/riscos/configure/con_fonts.c209
-rw-r--r--frontends/riscos/configure/con_home.c118
-rw-r--r--frontends/riscos/configure/con_image.c269
-rw-r--r--frontends/riscos/configure/con_inter.c145
-rw-r--r--frontends/riscos/configure/con_language.c139
-rw-r--r--frontends/riscos/configure/con_secure.c83
-rw-r--r--frontends/riscos/configure/con_theme.c420
-rw-r--r--frontends/riscos/configure/configure.h43
-rw-r--r--frontends/riscos/content-handlers/artworks.c435
-rw-r--r--frontends/riscos/content-handlers/artworks.h42
-rw-r--r--frontends/riscos/content-handlers/awrender.s390
-rw-r--r--frontends/riscos/content-handlers/draw.c254
-rw-r--r--frontends/riscos/content-handlers/draw.h42
-rw-r--r--frontends/riscos/content-handlers/sprite.c266
-rw-r--r--frontends/riscos/content-handlers/sprite.h44
-rw-r--r--frontends/riscos/cookies.c385
-rw-r--r--frontends/riscos/cookies.h38
-rw-r--r--frontends/riscos/dialog.c816
-rw-r--r--frontends/riscos/dialog.h55
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/!Boot,feb17
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/!Help,feb2
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/!Run,feb9
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/!RunImage,ffbbin0 -> 2985 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/!Sprites,ff9bin0 -> 864 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/!Sprites22,ff9bin0 -> 2504 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/Caches/Blank1
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/MultiError,ffbbin0 -> 24031 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/ResFind,ffbbin0 -> 1930 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/!Meta9
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Help60
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Messages8
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Cache/Resources/UK/Templates,fecbin0 -> 541 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/!Boot,feb5
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/!Help1
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/!Run,feb5
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites,ff9bin0 -> 5780 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites11,ff9bin0 -> 11132 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/!Sprites22,ff9bin0 -> 7324 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Acorn/Latin1bin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/CentEurobin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Cyrillicbin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Romanbin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Apple/Ukrainianbin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/BigFivebin0 -> 29516 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C0/40[ISO646]bin0 -> 64 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/C1/43[IS6429]bin0 -> 64 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/40[646old]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/41[646-GB]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/42[646IRV]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/43[FinSwe]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/47[646-SE]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/48[646-SE]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/49[JS201K]1
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4A[JS201R]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4B[646-DE]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/4C[646-PT]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/54[GB1988]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/56[Teltxt]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/59[646-IT]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/5A[646-ES]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/60[646-NO]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/66[646-FR]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/69[646-HU]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6B[Arabic]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/6C[IS6937]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94/7A[SerbCr]bin0 -> 188 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/40[JS6226]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/41[GB2312]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/42[JIS208]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/43[KS1001]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/44[JIS212]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/47[CNS1]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/48[CNS2]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/49[CNS3]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4A[CNS4]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4B[CNS5]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4C[CNS6]bin0 -> 17672 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G94x94/4D[CNS7]2
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/41[Lat1]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/42[Lat2]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/43[Lat3]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/44[Lat4]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/46[Greek]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/47[Arabic]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/48[Hebrew]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4C[Cyrill]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/4D[Lat5]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/50[LatSup]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/52[IS6937]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/54[Thai]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/56[Lat6]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/58[L6Sami]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/59[Lat7]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5C[Welsh]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5D[Sami]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5E[Hebrew]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/5F[Lat8]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/62[Lat9]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/ISO2022/G96/66[Lat10]bin0 -> 192 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/KOI8-Rbin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1250bin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1251bin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1252bin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1253bin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1254bin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP1256bin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP866bin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP874bin0 -> 256 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Encodings/Microsoft/CP932bin0 -> 996 bytes
-rw-r--r--frontends/riscos/distribution/!Boot/Resources/!Unicode/Files/Aliases303
-rw-r--r--frontends/riscos/distribution/!System/310/Modules/CryptRand,ffabin0 -> 15584 bytes
-rw-r--r--frontends/riscos/distribution/!System/310/Modules/Iconv,ffabin0 -> 66240 bytes
-rw-r--r--frontends/riscos/distribution/!System/310/Modules/Network/URI,ffabin0 -> 9188 bytes
-rwxr-xr-xfrontends/riscos/distribution/!System/310/Modules/SharedULib,ffabin0 -> 3116 bytes
-rw-r--r--frontends/riscos/distribution/!System/310/Modules/Tinct,ffabin0 -> 25680 bytes
-rw-r--r--frontends/riscos/distribution/3rdParty/AcornURI/!ReadMe34
-rw-r--r--frontends/riscos/distribution/3rdParty/AcornURI/Copying504
-rw-r--r--frontends/riscos/distribution/3rdParty/CryptRand/Copyright46
-rw-r--r--frontends/riscos/distribution/3rdParty/Iconv/ReadMe45
-rw-r--r--frontends/riscos/distribution/3rdParty/Iconv/doc/API132
-rw-r--r--frontends/riscos/distribution/3rdParty/Iconv/doc/ChangeLog114
-rw-r--r--frontends/riscos/distribution/3rdParty/Iconv/doc/Uni-iconv204
-rw-r--r--frontends/riscos/distribution/3rdParty/SharedULib/Copyright761
-rw-r--r--frontends/riscos/distribution/3rdParty/Tinct/!Help304
-rw-r--r--frontends/riscos/distribution/LeesMij73
-rw-r--r--frontends/riscos/distribution/ReadMe61
-rw-r--r--frontends/riscos/download.c1629
-rw-r--r--frontends/riscos/filetype.c352
-rw-r--r--frontends/riscos/filetype.h128
-rw-r--r--frontends/riscos/font.c598
-rw-r--r--frontends/riscos/font.h45
-rw-r--r--frontends/riscos/global_history.c413
-rw-r--r--frontends/riscos/global_history.h38
-rw-r--r--frontends/riscos/gui.c2522
-rw-r--r--frontends/riscos/gui.h271
-rw-r--r--frontends/riscos/gui/button_bar.c1229
-rw-r--r--frontends/riscos/gui/button_bar.h309
-rw-r--r--frontends/riscos/gui/progress_bar.c535
-rw-r--r--frontends/riscos/gui/progress_bar.h44
-rw-r--r--frontends/riscos/gui/status_bar.c625
-rw-r--r--frontends/riscos/gui/status_bar.h45
-rw-r--r--frontends/riscos/gui/throbber.c418
-rw-r--r--frontends/riscos/gui/throbber.h147
-rw-r--r--frontends/riscos/gui/url_bar.c1344
-rw-r--r--frontends/riscos/gui/url_bar.h329
-rw-r--r--frontends/riscos/help.c361
-rw-r--r--frontends/riscos/help.h33
-rw-r--r--frontends/riscos/history.c336
-rw-r--r--frontends/riscos/hotlist.c737
-rw-r--r--frontends/riscos/hotlist.h53
-rw-r--r--frontends/riscos/iconbar.c261
-rw-r--r--frontends/riscos/iconbar.h32
-rw-r--r--frontends/riscos/image.c219
-rw-r--r--frontends/riscos/image.h39
-rw-r--r--frontends/riscos/menus.c958
-rw-r--r--frontends/riscos/menus.h183
-rw-r--r--frontends/riscos/message.c247
-rw-r--r--frontends/riscos/message.h42
-rw-r--r--frontends/riscos/mouse.c282
-rw-r--r--frontends/riscos/mouse.h110
-rw-r--r--frontends/riscos/options.h68
-rw-r--r--frontends/riscos/oslib_pre7.h42
-rw-r--r--frontends/riscos/palettes.c321
-rw-r--r--frontends/riscos/palettes.h33
-rw-r--r--frontends/riscos/plotters.c525
-rw-r--r--frontends/riscos/print.c976
-rw-r--r--frontends/riscos/print.h33
-rw-r--r--frontends/riscos/query.c381
-rw-r--r--frontends/riscos/query.h53
-rw-r--r--frontends/riscos/save.c1401
-rw-r--r--frontends/riscos/save.h50
-rw-r--r--frontends/riscos/save_draw.c474
-rw-r--r--frontends/riscos/save_draw.h31
-rw-r--r--frontends/riscos/save_pdf.c60
-rw-r--r--frontends/riscos/save_pdf.h31
-rw-r--r--frontends/riscos/schedule.c163
-rw-r--r--frontends/riscos/scripts/Help12
-rw-r--r--frontends/riscos/scripts/Run109
-rw-r--r--frontends/riscos/search.c475
-rw-r--r--frontends/riscos/searchweb.c18
-rw-r--r--frontends/riscos/sslcert.c348
-rw-r--r--frontends/riscos/sslcert.h34
-rw-r--r--frontends/riscos/templates/de3845
-rw-r--r--frontends/riscos/templates/en3837
-rw-r--r--frontends/riscos/templates/fr3862
-rw-r--r--frontends/riscos/templates/nl3887
-rw-r--r--frontends/riscos/textarea.c1160
-rw-r--r--frontends/riscos/textarea.h50
-rw-r--r--frontends/riscos/textselection.c657
-rw-r--r--frontends/riscos/textselection.h53
-rw-r--r--frontends/riscos/theme.c741
-rw-r--r--frontends/riscos/theme.h109
-rw-r--r--frontends/riscos/theme_install.c237
-rw-r--r--frontends/riscos/tinct.h154
-rw-r--r--frontends/riscos/toolbar.c1788
-rw-r--r--frontends/riscos/toolbar.h542
-rw-r--r--frontends/riscos/treeview.c1279
-rw-r--r--frontends/riscos/treeview.h55
-rw-r--r--frontends/riscos/ucstables.c697
-rw-r--r--frontends/riscos/ucstables.h29
-rw-r--r--frontends/riscos/uri.c139
-rw-r--r--frontends/riscos/uri.h30
-rw-r--r--frontends/riscos/url_complete.c740
-rw-r--r--frontends/riscos/url_complete.h100
-rw-r--r--frontends/riscos/url_protocol.c226
-rw-r--r--frontends/riscos/url_protocol.h35
-rw-r--r--frontends/riscos/url_suggest.c239
-rw-r--r--frontends/riscos/url_suggest.h38
-rw-r--r--frontends/riscos/wimp.c1134
-rw-r--r--frontends/riscos/wimp.h83
-rw-r--r--frontends/riscos/wimp_event.c1814
-rw-r--r--frontends/riscos/wimp_event.h116
-rw-r--r--frontends/riscos/wimputils.h65
-rw-r--r--frontends/riscos/window.c5025
-rw-r--r--frontends/riscos/window.h46
-rw-r--r--frontends/windows/Makefile75
-rw-r--r--frontends/windows/Makefile.defaults25
-rw-r--r--frontends/windows/about.c151
-rw-r--r--frontends/windows/about.h24
-rw-r--r--frontends/windows/bitmap.c387
-rw-r--r--frontends/windows/bitmap.h40
-rw-r--r--frontends/windows/download.c346
-rw-r--r--frontends/windows/download.h37
-rw-r--r--frontends/windows/drawable.c625
-rw-r--r--frontends/windows/drawable.h25
-rw-r--r--frontends/windows/file.c302
-rw-r--r--frontends/windows/file.h29
-rw-r--r--frontends/windows/filetype.c60
-rw-r--r--frontends/windows/filetype.h24
-rw-r--r--frontends/windows/findfile.c156
-rw-r--r--frontends/windows/findfile.h26
-rw-r--r--frontends/windows/font.c298
-rw-r--r--frontends/windows/font.h53
-rw-r--r--frontends/windows/gui.c170
-rw-r--r--frontends/windows/gui.h58
-rw-r--r--frontends/windows/localhistory.c401
-rw-r--r--frontends/windows/localhistory.h32
-rw-r--r--frontends/windows/main.c271
-rw-r--r--frontends/windows/plot.c868
-rw-r--r--frontends/windows/plot.h24
-rw-r--r--frontends/windows/pointers.c128
-rw-r--r--frontends/windows/pointers.h40
-rw-r--r--frontends/windows/prefs.c680
-rw-r--r--frontends/windows/prefs.h24
-rw-r--r--frontends/windows/res/NetSurf.icobin0 -> 18614 bytes
l---------frontends/windows/res/adblock.css1
-rw-r--r--frontends/windows/res/banner.bmpbin0 -> 79518 bytes
l---------frontends/windows/res/ca-bundle.crt1
l---------frontends/windows/res/credits.html1
l---------frontends/windows/res/default.css1
-rw-r--r--frontends/windows/res/home.bmpbin0 -> 2358 bytes
-rw-r--r--frontends/windows/res/icons/back.pngbin0 -> 653 bytes
-rw-r--r--frontends/windows/res/icons/back_g.pngbin0 -> 306 bytes
-rw-r--r--frontends/windows/res/icons/back_h.pngbin0 -> 607 bytes
-rw-r--r--frontends/windows/res/icons/forward.pngbin0 -> 697 bytes
-rw-r--r--frontends/windows/res/icons/forward_g.pngbin0 -> 538 bytes
-rw-r--r--frontends/windows/res/icons/forward_h.pngbin0 -> 635 bytes
-rw-r--r--frontends/windows/res/icons/home.pngbin0 -> 745 bytes
-rw-r--r--frontends/windows/res/icons/home_g.pngbin0 -> 576 bytes
-rw-r--r--frontends/windows/res/icons/home_h.pngbin0 -> 751 bytes
-rw-r--r--frontends/windows/res/icons/reload.pngbin0 -> 1062 bytes
-rw-r--r--frontends/windows/res/icons/reload_g.pngbin0 -> 814 bytes
-rw-r--r--frontends/windows/res/icons/reload_h.pngbin0 -> 1046 bytes
-rw-r--r--frontends/windows/res/icons/stop.pngbin0 -> 1135 bytes
-rw-r--r--frontends/windows/res/icons/stop_g.pngbin0 -> 850 bytes
-rw-r--r--frontends/windows/res/icons/stop_h.pngbin0 -> 1119 bytes
-rw-r--r--frontends/windows/res/installer.nsi141
l---------frontends/windows/res/internal.css1
l---------frontends/windows/res/licence.html1
-rw-r--r--frontends/windows/res/netsurf.gifbin0 -> 14119 bytes
l---------frontends/windows/res/netsurf.png1
l---------frontends/windows/res/quirks.css1
-rw-r--r--frontends/windows/res/resource.rc265
-rw-r--r--frontends/windows/res/throbber.avibin0 -> 23980 bytes
-rw-r--r--frontends/windows/res/throbber/throbber0.bmpbin0 -> 1866 bytes
-rwxr-xr-xfrontends/windows/res/throbber/throbber0.pngbin0 -> 730 bytes
-rw-r--r--frontends/windows/res/throbber/throbber1.bmpbin0 -> 1866 bytes
-rwxr-xr-xfrontends/windows/res/throbber/throbber1.pngbin0 -> 928 bytes
-rw-r--r--frontends/windows/res/throbber/throbber2.bmpbin0 -> 1866 bytes
-rwxr-xr-xfrontends/windows/res/throbber/throbber2.pngbin0 -> 906 bytes
-rw-r--r--frontends/windows/res/throbber/throbber3.bmpbin0 -> 1866 bytes
-rwxr-xr-xfrontends/windows/res/throbber/throbber3.pngbin0 -> 917 bytes
-rw-r--r--frontends/windows/res/throbber/throbber4.bmpbin0 -> 1866 bytes
-rwxr-xr-xfrontends/windows/res/throbber/throbber4.pngbin0 -> 927 bytes
-rw-r--r--frontends/windows/res/throbber/throbber5.bmpbin0 -> 1866 bytes
-rwxr-xr-xfrontends/windows/res/throbber/throbber5.pngbin0 -> 923 bytes
-rw-r--r--frontends/windows/res/throbber/throbber6.bmpbin0 -> 1866 bytes
-rwxr-xr-xfrontends/windows/res/throbber/throbber6.pngbin0 -> 904 bytes
-rw-r--r--frontends/windows/res/throbber/throbber7.bmpbin0 -> 1866 bytes
-rwxr-xr-xfrontends/windows/res/throbber/throbber7.pngbin0 -> 940 bytes
-rwxr-xr-xfrontends/windows/res/throbber/throbber8.pngbin0 -> 921 bytes
-rw-r--r--frontends/windows/res/toolbar.bmpbin0 -> 8694 bytes
-rw-r--r--frontends/windows/res/toolbarg.bmpbin0 -> 8694 bytes
-rw-r--r--frontends/windows/res/toolbarh.bmpbin0 -> 8694 bytes
l---------frontends/windows/res/welcome.html1
-rw-r--r--frontends/windows/resourceid.h138
-rw-r--r--frontends/windows/schedule.c235
-rw-r--r--frontends/windows/schedule.h65
-rw-r--r--frontends/windows/windbg.c663
-rw-r--r--frontends/windows/windbg.h34
-rw-r--r--frontends/windows/window.c1741
-rw-r--r--frontends/windows/window.h109
1076 files changed, 215611 insertions, 0 deletions
diff --git a/frontends/Makefile b/frontends/Makefile
new file mode 100644
index 000000000..da6fe2019
--- /dev/null
+++ b/frontends/Makefile
@@ -0,0 +1,9 @@
+# NetSurf Frontend sources
+
+FRONTEND_SOURCE_DIR := frontends/$(TARGET)
+FRONTEND_RESOURCES_DIR := frontends/$(TARGET)/res
+
+# Target Specific setup
+include frontends/$(TARGET)/Makefile
+
+S_FRONTEND := $(addprefix frontends/$(TARGET)/,$(S_FRONTEND))
diff --git a/frontends/amiga/Makefile b/frontends/amiga/Makefile
new file mode 100644
index 000000000..a5e9d1c1f
--- /dev/null
+++ b/frontends/amiga/Makefile
@@ -0,0 +1,122 @@
+# ----------------------------------------------------------------------------
+# Amiga target setup
+# ----------------------------------------------------------------------------
+
+CFLAGS += -std=c99 -Dnsamiga
+
+ifneq ($(SUBTARGET),os3)
+ CFLAGS += -O2 -finline-functions -U__STRICT_ANSI__ -D__USE_INLINE__ -D__USE_BASETYPE__
+else
+ CFLAGS += -msoft-float -m68020-60 -O2 -DPATH_MAX=1024 -D__m68k__
+endif
+
+NETSURF_FEATURE_ROSPRITE_CFLAGS := -DWITH_NSSPRITE
+NETSURF_FEATURE_BMP_CFLAGS := -DWITH_BMP
+NETSURF_FEATURE_GIF_CFLAGS := -DWITH_GIF
+NETSURF_FEATURE_PNG_CFLAGS := -DWITH_PNG
+NETSURF_FEATURE_NSSVG_CFLAGS := -DWITH_NS_SVG
+NETSURF_FEATURE_VIDEO_CFLAGS := -DWITH_VIDEO
+
+ifeq ($(HOST),amiga)
+ $(eval $(call feature_enabled,ROSPRITE,-DWITH_NSSPRITE,-lrosprite,Sprite (librosprite)))
+ $(eval $(call feature_enabled,BMP,-DWITH_BMP,-lnsbmp,BMP (libnsbmp)))
+ $(eval $(call feature_enabled,GIF,-DWITH_GIF,-lnsgif,GIF (libnsgif)))
+ $(eval $(call feature_enabled,PNG,-DWITH_PNG,-lpng,PNG (libpng) ))
+ $(eval $(call feature_enabled,NSSVG,-DWITH_NS_SVG,-lsvgtiny,SVG (libsvgtiny)))
+ $(eval $(call feature_enabled,VIDEO,-DWITH_VIDEO -I /SDK/local/newlib/include/glib-2.0,-lgstreamer-0.10 -lglib-2.0 -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lintl -lffi,Video (libgstreamer)))
+ $(eval $(call feature_enabled,JS,-DXP_UNIX -DWITH_JS -DJS_VERSION=185,-lstdc++ -lmozjs185,JavaScript))
+ $(eval $(call feature_enabled,MOZJS,-DXP_AMIGA -DWITH_MOZJS -DJS_VERSION=170 -DJSVERSION_LATEST=170 -DJSOPTION_JIT=0 -DJSCLASS_GLOBAL_FLAGS=0,-ljs -lfdlibm,JavaScript))
+ $(eval $(call feature_enabled,AMIGA_ICON,-DWITH_AMIGA_ICON,,Amiga icon))
+ $(eval $(call feature_enabled,AMIGA_DATATYPES,-DWITH_AMIGA_DATATYPES,,DataTypes))
+
+ CFLAGS += -I /SDK/local/common/include/libpng12
+ LDFLAGS += -lcurl -lrtmp -lpthread -ltre -lintl -lpbl
+ LDFLAGS += -lssl -lcrypto -ldom -lhubbub -lcss -lparserutils -lwapcaplet
+else
+ $(eval $(call feature_enabled,AMIGA_ICON,-DWITH_AMIGA_ICON,,Amiga icon))
+ $(eval $(call feature_enabled,AMIGA_DATATYPES,-DWITH_AMIGA_DATATYPES,,DataTypes))
+
+ CFLAGS += -I$(GCCSDK_INSTALL_ENV)/include
+ CFLAGS += $(shell $(PKG_CONFIG) --cflags tre)
+
+ LDFLAGS += $(shell $(PKG_CONFIG) --static --libs libcurl openssl)
+ LDFLAGS += $(shell $(PKG_CONFIG) --libs tre)
+ LDFLAGS += -L$(GCCSDK_INSTALL_ENV)/lib
+
+ LDFLAGS += -lpbl -liconv
+
+ ifeq ($(SUBTARGET),os3)
+ LDFLAGS += -lamiga -lm
+ endif
+endif
+
+EXETARGET := NetSurf
+
+# The filter and target for split messages
+MESSAGES_FILTER=ami
+
+# ----------------------------------------------------------------------------
+# Source file setup
+# ----------------------------------------------------------------------------
+
+# sources purely for the Amiga build
+S_FRONTEND := gui.c tree.c history.c hotlist.c schedule.c file.c \
+ misc.c bitmap.c font.c filetype.c utf8.c login.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 \
+ 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
+
+# This is the final source build list
+# Note this is deliberately *not* expanded here as common and image
+# are not yet available
+SOURCES = $(S_COMMON) $(S_IMAGE) $(S_BROWSER) $(S_FRONTEND)
+
+# ----------------------------------------------------------------------------
+# Install target
+# ----------------------------------------------------------------------------
+
+install-amiga:
+
+# ----------------------------------------------------------------------------
+# Package target
+# ----------------------------------------------------------------------------
+
+package-amiga: netsurf.lha
+
+AMIGA_LANGUAGES := de en it ja nl
+AMIGA_PLATFORM_RESOURCES := Pointers Themes default.css default.css.info favicon.png LangNames mimetypes Resource.map SearchEngines splash.png
+AMIGA_GENERIC_RESOURCES := $(AMIGA_LANGUAGES) ca-bundle Icons
+AMIGA_RESOURCES := $(addprefix $(FRONTEND_SOURCE_DIR)/resources/,$(AMIGA_PLATFORM_RESOURCES)) $(addprefix \!NetSurf/Resources/,$(AMIGA_GENERIC_RESOURCES))
+AMIGA_DISTRIBUTION_FILES := $(FRONTEND_SOURCE_DIR)/dist/*
+AMIGA_INSTALL_TARGET_DIR := NetSurf_Amiga
+
+netsurf.lha: $(EXETARGET)
+ $(VQ)echo Creating netsurf.lha
+ $(Q)rm -rf $(AMIGA_INSTALL_TARGET_DIR)
+ $(Q)mkdir -p $(AMIGA_INSTALL_TARGET_DIR)/NetSurf
+ $(Q)cp -p $(EXETARGET) $(AMIGA_INSTALL_TARGET_DIR)/NetSurf
+ $(Q)mkdir $(AMIGA_INSTALL_TARGET_DIR)/NetSurf/Resources
+ $(Q)cp -r $(AMIGA_RESOURCES) $(AMIGA_INSTALL_TARGET_DIR)/NetSurf/Resources
+ $(Q)cp -r $(AMIGA_DISTRIBUTION_FILES) $(AMIGA_INSTALL_TARGET_DIR)/NetSurf
+ $(Q)cp \!NetSurf/Resources/AdBlock,f79 $(AMIGA_INSTALL_TARGET_DIR)/NetSurf/Resources/adblock.css
+ $(Q)cp \!NetSurf/Resources/CSS,f79 $(AMIGA_INSTALL_TARGET_DIR)/NetSurf/Resources/nsdefault.css
+ $(Q)cp \!NetSurf/Resources/internal.css,f79 $(AMIGA_INSTALL_TARGET_DIR)/NetSurf/Resources/internal.css
+ $(Q)cp \!NetSurf/Resources/Quirks,f79 $(AMIGA_INSTALL_TARGET_DIR)/NetSurf/Resources/quirks.css
+ $(Q)cp \!NetSurf/Resources/netsurf.png,b60 $(AMIGA_INSTALL_TARGET_DIR)/NetSurf/Resources/netsurf.png
+ $(Q)cp amiga/pkg/drawer.info $(AMIGA_INSTALL_TARGET_DIR)/NetSurf.info
+ $(Q)cp amiga/pkg/AutoInstall $(AMIGA_INSTALL_TARGET_DIR)
+ ifeq ($(SUBTARGET),os3)
+ $(Q)cp amiga/pkg/netsurf_os3.readme $(AMIGA_INSTALL_TARGET_DIR)/NetSurf
+ $(Q)cp amiga/pkg/netsurf_os3.readme.info $(AMIGA_INSTALL_TARGET_DIR)/NetSurf
+ else
+ $(Q)cp amiga/pkg/netsurf.readme $(AMIGA_INSTALL_TARGET_DIR)/NetSurf
+ $(Q)cp amiga/pkg/netsurf.readme.info $(AMIGA_INSTALL_TARGET_DIR)/NetSurf
+ endif
+ $(Q)cd $(AMIGA_INSTALL_TARGET_DIR); \
+ lha a netsurf.lha NetSurf NetSurf.info AutoInstall
+
diff --git a/frontends/amiga/Makefile.defaults b/frontends/amiga/Makefile.defaults
new file mode 100644
index 000000000..0674a9de2
--- /dev/null
+++ b/frontends/amiga/Makefile.defaults
@@ -0,0 +1,42 @@
+# ----------------------------------------------------------------------------
+# Amiga-specific options
+# ----------------------------------------------------------------------------
+
+# Force using glibc internal iconv implementation instead of external libiconv
+# Valid options: YES, NO
+ifneq ($(SUBTARGET),os3)
+ NETSURF_USE_LIBICONV_PLUG := YES
+else
+ NETSURF_USE_LIBICONV_PLUG := NO
+endif
+
+# Enable NetSurf's use of librosprite for displaying RISC OS Sprites
+# Valid options: YES, NO, AUTO
+NETSURF_USE_ROSPRITE := NO
+
+# Enable NetSurf to display Amiga icons
+# Valid options: YES, NO (recommended)
+NETSURF_USE_AMIGA_ICON := YES
+
+# Enable NetSurf's use of DataTypes for unknown filetypes
+# Valid options: YES, NO
+NETSURF_USE_AMIGA_DATATYPES := YES
+
+# Enable NetSurf's use of libsvgtiny for displaying SVGs
+# Valid options: YES, NO
+NETSURF_USE_NSSVG := YES
+
+# Enable NetSurf's use of Spidermonkey 1.80+
+# Only here to stop the build complaining;
+# enable NETSURF_USE_MOZJS instead for JavaScript support
+# Valid options: NO
+NETSURF_USE_JS := NO
+
+# Enable building the source object cache filesystem based backing store.
+# implementation.
+# Valid options: YES, NO
+NETSURF_FS_BACKING_STORE := YES
+
+# Optimisation levels
+CFLAGS += -fomit-frame-pointer -gstabs
+
diff --git a/frontends/amiga/agclass/amigaguide_class.c b/frontends/amiga/agclass/amigaguide_class.c
new file mode 100644
index 000000000..2b80223ca
--- /dev/null
+++ b/frontends/amiga/agclass/amigaguide_class.c
@@ -0,0 +1,394 @@
+/*
+ * AmigaGuide Class
+ * A BOOPSI class for displaying AmigaGuide files.
+ * by Daniel "Trixie" Jedlicka
+ */
+
+#include "amiga/os3support.h"
+#include "amigaguide_class.h"
+
+#ifdef __amigaos4__
+#define DISPATCHHOOK(func) static uint32 func(Class *cl, Object *o, Msg msg)
+#else
+#define DISPATCHHOOK(func) static ASM uint32 func(REG(a0, Class *cl),REG(a2, Object *o), REG(a1, Msg msg))
+#endif
+
+struct localObjectData
+{
+ struct NewAmigaGuide nag;
+ struct AmigaGuideMsg *agm;
+ AMIGAGUIDECONTEXT agHandle;
+ uint32 agContextID;
+ uint32 agSignal;
+};
+
+struct Library *AmigaGuideBase = NULL;
+struct AmigaGuideIFace *IAmigaGuide = NULL;
+
+
+/* ********************************** function prototypes ************************************ */
+
+DISPATCHHOOK(dispatchAGClass);
+
+
+// class methods
+uint32 om_new(Class *, Object *, struct opSet *);
+uint32 om_dispose(Class *, Object *, Msg);
+uint32 om_set(Class *, Object *, struct opSet *);
+uint32 om_get(Class *, Object *, struct opGet *);
+uint32 agm_open(Class *, Object *, Msg);
+uint32 agm_close(Class *, Object *, Msg);
+uint32 agm_process(Class *, Object *, Msg);
+
+
+/* *************************** class initialization and disposal ***************************** */
+
+
+Class *initAGClass(void)
+{
+ Class *cl = NULL;
+
+
+ // Open amigaguide.library and its interface.
+ if ( (AmigaGuideBase = OpenLibrary("amigaguide.library", 40)) )
+ {
+#ifdef __amigaos4__
+ if ( (IAmigaGuide = (struct AmigaGuideIFace *)GetInterface(AmigaGuideBase, "main", 1L, NULL)) )
+ {
+#endif
+ if ( (cl = MakeClass(NULL, "rootclass", NULL, sizeof(struct localObjectData), 0)) )
+ {
+ cl->cl_Dispatcher.h_Entry = (HOOKFUNC)dispatchAGClass;
+ AddClass(cl);
+ }
+ else freeAGClass(NULL);
+#ifdef __amigaos4__
+ }
+ else freeAGClass(NULL);
+#endif
+ }
+
+ return cl;
+
+}
+
+
+
+BOOL freeAGClass(Class *cl)
+{
+ BOOL retVal = FALSE;
+
+
+ // Close amigaguide.library and free the class.
+#ifdef __amigaos4__
+ if (IAmigaGuide) DropInterface((struct Interface *)IAmigaGuide);
+#endif
+ if (AmigaGuideBase) CloseLibrary(AmigaGuideBase);
+ if (cl) retVal = FreeClass(cl);
+
+ return retVal;
+}
+
+
+
+/* ************************************** class dispatcher ************************************ */
+
+
+DISPATCHHOOK(dispatchAGClass)
+{
+
+ switch (msg->MethodID)
+ {
+ case OM_NEW:
+ return om_new(cl, o, (struct opSet *)msg);
+
+ case OM_DISPOSE:
+ return om_dispose(cl, o, msg);
+
+ case OM_UPDATE:
+ case OM_SET:
+ return om_set(cl, o, (struct opSet *)msg);
+
+ case OM_GET:
+ return om_get(cl, o, (struct opGet *)msg);
+
+ case AGM_OPEN:
+ return agm_open(cl, o, msg);
+
+ case AGM_CLOSE:
+ return agm_close(cl, o, msg);
+
+ case AGM_PROCESS:
+ return agm_process(cl, o, msg);
+
+ default:
+ return IDoSuperMethodA(cl, o, msg);
+ }
+
+}
+
+
+/* *************************************** class methods ************************************** */
+
+uint32 om_new(Class *cl, Object *o, struct opSet *msg)
+{
+ struct localObjectData *lod = NULL;
+ uint32 retVal = 0L;
+
+
+ if ( (retVal = IDoSuperMethodA(cl, o, (Msg)msg)) )
+ {
+ // Obtain pointer to our object's local instance data.
+ if ( (lod = (struct localObjectData *)INST_DATA(cl, retVal)) )
+ {
+ // Initialize values.
+ lod->agHandle = NULL;
+ lod->agContextID = 0;
+ lod->nag.nag_Name = NULL;
+ lod->nag.nag_Screen = NULL;
+ lod->nag.nag_PubScreen = NULL;
+ lod->nag.nag_BaseName = NULL;
+ lod->nag.nag_Context = NULL;
+ lod->nag.nag_Client = NULL; // private, must be NULL!
+
+ // Set initial object attributes based on the tags from NewObject().
+ om_set(cl, (Object *)retVal, msg);
+ }
+ }
+
+ return retVal;
+
+}
+
+
+
+
+
+uint32 om_dispose(Class *cl, Object *o, Msg msg)
+{
+
+ // Close the document, should it still be opened.
+ agm_close(cl, o, msg);
+
+ // Let superclass dispose of the object.
+ return IDoSuperMethodA(cl, o, msg);
+
+}
+
+
+
+
+
+uint32 om_set(Class *cl, Object *o, struct opSet *msg)
+{
+ struct localObjectData *lod = (struct localObjectData *)INST_DATA(cl, o);
+ struct TagItem *ti = NULL, *tags = msg->ops_AttrList;
+ uint32 retVal = 0L;
+
+
+ while ((ti = NextTagItem (&tags)))
+ {
+ switch (ti->ti_Tag)
+ {
+ case AMIGAGUIDE_Name:
+ lod->nag.nag_Name = (STRPTR)ti->ti_Data;
+ retVal++;
+ break;
+
+ case AMIGAGUIDE_Screen:
+ lod->nag.nag_Screen = (struct Screen *)ti->ti_Data;
+ retVal++;
+ break;
+
+ case AMIGAGUIDE_PubScreen:
+ lod->nag.nag_PubScreen = (STRPTR)ti->ti_Data;
+ retVal++;
+ break;
+
+ case AMIGAGUIDE_BaseName:
+ lod->nag.nag_BaseName = (STRPTR)ti->ti_Data;
+ retVal++;
+ break;
+
+ case AMIGAGUIDE_ContextArray:
+ lod->nag.nag_Context = (STRPTR *)ti->ti_Data;
+ retVal++;
+ break;
+
+ case AMIGAGUIDE_ContextID:
+ lod->agContextID = (uint32)ti->ti_Data;
+ retVal++;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return retVal;
+
+}
+
+
+
+
+
+uint32 om_get(Class *cl, Object *o, struct opGet *msg)
+{
+ struct localObjectData *lod = (struct localObjectData *)INST_DATA(cl, o);
+ uint32 retVal = 0L;
+
+
+ switch (msg->opg_AttrID)
+ {
+ case AMIGAGUIDE_Name:
+ *(msg->opg_Storage) = (uint32)lod->nag.nag_Name;
+ retVal = 1L;
+ break;
+
+ case AMIGAGUIDE_Screen:
+ *(msg->opg_Storage) = (uint32)lod->nag.nag_Screen;
+ retVal = 1L;
+ break;
+
+ case AMIGAGUIDE_PubScreen:
+ *(msg->opg_Storage) = (uint32)lod->nag.nag_PubScreen;
+ retVal = 1L;
+ break;
+
+ case AMIGAGUIDE_BaseName:
+ *(msg->opg_Storage) = (uint32)lod->nag.nag_BaseName;
+ retVal = 1L;
+ break;
+
+ case AMIGAGUIDE_ContextArray:
+ *(msg->opg_Storage) = (uint32)lod->nag.nag_Context;
+ retVal = 1L;
+ break;
+
+ case AMIGAGUIDE_ContextID:
+ *(msg->opg_Storage) = (uint32)lod->agContextID;
+ retVal = 1L;
+ break;
+
+ case AMIGAGUIDE_Signal:
+ *(msg->opg_Storage) = (uint32)lod->agSignal;
+ retVal = 1L;
+ break;
+
+ default:
+ retVal = IDoSuperMethodA(cl, o, (Msg)msg);
+ }
+
+ return retVal;
+
+}
+
+
+
+
+
+uint32 agm_open(Class *cl, Object *o, Msg msg)
+{
+ struct localObjectData *lod = (struct localObjectData *)INST_DATA(cl, o);
+ BOOL agActive = FALSE;
+ uint32 retVal = 0L;
+
+
+ // Close a previous instance.
+ if ( lod->agHandle ) agm_close(cl, o, msg);
+
+ // (Re)establish the AmigaGuide context and open the database asynchronously.
+ if ( (lod->agHandle = OpenAmigaGuideAsync(&(lod->nag), NULL)) )
+ {
+ if ( (lod->agSignal = AmigaGuideSignal(lod->agHandle)) )
+ {
+ // Wait until the database is displayed and ready.
+ Wait(lod->agSignal);
+ while ( agActive == FALSE )
+ {
+ while ( (lod->agm = GetAmigaGuideMsg(lod->agHandle)) )
+ {
+ // The AmigaGuide process started OK.
+ if ( lod->agm->agm_Type == ActiveToolID ) agActive = TRUE;
+
+ // Opening the guide file failed for some reason, continue as usual.
+ if ( lod->agm->agm_Type == ToolStatusID && lod->agm->agm_Pri_Ret ) agActive = TRUE;
+
+ ReplyAmigaGuideMsg(lod->agm);
+ }
+ }
+ if ( lod->nag.nag_Context )
+ {
+ // A context node array is provided = open the current context node.
+ SetAmigaGuideContext(lod->agHandle, lod->agContextID, NULL);
+ retVal = SendAmigaGuideContext(lod->agHandle, NULL);
+ }
+ else
+ {
+ // No context array is provided = open the main node.
+ retVal = SendAmigaGuideCmd(lod->agHandle, "LINK MAIN", TAG_DONE);
+ }
+ }
+ }
+
+
+ return retVal;
+}
+
+
+
+
+
+uint32 agm_close(Class *cl, Object *o, Msg msg)
+{
+ struct localObjectData *lod = (struct localObjectData *)INST_DATA(cl, o);
+ uint32 retVal = 0L;
+
+
+ if ( lod->agHandle )
+ {
+ CloseAmigaGuide(lod->agHandle);
+ lod->agHandle = NULL;
+ lod->agSignal = 0;
+ retVal = 1L;
+ }
+
+ return retVal;
+
+}
+
+
+
+
+
+
+uint32 agm_process(Class *cl, Object *o, Msg msg)
+{
+ struct localObjectData *lod = (struct localObjectData *)INST_DATA(cl, o);
+ uint32 retVal = 0L;
+
+
+ if (lod->agHandle)
+ {
+ while ( (lod->agm = GetAmigaGuideMsg(lod->agHandle)) )
+ {
+ switch (lod->agm->agm_Type)
+ {
+ case ShutdownMsgID:
+ agm_close(cl, o, msg);
+ retVal = 1L;
+ break;
+
+ default:
+ //printf("%d\n", lod->agm->agm_Type);
+ break;
+ }
+ ReplyAmigaGuideMsg(lod->agm);
+ }
+ }
+
+ return retVal;
+
+}
+
diff --git a/frontends/amiga/agclass/amigaguide_class.h b/frontends/amiga/agclass/amigaguide_class.h
new file mode 100755
index 000000000..ee7e55e60
--- /dev/null
+++ b/frontends/amiga/agclass/amigaguide_class.h
@@ -0,0 +1,43 @@
+/*
+ * AmigaGuide Class
+ *
+ */
+
+#ifndef AMIGAGUIDE_CLASS_H
+#define AMIGAGUIDE_CLASS_H
+
+#include <exec/types.h>
+#include <intuition/classes.h>
+
+#include <classes/window.h>
+
+#include <proto/exec.h>
+#include <proto/intuition.h>
+#include <proto/amigaguide.h>
+#include <proto/utility.h>
+
+
+
+// tag definitions
+#define AMIGAGUIDE_Dummy (TAG_USER+0x05000000)
+
+#define AMIGAGUIDE_Name (AMIGAGUIDE_Dummy + 1) // Name of the AmigaGuide database.
+#define AMIGAGUIDE_Screen (AMIGAGUIDE_Dummy + 2) // Pointer of the screen to open on.
+#define AMIGAGUIDE_PubScreen (AMIGAGUIDE_Dummy + 3) // Name of the public screen to open on.
+#define AMIGAGUIDE_BaseName (AMIGAGUIDE_Dummy + 4) // Basename of the application that opens the help file.
+#define AMIGAGUIDE_ContextArray (AMIGAGUIDE_Dummy + 5) // Context node array (must be NULL-terminated).
+#define AMIGAGUIDE_ContextID (AMIGAGUIDE_Dummy + 6) // Index value of the node to display.
+#define AMIGAGUIDE_Signal (AMIGAGUIDE_Dummy + 7) // Signal mask to wait on
+
+// method definition
+#define AGM_Dummy AMIGAGUIDE_Dummy + 100
+#define AGM_OPEN AGM_Dummy + 1
+#define AGM_CLOSE AGM_Dummy + 2
+#define AGM_PROCESS AGM_Dummy + 3
+
+// function prototypes
+Class *initAGClass(void);
+BOOL freeAGClass(Class *);
+
+#endif // AMIGAGUIDE_CLASS_H
+
diff --git a/frontends/amiga/arexx.c b/frontends/amiga/arexx.c
new file mode 100644
index 000000000..c5b5ab42d
--- /dev/null
+++ b/frontends/amiga/arexx.c
@@ -0,0 +1,636 @@
+/*
+ * Copyright 2008-2010 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 <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <proto/intuition.h>
+#include <proto/dos.h>
+#include <proto/exec.h>
+#include <proto/clicktab.h>
+#include <gadgets/clicktab.h>
+#include <reaction/reaction_macros.h>
+
+#include "utils/utils.h"
+#include "utils/log.h"
+#include "utils/nsoption.h"
+#include "utils/nsurl.h"
+#include "content/hlcache.h"
+#include "desktop/browser.h"
+#include "desktop/gui_window.h"
+#include "desktop/version.h"
+
+#include "amiga/arexx.h"
+#include "amiga/download.h"
+#include "amiga/gui.h"
+#include "amiga/hotlist.h"
+#include "amiga/libs.h"
+#include "amiga/misc.h"
+#include "amiga/theme.h"
+
+extern const char * const verarexx;
+extern const char * const wt_revid;
+
+enum
+{
+ RX_OPEN=0,
+ RX_QUIT,
+ RX_TOFRONT,
+ RX_GETURL,
+ RX_GETTITLE,
+ RX_VERSION,
+ RX_SAVE,
+ RX_PUBSCREEN,
+ RX_BACK,
+ RX_FORWARD,
+ RX_HOME,
+ RX_RELOAD,
+ RX_WINDOWS,
+ RX_ACTIVE,
+ RX_CLOSE,
+ RX_HOTLIST
+};
+
+STATIC char result[100];
+
+STATIC VOID rx_open(struct ARexxCmd *, struct RexxMsg *);
+STATIC VOID rx_quit(struct ARexxCmd *, struct RexxMsg *);
+STATIC VOID rx_tofront(struct ARexxCmd *, struct RexxMsg *);
+STATIC VOID rx_geturl(struct ARexxCmd *, struct RexxMsg *);
+STATIC VOID rx_gettitle(struct ARexxCmd *, struct RexxMsg *);
+STATIC VOID rx_version(struct ARexxCmd *, struct RexxMsg *);
+STATIC VOID rx_save(struct ARexxCmd *, struct RexxMsg *);
+STATIC VOID rx_pubscreen(struct ARexxCmd *, struct RexxMsg *);
+STATIC VOID rx_back(struct ARexxCmd *, struct RexxMsg *);
+STATIC VOID rx_forward(struct ARexxCmd *, struct RexxMsg *);
+STATIC VOID rx_home(struct ARexxCmd *, struct RexxMsg *);
+STATIC VOID rx_reload(struct ARexxCmd *, struct RexxMsg *);
+STATIC VOID rx_windows(struct ARexxCmd *, struct RexxMsg *);
+STATIC VOID rx_active(struct ARexxCmd *, struct RexxMsg *);
+STATIC VOID rx_close(struct ARexxCmd *, struct RexxMsg *);
+STATIC VOID rx_hotlist(struct ARexxCmd *, struct RexxMsg *);
+
+STATIC struct ARexxCmd Commands[] =
+{
+ {"OPEN",RX_OPEN,rx_open,"URL/A,NEW=NEWWINDOW/S,NEWTAB/S,SAVEAS/K,W=WINDOW/K/N,T=TAB/K/N", 0, NULL, 0, 0, NULL },
+ {"QUIT",RX_QUIT,rx_quit,NULL, 0, NULL, 0, 0, NULL },
+ {"TOFRONT",RX_TOFRONT,rx_tofront,NULL, 0, NULL, 0, 0, NULL },
+ {"GETURL",RX_GETURL,rx_geturl, "W=WINDOW/K/N,T=TAB/K/N", 0, NULL, 0, 0, NULL },
+ {"GETTITLE",RX_GETTITLE,rx_gettitle, "W=WINDOW/K/N,T=TAB/K/N", 0, NULL, 0, 0, NULL },
+ {"VERSION",RX_VERSION,rx_version,"VERSION/N,SVN=REVISION/N,RELEASE/S", 0, NULL, 0, 0, NULL },
+ {"SAVE",RX_SAVE,rx_save,"FILENAME/A,W=WINDOW/K/N,T=TAB/K/N", 0, NULL, 0, 0, NULL },
+ {"GETSCREENNAME",RX_PUBSCREEN,rx_pubscreen,NULL, 0, NULL, 0, 0, NULL },
+ {"BACK", RX_BACK, rx_back, "W=WINDOW/K/N,T=TAB/K/N", 0, NULL, 0, 0, NULL },
+ {"FORWARD", RX_FORWARD, rx_forward, "W=WINDOW/K/N,T=TAB/K/N", 0, NULL, 0, 0, NULL },
+ {"HOME", RX_HOME, rx_home, "W=WINDOW/K/N,T=TAB/K/N", 0, NULL, 0, 0, NULL },
+ {"RELOAD", RX_RELOAD, rx_reload, "FORCE/S,W=WINDOW/K/N,T=TAB/K/N", 0, NULL, 0, 0, NULL },
+ {"WINDOWS", RX_WINDOWS, rx_windows, "W=WINDOW/K/N", 0, NULL, 0, 0, NULL },
+ {"ACTIVE", RX_ACTIVE, rx_active, "T=TAB/S", 0, NULL, 0, 0, NULL },
+ {"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 },
+ { NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL }
+};
+
+BOOL ami_arexx_init(void)
+{
+ if((arexx_obj = ARexxObj,
+ AREXX_HostName,"NETSURF",
+ AREXX_Commands,Commands,
+ AREXX_NoSlot,TRUE,
+ AREXX_ReplyHook,NULL,
+ AREXX_DefExtension,"nsrx",
+ End))
+ {
+ GetAttr(AREXX_SigMask, arexx_obj, &rxsig);
+ return true;
+ }
+ else
+ {
+/* Create a temporary ARexx port so we can send commands to the NetSurf which
+ * is already running */
+ arexx_obj = ARexxObj,
+ AREXX_HostName,"NETSURF",
+ AREXX_Commands,Commands,
+ AREXX_NoSlot,FALSE,
+ AREXX_ReplyHook,NULL,
+ AREXX_DefExtension,"nsrx",
+ End;
+ return false;
+ }
+}
+
+void ami_arexx_handle(void)
+{
+ RA_HandleRexx(arexx_obj);
+}
+
+void ami_arexx_execute(char *script)
+{
+ char full_script_path[1025];
+ BPTR lock;
+
+ if((lock = Lock(script, ACCESS_READ))) {
+ DevNameFromLock(lock, full_script_path, 1024, DN_FULLPATH);
+ LOG("Executing script: %s", full_script_path);
+ IDoMethod(arexx_obj, AM_EXECUTE, full_script_path, NULL, NULL, NULL, NULL, NULL);
+ UnLock(lock);
+ }
+}
+
+void ami_arexx_cleanup(void)
+{
+ if(arexx_obj) DisposeObject(arexx_obj);
+}
+
+static struct gui_window *ami_find_tab_gwin(struct gui_window_2 *gwin, int tab)
+{
+ int tabs = 0;
+ struct Node *ctab;
+ struct Node *ntab;
+ struct gui_window *gw;
+
+ if((tab == 0) || (gwin->tabs == 0)) return gwin->gw;
+
+ ctab = GetHead(&gwin->tab_list);
+
+ do
+ {
+ tabs++;
+ ntab=GetSucc(ctab);
+ GetClickTabNodeAttrs(ctab,
+ TNA_UserData, &gw,
+ TAG_DONE);
+ if(tabs == tab) return gw;
+ } while((ctab=ntab));
+
+ return NULL;
+}
+
+static int ami_find_tab_bw(struct gui_window_2 *gwin, struct browser_window *bw)
+{
+ int tabs = 0;
+ struct Node *ctab;
+ struct Node *ntab;
+ struct gui_window *tgw = NULL;
+
+ if((bw == NULL) || (gwin->tabs == 0)) return 1;
+
+ ctab = GetHead(&gwin->tab_list);
+
+ do
+ {
+ tabs++;
+ ntab=GetSucc(ctab);
+ GetClickTabNodeAttrs(ctab,
+ TNA_UserData, &tgw,
+ TAG_DONE);
+ if(tgw->bw == bw) return tabs;
+ } while((ctab=ntab));
+
+ return 0;
+}
+
+static struct gui_window *ami_find_tab(int window, int tab)
+{
+ struct nsObject *node, *nnode;
+
+ if(!IsMinListEmpty(window_list))
+ {
+ int windows = 0;
+
+ node = (struct nsObject *)GetHead((struct List *)window_list);
+
+ do
+ {
+ nnode=(struct nsObject *)GetSucc((struct Node *)node);
+
+ if(node->Type == AMINS_WINDOW)
+ {
+ windows++;
+ if(windows == window)
+ return ami_find_tab_gwin(node->objstruct, tab);
+ }
+ } while((node = nnode));
+ }
+ return NULL;
+}
+
+STATIC VOID rx_open(struct ARexxCmd *cmd, struct RexxMsg *rxm __attribute__((unused)))
+{
+ struct dlnode *dln;
+ struct gui_window *gw = cur_gw;
+ nsurl *url;
+
+ cmd->ac_RC = 0;
+
+ if((cmd->ac_ArgList[4]) && (cmd->ac_ArgList[5]))
+ gw = ami_find_tab(*(ULONG *)cmd->ac_ArgList[4], *(ULONG *)cmd->ac_ArgList[5]);
+
+ if (nsurl_create((char *)cmd->ac_ArgList[0], &url) != NSERROR_OK) {
+ amiga_warn_user("NoMemory", 0);
+ return;
+ }
+
+ if(cmd->ac_ArgList[3])
+ {
+ if(!gw) return;
+
+ dln = ami_misc_allocvec_clear(sizeof(struct dlnode), 0);
+ 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,
+ url,
+ NULL,
+ BW_NAVIGATE_DOWNLOAD,
+ NULL,
+ NULL,
+ NULL);
+ }
+ else if(cmd->ac_ArgList[2])
+ {
+ browser_window_create(BW_CREATE_HISTORY |
+ BW_CREATE_TAB,
+ url,
+ NULL,
+ gw->bw,
+ NULL);
+ }
+ else if(cmd->ac_ArgList[1])
+ {
+ browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ }
+ else
+ {
+ if(gw)
+ {
+ browser_window_navigate(gw->bw,
+ url,
+ NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+ }
+ else
+ {
+ browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ }
+ }
+ nsurl_unref(url);
+}
+
+STATIC VOID rx_save(struct ARexxCmd *cmd, struct RexxMsg *rxm __attribute__((unused)))
+{
+ BPTR fh = 0;
+ ULONG source_size;
+ const char *source_data;
+ struct gui_window *gw = cur_gw;
+
+ cmd->ac_RC = 0;
+
+ if((cmd->ac_ArgList[1]) && (cmd->ac_ArgList[2]))
+ gw = ami_find_tab(*(ULONG *)cmd->ac_ArgList[1], *(ULONG *)cmd->ac_ArgList[2]);
+
+ if(!gw) return;
+
+ ami_set_pointer(gw->shared, GUI_POINTER_WAIT, false);
+
+ if((fh = FOpen((char *)cmd->ac_ArgList[0], MODE_NEWFILE, 0)))
+ {
+ hlcache_handle *h = browser_window_get_content(gw->bw);
+ if((source_data = content_get_source_data(h, &source_size)))
+ FWrite(fh, source_data, 1, source_size);
+
+ FClose(fh);
+ SetComment((char *)cmd->ac_ArgList[0], nsurl_access(browser_window_get_url(gw->bw)));
+ }
+
+ ami_reset_pointer(gw->shared);
+}
+
+STATIC VOID rx_quit(struct ARexxCmd *cmd, struct RexxMsg *rxm __attribute__((unused)))
+{
+ cmd->ac_RC = 0;
+ ami_quit_netsurf();
+}
+
+STATIC VOID rx_tofront(struct ARexxCmd *cmd, struct RexxMsg *rxm __attribute__((unused)))
+{
+ cmd->ac_RC = 0;
+ ScreenToFront(scrn);
+}
+
+STATIC VOID rx_geturl(struct ARexxCmd *cmd, struct RexxMsg *rxm __attribute__((unused)))
+{
+ struct gui_window *gw = cur_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)
+ {
+ strcpy(result, nsurl_access(browser_window_get_url(gw->bw)));
+ }
+ else
+ {
+ strcpy(result,"");
+ }
+
+ cmd->ac_Result = result;
+}
+
+STATIC VOID rx_gettitle(struct ARexxCmd *cmd, struct RexxMsg *rxm __attribute__((unused)))
+{
+ struct gui_window *gw = cur_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)
+ {
+ if(gw->shared->tabs > 1)
+ strcpy(result, gw->tabtitle);
+ else
+ strcpy(result, gw->shared->wintitle);
+ }
+ else
+ {
+ strcpy(result,"");
+ }
+
+ cmd->ac_Result = result;
+}
+
+STATIC VOID rx_version(struct ARexxCmd *cmd, struct RexxMsg *rxm __attribute__((unused)))
+{
+ cmd->ac_RC = 0;
+
+ if(cmd->ac_ArgList[2])
+ {
+ if(cmd->ac_ArgList[1])
+ {
+ if((netsurf_version_major > *(int *)cmd->ac_ArgList[0]) || ((netsurf_version_minor >= *(int *)cmd->ac_ArgList[1]) && (netsurf_version_major == *(int *)cmd->ac_ArgList[0])))
+ {
+ strcpy(result,"1");
+ }
+ else
+ {
+ strcpy(result,"0");
+ }
+ }
+ else if(cmd->ac_ArgList[0])
+ {
+ if((netsurf_version_major >= *(int *)cmd->ac_ArgList[0]))
+ {
+ strcpy(result,"1");
+ }
+ else
+ {
+ strcpy(result,"0");
+ }
+ }
+ else
+ {
+ strcpy(result,netsurf_version);
+ }
+ }
+ else
+ {
+ if(cmd->ac_ArgList[1])
+ {
+ if((netsurf_version_major > *(int *)cmd->ac_ArgList[0]) || ((atoi(wt_revid) >= *(int *)cmd->ac_ArgList[1]) && (netsurf_version_major == *(int *)cmd->ac_ArgList[0])))
+ {
+ strcpy(result,"1");
+ }
+ else
+ {
+ strcpy(result,"0");
+ }
+ }
+ else if(cmd->ac_ArgList[0])
+ {
+ if((netsurf_version_major >= *(int *)cmd->ac_ArgList[0]))
+ {
+ strcpy(result,"1");
+ }
+ else
+ {
+ strcpy(result,"0");
+ }
+ }
+ else
+ {
+ strcpy(result,verarexx);
+ }
+ }
+
+ cmd->ac_Result = result;
+}
+
+STATIC VOID rx_pubscreen(struct ARexxCmd *cmd, struct RexxMsg *rxm __attribute__((unused)))
+{
+ cmd->ac_RC = 0;
+
+ if(nsoption_charp(pubscreen_name) == NULL)
+ {
+ strcpy(result,"NetSurf");
+ }
+ else
+ {
+ strcpy(result, nsoption_charp(pubscreen_name));
+ }
+
+ cmd->ac_Result = result;
+}
+
+STATIC VOID rx_back(struct ARexxCmd *cmd, struct RexxMsg *rxm __attribute__((unused)))
+{
+ struct gui_window *gw = cur_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);
+}
+
+STATIC VOID rx_forward(struct ARexxCmd *cmd, struct RexxMsg *rxm __attribute__((unused)))
+{
+ struct gui_window *gw = cur_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);
+
+}
+
+STATIC VOID rx_home(struct ARexxCmd *cmd, struct RexxMsg *rxm __attribute__((unused)))
+{
+ struct gui_window *gw = cur_gw;
+ nsurl *url;
+
+ 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 == NULL) return;
+
+ if (nsurl_create(nsoption_charp(homepage_url), &url) != NSERROR_OK) {
+ amiga_warn_user("NoMemory", 0);
+ } else {
+ browser_window_navigate(gw->bw,
+ url,
+ NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+}
+
+STATIC VOID rx_reload(struct ARexxCmd *cmd, struct RexxMsg *rxm __attribute__((unused)))
+{
+ struct gui_window *gw = cur_gw;
+
+ cmd->ac_RC = 0;
+
+ if((cmd->ac_ArgList[1]) && (cmd->ac_ArgList[2]))
+ gw = ami_find_tab(*(ULONG *)cmd->ac_ArgList[1], *(ULONG *)cmd->ac_ArgList[2]);
+
+ if(gw)
+ {
+ if(cmd->ac_ArgList[0]) /* FORCE */
+ {
+ browser_window_reload(gw->bw, true);
+ }
+ else
+ {
+ browser_window_reload(gw->bw, false);
+ }
+ }
+}
+
+STATIC VOID rx_windows(struct ARexxCmd *cmd, struct RexxMsg *rxm __attribute__((unused)))
+{
+ int windows = 0, tabs = 0;
+ int window = 0;
+
+ if(cmd->ac_ArgList[0]) window = *(ULONG *)cmd->ac_ArgList[0];
+ cmd->ac_RC = 0;
+
+ windows = ami_gui_count_windows(window, &tabs);
+
+ if(cmd->ac_ArgList[0]) sprintf(result, "%d", tabs);
+ else sprintf(result, "%d", windows);
+ cmd->ac_Result = result;
+}
+
+STATIC VOID rx_active(struct ARexxCmd *cmd, struct RexxMsg *rxm __attribute__((unused)))
+{
+ int window = 0, tab = 0;
+ struct gui_window *gw = cur_gw;
+ struct nsObject *node, *nnode;
+ struct gui_window_2 *gwin = NULL;
+
+ cmd->ac_RC = 0;
+
+ if(!IsMinListEmpty(window_list))
+ {
+ int windows = 0;
+
+ node = (struct nsObject *)GetHead((struct List *)window_list);
+
+ do
+ {
+ nnode=(struct nsObject *)GetSucc((struct Node *)node);
+
+ gwin = node->objstruct;
+
+ if(node->Type == AMINS_WINDOW)
+ {
+ windows++;
+ if(gwin->gw == gw)
+ {
+ window = windows;
+ break;
+ }
+ }
+ } while((node = nnode));
+ }
+
+ if(cmd->ac_ArgList[0])
+ {
+ tab = ami_find_tab_bw(gwin, gw->bw);
+ }
+
+ if(cmd->ac_ArgList[0]) sprintf(result, "%d", tab);
+ else sprintf(result, "%d", window);
+ cmd->ac_Result = result;
+}
+
+STATIC VOID rx_close(struct ARexxCmd *cmd, struct RexxMsg *rxm __attribute__((unused)))
+{
+ struct gui_window *gw = cur_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]);
+ else if(cmd->ac_ArgList[0])
+ {
+ ami_gui_close_window(gw->shared);
+ return;
+ }
+
+ if(gw) browser_window_destroy(gw->bw);
+}
+
+STATIC VOID rx_hotlist(struct ARexxCmd *cmd, struct RexxMsg *rxm __attribute__((unused)))
+{
+ cmd->ac_RC = 0;
+
+ if(strcasecmp((char *)cmd->ac_ArgList[0], "OPEN") == 0) {
+ ami_tree_open(hotlist_window, AMI_TREE_HOTLIST);
+ } else if(strcasecmp((char *)cmd->ac_ArgList[0], "CLOSE") == 0) {
+ ami_tree_close(hotlist_window);
+ }
+}
+
diff --git a/frontends/amiga/arexx.h b/frontends/amiga/arexx.h
new file mode 100755
index 000000000..358d174f3
--- /dev/null
+++ b/frontends/amiga/arexx.h
@@ -0,0 +1,32 @@
+/*
+ * 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/>.
+ */
+
+#ifndef AMIGA_AREXX_H
+#define AMIGA_AREXX_H
+
+#include <proto/arexx.h>
+#include <classes/arexx.h>
+
+BOOL ami_arexx_init(void);
+void ami_arexx_handle(void);
+void ami_arexx_execute(char *);
+void ami_arexx_cleanup(void);
+
+Object *arexx_obj;
+ULONG rxsig;
+#endif
diff --git a/frontends/amiga/bitmap.c b/frontends/amiga/bitmap.c
new file mode 100644
index 000000000..d04857262
--- /dev/null
+++ b/frontends/amiga/bitmap.c
@@ -0,0 +1,706 @@
+/*
+ * Copyright 2008, 2009, 2012, 2016 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 <stdlib.h>
+#include <proto/exec.h>
+#ifdef __amigaos4__
+#include <graphics/blitattr.h>
+#include <graphics/composite.h>
+#endif
+#include <graphics/gfxbase.h>
+#include <proto/datatypes.h>
+#include <datatypes/pictureclass.h>
+#include <proto/dos.h>
+#include <proto/intuition.h>
+#include <proto/utility.h>
+
+#include <proto/guigfx.h>
+#include <guigfx/guigfx.h>
+#include <render/render.h>
+#ifndef __amigaos4__
+#include <inline/guigfx.h>
+#endif
+
+#ifdef __amigaos4__
+#include <sys/param.h>
+#endif
+#include "assert.h"
+
+#include "utils/log.h"
+#include "utils/nsoption.h"
+#include "utils/nsurl.h"
+#include "utils/messages.h"
+#include "content/hlcache.h"
+#include "desktop/mouse.h"
+#include "desktop/gui_window.h"
+#include "image/bitmap.h"
+
+#include "amiga/gui.h"
+#include "amiga/bitmap.h"
+#include "amiga/download.h"
+#include "amiga/misc.h"
+#include "amiga/rtg.h"
+
+struct bitmap {
+ int width;
+ int height;
+ UBYTE *pixdata;
+ bool opaque;
+ int native;
+ struct BitMap *nativebm;
+ int nativebmwidth;
+ int nativebmheight;
+ PLANEPTR native_mask;
+ Object *dto;
+ APTR drawhandle;
+ struct nsurl *url; /* temporary storage space */
+ char *title; /* temporary storage space */
+ ULONG *icondata; /* for appicons */
+};
+
+enum {
+ AMI_NSBM_NONE = 0,
+ AMI_NSBM_TRUECOLOUR,
+ AMI_NSBM_PALETTEMAPPED
+};
+
+APTR pool_bitmap = NULL;
+
+/* exported function documented in amiga/bitmap.h */
+void *amiga_bitmap_create(int width, int height, unsigned int state)
+{
+ struct bitmap *bitmap;
+
+ if(pool_bitmap == NULL) pool_bitmap = ami_misc_itempool_create(sizeof(struct bitmap));
+
+ bitmap = ami_misc_itempool_alloc(pool_bitmap, sizeof(struct bitmap));
+ if(bitmap == NULL) return NULL;
+
+ bitmap->pixdata = ami_misc_allocvec_clear(width*height*4, 0xff);
+ bitmap->width = width;
+ bitmap->height = height;
+
+ if(state & BITMAP_OPAQUE) bitmap->opaque = true;
+ else bitmap->opaque = false;
+
+ bitmap->nativebm = NULL;
+ bitmap->nativebmwidth = 0;
+ bitmap->nativebmheight = 0;
+ bitmap->native_mask = NULL;
+ bitmap->drawhandle = NULL;
+ bitmap->url = NULL;
+ bitmap->title = NULL;
+ bitmap->icondata = NULL;
+ bitmap->native = AMI_NSBM_NONE;
+
+ return bitmap;
+}
+
+
+/* exported function documented in amiga/bitmap.h */
+unsigned char *amiga_bitmap_get_buffer(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+ return bm->pixdata;
+}
+
+/* exported function documented in amiga/bitmap.h */
+size_t amiga_bitmap_get_rowstride(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if(bm)
+ {
+ return ((bm->width)*4);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+/* exported function documented in amiga/bitmap.h */
+void amiga_bitmap_destroy(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if(bm)
+ {
+ if((bm->nativebm)) { // && (bm->native == AMI_NSBM_TRUECOLOUR)) {
+ ami_rtg_freebitmap(bm->nativebm);
+ }
+
+ if(bm->native_mask) FreeRaster(bm->native_mask, bm->width, bm->height);
+ if(bm->drawhandle) ReleaseDrawHandle(bm->drawhandle);
+ FreeVec(bm->pixdata);
+
+ if(bm->url) nsurl_unref(bm->url);
+ if(bm->title) free(bm->title);
+
+ bm->pixdata = NULL;
+ bm->nativebm = NULL;
+ bm->native_mask = NULL;
+ bm->drawhandle = NULL;
+ bm->url = NULL;
+ bm->title = NULL;
+
+ ami_misc_itempool_free(pool_bitmap, bm, sizeof(struct bitmap));
+ bm = NULL;
+ }
+}
+
+
+/* exported function documented in amiga/bitmap.h */
+bool amiga_bitmap_save(void *bitmap, const char *path, unsigned flags)
+{
+ int err = 0;
+ Object *dto = NULL;
+
+ if((dto = ami_datatype_object_from_bitmap(bitmap)))
+ {
+ if (flags & AMI_BITMAP_SCALE_ICON) {
+ IDoMethod(dto, PDTM_SCALE, 16, 16, 0);
+
+ if((DoDTMethod(dto, 0, 0, DTM_PROCLAYOUT, 0, 1)) == 0) {
+ return false;
+ }
+ }
+
+ err = SaveDTObjectA(dto, NULL, NULL, path, DTWM_IFF, FALSE, NULL);
+ DisposeDTObject(dto);
+ }
+
+ if(err == 0) return false;
+ else return true;
+}
+
+
+/* exported function documented in amiga/bitmap.h */
+void amiga_bitmap_modified(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if((bm->nativebm)) // && (bm->native == AMI_NSBM_TRUECOLOUR))
+ ami_rtg_freebitmap(bm->nativebm);
+
+ if(bm->drawhandle) ReleaseDrawHandle(bm->drawhandle);
+ if(bm->native_mask) FreeRaster(bm->native_mask, bm->width, bm->height);
+ bm->nativebm = NULL;
+ bm->drawhandle = NULL;
+ bm->native_mask = NULL;
+ bm->native = AMI_NSBM_NONE;
+}
+
+
+/* exported function documented in amiga/bitmap.h */
+void amiga_bitmap_set_opaque(void *bitmap, bool opaque)
+{
+ struct bitmap *bm = bitmap;
+ assert(bitmap);
+ bm->opaque = 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;
+ assert(bitmap);
+ return bm->opaque;
+}
+
+/**
+ * get width of a bitmap.
+ */
+int bitmap_get_width(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if(bm)
+ {
+ return(bm->width);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/**
+ * get height of a bitmap.
+ */
+int bitmap_get_height(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if(bm)
+ {
+ return(bm->height);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+/**
+ * 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)
+{
+ int x,y;
+ ULONG *bm = (ULONG *)amiga_bitmap_get_buffer(bitmap);
+
+ printf("Width=%ld, Height=%ld, Opaque=%s\nnativebm=%lx, width=%ld, height=%ld\n",
+ bitmap->width, bitmap->height, bitmap->opaque ? "true" : "false",
+ bitmap->nativebm, bitmap->nativebmwidth, bitmap->nativebmheight);
+
+ for(y = 0; y < bitmap->height; y++) {
+ for(x = 0; x < bitmap->width; x++) {
+ printf("%lx ", bm[(y*bitmap->width) + x]);
+ }
+ printf("\n");
+ }
+}
+#endif
+
+Object *ami_datatype_object_from_bitmap(struct bitmap *bitmap)
+{
+ Object *dto;
+ struct BitMapHeader *bmhd;
+
+ if((dto = NewDTObject(NULL,
+ DTA_SourceType,DTST_RAM,
+ DTA_GroupID,GID_PICTURE,
+ //DTA_BaseName,"ilbm",
+ PDTA_DestMode,PMODE_V43,
+ TAG_DONE)))
+ {
+ if(GetDTAttrs(dto,PDTA_BitMapHeader,&bmhd,TAG_DONE))
+ {
+ 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;
+ if(!amiga_bitmap_get_opaque(bitmap)) bmhd->bmh_Masking = mskHasAlpha;
+ }
+
+ SetDTAttrs(dto,NULL,NULL,
+ DTA_ObjName, bitmap->url ? nsurl_access(bitmap->url) : "",
+ DTA_ObjAnnotation,bitmap->title,
+ DTA_ObjAuthor,messages_get("NetSurf"),
+ DTA_NominalHoriz,bitmap_get_width(bitmap),
+ DTA_NominalVert,bitmap_get_height(bitmap),
+ PDTA_SourceMode,PMODE_V43,
+ TAG_DONE);
+
+ IDoMethod(dto, PDTM_WRITEPIXELARRAY, amiga_bitmap_get_buffer(bitmap),
+ PBPAFMT_RGBA, amiga_bitmap_get_rowstride(bitmap), 0, 0,
+ bitmap_get_width(bitmap), bitmap_get_height(bitmap));
+ }
+
+ return dto;
+}
+
+/* Quick way to get an object on disk into a struct bitmap */
+struct bitmap *ami_bitmap_from_datatype(char *filename)
+{
+ Object *dto;
+ struct bitmap *bm = NULL;
+
+ if((dto = NewDTObject(filename,
+ DTA_GroupID, GID_PICTURE,
+ PDTA_DestMode, PMODE_V43,
+ PDTA_PromoteMask, TRUE,
+ TAG_DONE))) {
+ struct BitMapHeader *bmh;
+
+ if(GetDTAttrs(dto, PDTA_BitMapHeader, &bmh, TAG_DONE))
+ {
+ 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,
+ bmh->bmh_Width, bmh->bmh_Height);
+
+ amiga_bitmap_set_opaque(bm, amiga_bitmap_test_opaque(bm));
+ }
+ DisposeDTObject(dto);
+ }
+
+ return bm;
+}
+
+static inline struct BitMap *ami_bitmap_get_generic(struct bitmap *bitmap, int width, int height, struct BitMap *friendbm, int type)
+{
+ struct BitMap *tbm = NULL;
+
+ if(bitmap->nativebm)
+ {
+ if((bitmap->nativebmwidth == width) && (bitmap->nativebmheight == height)) {
+ tbm = bitmap->nativebm;
+ return tbm;
+ } else if((bitmap->nativebmwidth == bitmap->width) &&
+ (bitmap->nativebmheight == bitmap->height)) { // >= width/height ?
+ tbm = bitmap->nativebm;
+ } else {
+ if(bitmap->nativebm) amiga_bitmap_modified(bitmap);
+ }
+ }
+
+ if(tbm == NULL) {
+ if(type == AMI_NSBM_TRUECOLOUR) {
+ if((tbm = ami_rtg_allocbitmap(bitmap->width, bitmap->height, 32, 0,
+ friendbm, AMI_BITMAP_FORMAT))) {
+ ami_rtg_writepixelarray(amiga_bitmap_get_buffer(bitmap),
+ tbm, bitmap->width, bitmap->height,
+ bitmap->width * 4, AMI_BITMAP_FORMAT);
+ }
+ } else {
+ if((tbm = ami_rtg_allocbitmap(bitmap->width, bitmap->height,
+ 8, 0, friendbm, AMI_BITMAP_FORMAT))) {
+
+ struct RastPort rp;
+ InitRastPort(&rp);
+ rp.BitMap = tbm;
+ ULONG dithermode = DITHERMODE_NONE;
+
+ if(nsoption_int(dither_quality) == 1) {
+ dithermode = DITHERMODE_EDD;
+ } else if(nsoption_int(dither_quality) == 2) {
+ 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,
+ bitmap->width, bitmap->height, NULL);
+
+ DirectDrawTrueColor(ddh, (ULONG *)amiga_bitmap_get_buffer(bitmap), 0, 0, TAG_DONE);
+ DeleteDirectDrawHandle(ddh);
+ ami_bitmap_argb_to_rgba(bitmap);
+ }
+ }
+
+ if(nsoption_int(cache_bitmaps) == 2)
+ {
+ bitmap->nativebm = tbm;
+ bitmap->nativebmwidth = bitmap->width;
+ bitmap->nativebmheight = bitmap->height;
+ bitmap->native = type;
+ }
+ }
+
+ if((bitmap->width != width) || (bitmap->height != height))
+ {
+ struct BitMap *scaledbm;
+ struct BitScaleArgs bsa;
+ int depth = 32;
+ if(type == AMI_NSBM_PALETTEMAPPED) depth = 8;
+
+ scaledbm = ami_rtg_allocbitmap(width, height, depth, 0,
+ friendbm, AMI_BITMAP_FORMAT);
+#ifdef __amigaos4__
+ if(__builtin_expect(((GfxBase->LibNode.lib_Version >= 53) &&
+ (type == AMI_NSBM_TRUECOLOUR)), 1)) {
+ /* AutoDoc says v52, but this function isn't in OS4.0, so checking for v53 (OS4.1)
+ * Additionally, when we use friend BitMaps in non 32-bit modes it freezes the OS */
+ uint32 flags = 0;
+ if(nsoption_bool(scale_quality)) flags |= COMPFLAG_SrcFilter;
+
+ CompositeTags(COMPOSITE_Src, tbm, scaledbm,
+ COMPTAG_ScaleX, COMP_FLOAT_TO_FIX((float)width/bitmap->width),
+ COMPTAG_ScaleY, COMP_FLOAT_TO_FIX((float)height/bitmap->height),
+ COMPTAG_Flags, flags,
+ COMPTAG_DestX, 0,
+ COMPTAG_DestY, 0,
+ COMPTAG_DestWidth, width,
+ COMPTAG_DestHeight, height,
+ COMPTAG_OffsetX, 0,
+ COMPTAG_OffsetY, 0,
+ COMPTAG_FriendBitMap, scrn->RastPort.BitMap,
+ TAG_DONE);
+ } else /* Do it the old-fashioned way. This is pretty slow, even on OS4.1 */
+#endif
+ {
+ bsa.bsa_SrcX = 0;
+ bsa.bsa_SrcY = 0;
+ bsa.bsa_SrcWidth = bitmap->width;
+ bsa.bsa_SrcHeight = bitmap->height;
+ bsa.bsa_DestX = 0;
+ bsa.bsa_DestY = 0;
+ bsa.bsa_XSrcFactor = bitmap->width;
+ bsa.bsa_XDestFactor = width;
+ bsa.bsa_YSrcFactor = bitmap->height;
+ bsa.bsa_YDestFactor = height;
+ bsa.bsa_SrcBitMap = tbm;
+ bsa.bsa_DestBitMap = scaledbm;
+ bsa.bsa_Flags = 0;
+
+ BitMapScale(&bsa);
+ }
+
+ if(bitmap->nativebm != tbm) ami_rtg_freebitmap(bitmap->nativebm);
+ ami_rtg_freebitmap(tbm);
+ tbm = scaledbm;
+ bitmap->nativebm = NULL;
+ bitmap->native = AMI_NSBM_NONE;
+
+ if(nsoption_int(cache_bitmaps) >= 1)
+ {
+ bitmap->nativebm = tbm;
+ bitmap->nativebmwidth = width;
+ bitmap->nativebmheight = height;
+ bitmap->native = type;
+ }
+ }
+
+ return tbm;
+}
+
+
+static inline struct BitMap *ami_bitmap_get_truecolour(struct bitmap *bitmap,int width,int height,struct BitMap *friendbm)
+{
+ if((bitmap->native != AMI_NSBM_NONE) && (bitmap->native != AMI_NSBM_TRUECOLOUR)) {
+ amiga_bitmap_modified(bitmap);
+ }
+
+ return ami_bitmap_get_generic(bitmap, width, height, friendbm, AMI_NSBM_TRUECOLOUR);
+}
+
+PLANEPTR ami_bitmap_get_mask(struct bitmap *bitmap, int width,
+ int height, struct BitMap *n_bm)
+{
+ uint32 *bmi = (uint32 *) amiga_bitmap_get_buffer(bitmap);
+ UBYTE maskbit = 0;
+ ULONG bm_width;
+ int y, x, bpr;
+
+ if((height != bitmap->height) || (width != bitmap->width)) return NULL;
+ if(amiga_bitmap_get_opaque(bitmap) == true) return NULL;
+ if(bitmap->native_mask) return bitmap->native_mask;
+
+ bm_width = GetBitMapAttr(n_bm, BMA_WIDTH);
+ bpr = RASSIZE(bm_width, 1);
+ bitmap->native_mask = AllocRaster(bm_width, height);
+ SetMem(bitmap->native_mask, 0, bpr * height);
+
+ for(y=0; y<height; y++) {
+ for(x=0; x<width; x++) {
+ if ((*bmi & 0x000000ffU) <= (ULONG)nsoption_int(mask_alpha)) maskbit = 0;
+ else maskbit = 1;
+ bmi++;
+ bitmap->native_mask[(y*bpr) + (x/8)] |=
+ maskbit << (7 - (x % 8));
+ }
+ }
+
+ return bitmap->native_mask;
+}
+
+static inline struct BitMap *ami_bitmap_get_palettemapped(struct bitmap *bitmap,
+ int width, int height, struct BitMap *friendbm)
+{
+ if((bitmap->native != AMI_NSBM_NONE) && (bitmap->native != AMI_NSBM_PALETTEMAPPED)) {
+ amiga_bitmap_modified(bitmap);
+ }
+
+ return ami_bitmap_get_generic(bitmap, width, height, friendbm, AMI_NSBM_PALETTEMAPPED);
+}
+
+struct BitMap *ami_bitmap_get_native(struct bitmap *bitmap,
+ int width, int height, struct BitMap *friendbm)
+{
+ if(bitmap == NULL) return NULL;
+
+ if(__builtin_expect(ami_plot_screen_is_palettemapped() == true, 0)) {
+ return ami_bitmap_get_palettemapped(bitmap, width, height, friendbm);
+ } else {
+ return ami_bitmap_get_truecolour(bitmap, width, height, friendbm);
+ }
+}
+
+void ami_bitmap_fini(void)
+{
+ if(pool_bitmap) ami_misc_itempool_delete(pool_bitmap);
+ pool_bitmap = NULL;
+}
+
+static nserror bitmap_render(struct bitmap *bitmap, hlcache_handle *content)
+{
+#ifdef __amigaos4__
+ struct redraw_context ctx = {
+ .interactive = false,
+ .background_images = true,
+ .plot = &amiplot
+ };
+
+ int plot_width;
+ int plot_height;
+ struct gui_globals bm_globals;
+ struct gui_globals *temp_gg = glob;
+
+ plot_width = MIN(content_get_width(content), bitmap->width);
+ plot_height = ((plot_width * bitmap->height) + (bitmap->width / 2)) /
+ bitmap->width;
+
+ ami_init_layers(&bm_globals, bitmap->width, bitmap->height, true);
+ bm_globals.shared_pens = NULL;
+
+ glob = &bm_globals;
+ ami_clearclipreg(&bm_globals);
+
+ content_scaled_redraw(content, plot_width, plot_height, &ctx);
+
+ BltBitMapTags( BLITA_SrcX, 0,
+ BLITA_SrcY, 0,
+ BLITA_Width, bitmap->width,
+ BLITA_Height, bitmap->height,
+ BLITA_Source, bm_globals.bm,
+ BLITA_SrcType, BLITT_BITMAP,
+ BLITA_Dest, amiga_bitmap_get_buffer(bitmap),
+ BLITA_DestType, BLITT_ARGB32,
+ BLITA_DestBytesPerRow, 4 * bitmap->width,
+ BLITA_DestX, 0,
+ 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) */
+
+ ami_free_layers(&bm_globals);
+ amiga_bitmap_set_opaque(bitmap, true);
+
+ /* Restore previous render area. This is set when plotting starts,
+ * but if bitmap_render is called *during* a browser render then
+ * having an invalid pointer here causes NetSurf to crash.
+ */
+ glob = temp_gg;
+#else
+#warning FIXME for OS3 (in current state none of bitmap_render can work!)
+#endif
+
+ return NSERROR_OK;
+}
+
+void ami_bitmap_set_url(struct bitmap *bm, struct nsurl *url)
+{
+ if(bm->url != NULL) return;
+ bm->url = nsurl_ref(url);
+}
+
+void ami_bitmap_set_title(struct bitmap *bm, const char *title)
+{
+ if(bm->title != NULL) return;
+ bm->title = strdup(title);
+}
+
+ULONG *ami_bitmap_get_icondata(struct bitmap *bm)
+{
+ return bm->icondata;
+}
+
+void ami_bitmap_set_icondata(struct bitmap *bm, ULONG *icondata)
+{
+ bm->icondata = icondata;
+}
+
+bool ami_bitmap_is_nativebm(struct bitmap *bm, struct BitMap *nbm)
+{
+ if(bm->nativebm == nbm) return true;
+ else return false;
+}
+
+
+static struct gui_bitmap_table bitmap_table = {
+ .create = amiga_bitmap_create,
+ .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,
+};
+
+struct gui_bitmap_table *amiga_bitmap_table = &bitmap_table;
diff --git a/frontends/amiga/bitmap.h b/frontends/amiga/bitmap.h
new file mode 100755
index 000000000..d7dd70bce
--- /dev/null
+++ b/frontends/amiga/bitmap.h
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2008,2009 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/>.
+ */
+
+#ifndef AMIGA_BITMAP_H
+#define AMIGA_BITMAP_H
+
+#include <stdbool.h>
+#include <exec/types.h>
+#include <proto/graphics.h>
+#include <intuition/classusr.h>
+#include <libraries/Picasso96.h>
+
+#define AMI_BITMAP_FORMAT RGBFB_R8G8B8A8
+#define AMI_BITMAP_SCALE_ICON 0xFF
+
+struct gui_bitmap_table *amiga_bitmap_table;
+struct bitmap;
+struct nsurl;
+
+struct BitMap *ami_bitmap_get_native(struct bitmap *bitmap,
+ int width, int height, struct BitMap *friendbm);
+PLANEPTR ami_bitmap_get_mask(struct bitmap *bitmap, int width,
+ int height, struct BitMap *n_bm);
+
+Object *ami_datatype_object_from_bitmap(struct bitmap *bitmap);
+struct bitmap *ami_bitmap_from_datatype(char *filename);
+
+/**
+ * Set bitmap URL
+ *
+ * \param bm a bitmap, as returned by bitmap_create()
+ * \param title a pointer to a title string
+ *
+ * A reference will be kept by the bitmap object.
+ * The URL can only ever be set once for a bitmap.
+ */
+void ami_bitmap_set_url(struct bitmap *bm, struct nsurl *url);
+
+/**
+ * Set bitmap title
+ *
+ * \param bm a bitmap, as returned by bitmap_create()
+ * \param title a pointer to a title string
+ *
+ * This is copied by the bitmap object.
+ * The title can only ever be set once for a bitmap.
+ */
+void ami_bitmap_set_title(struct bitmap *bm, const char *title);
+
+/**
+ * Get an icondata pointer
+ *
+ * \param bm a bitmap, as returned by bitmap_create()
+ * \return pointer to the icondata area
+ *
+ * This function probably shouldn't be here!
+ */
+ULONG *ami_bitmap_get_icondata(struct bitmap *bm);
+
+/**
+ * Set an icondata pointer
+ *
+ * \param bm a bitmap, as returned by bitmap_create()
+ * \param icondata a pointer to memory
+ *
+ * This function probably shouldn't be here!
+ */
+void ami_bitmap_set_icondata(struct bitmap *bm, ULONG *icondata);
+
+/**
+ * Test if a BitMap is owned by a bitmap.
+ *
+ * \param bm a bitmap, as returned by bitmap_create()
+ * \param nbm a BitMap, as created by AllocBitMap()
+ * \return true if the BitMap is owned by the bitmap
+ */
+bool ami_bitmap_is_nativebm(struct bitmap *bm, struct BitMap *nbm);
+
+/**
+ * Cleanup bitmap allocations
+ */
+void ami_bitmap_fini(void);
+
+/**
+ * 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
+ * \return an opaque struct bitmap, or NULL on memory exhaustion
+ */
+void *amiga_bitmap_create(int width, int height, unsigned int state);
+
+/**
+ * Return a pointer to the pixel data in a bitmap.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \return pointer to the pixel buffer
+ *
+ * The pixel data is packed as BITMAP_FORMAT, possibly with padding at the end
+ * of rows. The width of a row in bytes is given by bitmap_get_rowstride().
+ */
+unsigned char *amiga_bitmap_get_buffer(void *bitmap);
+
+/**
+ * Find the width of a pixel row in bytes.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \return width of a pixel row in the bitmap
+ */
+size_t amiga_bitmap_get_rowstride(void *bitmap);
+
+/**
+ * Return the width of a bitmap.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \return width in pixels
+ */
+int bitmap_get_width(void *bitmap);
+
+/**
+ * Return the height of a bitmap.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \return height in pixels
+ */
+int bitmap_get_height(void *bitmap);
+
+/**
+ * Free a bitmap.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+void amiga_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
+ */
+bool amiga_bitmap_save(void *bitmap, const char *path, unsigned flags);
+
+/**
+ * The bitmap image has changed, so flush any persistant cache.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+void amiga_bitmap_modified(void *bitmap);
+
+/**
+ * Sets whether a bitmap should be plotted opaque
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \param opaque whether the bitmap should be plotted opaque
+ */
+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()
+ */
+bool amiga_bitmap_get_opaque(void *bitmap);
+
+
+#endif
diff --git a/frontends/amiga/clipboard.c b/frontends/amiga/clipboard.c
new file mode 100644
index 000000000..12ceb0f09
--- /dev/null
+++ b/frontends/amiga/clipboard.c
@@ -0,0 +1,374 @@
+/*
+ * Copyright 2008-2012 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 <stdlib.h>
+#include <proto/iffparse.h>
+#include <proto/intuition.h>
+#include <proto/exec.h>
+#include <proto/datatypes.h>
+#include <proto/diskfont.h>
+
+#include <diskfont/diskfonttag.h>
+#include <datatypes/textclass.h>
+#include <datatypes/pictureclass.h>
+
+#include "utils/nsoption.h"
+#include "utils/utf8.h"
+#include "utils/nsurl.h"
+#include "content/hlcache.h"
+#include "desktop/browser.h"
+#include "desktop/plotters.h"
+#include "desktop/textinput.h"
+#include "desktop/gui_window.h"
+#include "desktop/gui_clipboard.h"
+
+#include "amiga/bitmap.h"
+#include "amiga/clipboard.h"
+#include "amiga/drag.h"
+#include "amiga/filetype.h"
+#include "amiga/gui.h"
+#include "amiga/iff_cset.h"
+#include "amiga/iff_dr2d.h"
+#include "amiga/menu.h"
+#include "amiga/misc.h"
+#include "amiga/utf8.h"
+
+#define ID_UTF8 MAKE_ID('U','T','F','8')
+
+struct IFFHandle *iffh = NULL;
+
+static struct IFFHandle *ami_clipboard_init_internal(int unit)
+{
+ struct IFFHandle *iffhandle = NULL;
+
+ if((iffhandle = AllocIFF()))
+ {
+ if((iffhandle->iff_Stream = (ULONG)OpenClipboard(unit)))
+ {
+ InitIFFasClip(iffhandle);
+ }
+ }
+
+ return iffhandle;
+}
+
+void ami_clipboard_init(void)
+{
+ iffh = ami_clipboard_init_internal(0);
+}
+
+static void ami_clipboard_free_internal(struct IFFHandle *iffhandle)
+{
+ if(iffhandle == NULL) return;
+ if(iffhandle->iff_Stream) CloseClipboard((struct ClipboardHandle *)iffhandle->iff_Stream);
+ FreeIFF(iffhandle);
+}
+
+void ami_clipboard_free(void)
+{
+ ami_clipboard_free_internal(iffh);
+}
+
+void gui_start_selection(struct gui_window *g)
+{
+ if(!g) return;
+ if(!g->shared->win) return;
+ if(nsoption_bool(kiosk_mode) == true) return;
+
+ OnMenu(g->shared->win, AMI_MENU_CLEAR);
+ OnMenu(g->shared->win, AMI_MENU_COPY);
+
+ if (browser_window_get_editor_flags(g->bw) & BW_EDITOR_CAN_CUT)
+ OnMenu(g->shared->win, AMI_MENU_CUT);
+}
+
+static char *ami_clipboard_cat_collection(struct CollectionItem *ci, LONG codeset, size_t *text_length)
+{
+ struct CollectionItem *ci_new = NULL, *ci_next = NULL, *ci_curr = ci;
+ size_t len = 0;
+ char *text = NULL, *p;
+
+ /* Scan the collected chunks to find out the total size.
+ * If they are not in UTF-8, convert the chunks first and create a new CollectionItem list.
+ */
+ do {
+ switch(codeset) {
+ case 106:
+ len += ci_curr->ci_Size;
+ break;
+
+ case 0:
+ if(ci_new) {
+ ci_next->ci_Next = ami_misc_allocvec_clear(sizeof(struct CollectionItem), 0);
+ ci_next = ci_next->ci_Next;
+ } else {
+ ci_new = ami_misc_allocvec_clear(sizeof(struct CollectionItem), 0);
+ ci_next = ci_new;
+ }
+
+ utf8_from_local_encoding(ci_curr->ci_Data, ci_curr->ci_Size, (char **)&ci_next->ci_Data);
+ ci_next->ci_Size = strlen(ci_next->ci_Data);
+ len += ci_next->ci_Size;
+ break;
+
+ default:
+ if(ci_new) {
+ ci_next->ci_Next = ami_misc_allocvec_clear(sizeof(struct CollectionItem), 0);
+ ci_next = ci_next->ci_Next;
+ } else {
+ ci_new = ami_misc_allocvec_clear(sizeof(struct CollectionItem), 0);
+ ci_next = ci_new;
+ }
+
+ utf8_from_enc(ci_curr->ci_Data,
+ (const char *)ObtainCharsetInfo(DFCS_NUMBER,
+ codeset, DFCS_MIMENAME),
+ ci_curr->ci_Size, (char **)&ci_next->ci_Data, NULL);
+ ci_next->ci_Size = strlen(ci_next->ci_Data);
+ len += ci_next->ci_Size;
+ break;
+ }
+ } while ((ci_curr = ci_curr->ci_Next));
+
+ text = malloc(len);
+
+ if(text == NULL) return NULL;
+
+ /* p points to the end of the buffer. This is because the chunks are
+ * in the list in reverse order. */
+ p = text + len;
+
+ if(ci_new) {
+ ci_curr = ci_new;
+ } else {
+ ci_curr = ci;
+ }
+
+ do {
+ p -= ci_curr->ci_Size;
+ memcpy(p, ci_curr->ci_Data, ci_curr->ci_Size);
+ ci_next = ci_curr->ci_Next;
+
+ if(ci_new) {
+ free(ci_curr->ci_Data);
+ FreeVec(ci_curr);
+ }
+ } while ((ci_curr = ci_next));
+
+ *text_length = len;
+ return text;
+}
+
+static void gui_get_clipboard(char **buffer, size_t *length)
+{
+ struct CollectionItem *ci = NULL;
+ struct StoredProperty *sp = NULL;
+ struct CSet *cset;
+
+ if(OpenIFF(iffh,IFFF_READ)) return;
+
+ if(CollectionChunk(iffh,ID_FTXT,ID_CHRS)) return;
+ if(PropChunk(iffh,ID_FTXT,ID_CSET)) return;
+ if(CollectionChunk(iffh,ID_FTXT,ID_UTF8)) return;
+ if(StopOnExit(iffh, ID_FTXT, ID_FORM)) return;
+
+ ParseIFF(iffh,IFFPARSE_SCAN);
+
+ if((ci = FindCollection(iffh, ID_FTXT, ID_UTF8))) {
+ *buffer = ami_clipboard_cat_collection(ci, 106, length);
+ } else if((ci = FindCollection(iffh, ID_FTXT, ID_CHRS))) {
+ LONG codeset = 0;
+ if((sp = FindProp(iffh, ID_FTXT, ID_CSET))) {
+ cset = (struct CSet *)sp->sp_Data;
+ codeset = cset->CodeSet;
+ }
+ *buffer = ami_clipboard_cat_collection(ci, codeset, length);
+ }
+
+ CloseIFF(iffh);
+}
+
+static void gui_set_clipboard(const char *buffer, size_t length,
+ nsclipboard_styles styles[], int n_styles)
+{
+ char *text;
+ struct CSet cset = {0, {0}};
+
+ if(buffer == NULL) return;
+
+ if(!(OpenIFF(iffh, IFFF_WRITE)))
+ {
+ if(!(PushChunk(iffh, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN)))
+ {
+ if(nsoption_bool(clipboard_write_utf8))
+ {
+ if(!(PushChunk(iffh, 0, ID_CSET, 32)))
+ {
+ cset.CodeSet = 106; // UTF-8
+ WriteChunkBytes(iffh, &cset, 32);
+ PopChunk(iffh);
+ }
+ }
+ }
+ else
+ {
+ PopChunk(iffh);
+ }
+
+ if(!(PushChunk(iffh, 0, ID_CHRS, IFFSIZE_UNKNOWN))) {
+ if(nsoption_bool(clipboard_write_utf8)) {
+ WriteChunkBytes(iffh, buffer, length);
+ } else {
+ if(utf8_to_local_encoding(buffer, length, &text) == NSERROR_OK) {
+ char *p;
+
+ p = text;
+
+ while(*p != '\0') {
+ if(*p == 0xa0) *p = 0x20;
+ p++;
+ }
+ WriteChunkBytes(iffh, text, strlen(text));
+ ami_utf8_free(text);
+ }
+ }
+
+ PopChunk(iffh);
+ } else {
+ PopChunk(iffh);
+ }
+
+ if(!(PushChunk(iffh, 0, ID_UTF8, IFFSIZE_UNKNOWN))) {
+ WriteChunkBytes(iffh, buffer, length);
+ PopChunk(iffh);
+ } else {
+ PopChunk(iffh);
+ }
+ CloseIFF(iffh);
+ }
+}
+
+void ami_drag_selection(struct gui_window *g)
+{
+ int x;
+ int y;
+ char *utf8text;
+ char *sel;
+ struct IFFHandle *old_iffh = iffh;
+ struct gui_window_2 *gwin = ami_window_at_pointer(AMINS_WINDOW);
+
+ /* NB: 'gwin' is at the drop point, 'g' is where the selection was dragged from.
+ * These may be different if the selection has been dragged between windows. */
+
+ if(!gwin)
+ {
+ DisplayBeep(scrn);
+ return;
+ }
+
+ x = gwin->win->MouseX;
+ y = gwin->win->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);
+
+ ami_clipboard_free_internal(iffh);
+ iffh = old_iffh;
+ }
+ else
+ {
+ x = gwin->win->MouseX;
+ y = gwin->win->MouseY;
+
+ if(ami_gadget_hit(gwin->objects[GID_URL], x, y))
+ {
+ if((sel = browser_window_get_selection(g->bw)))
+ {
+ utf8text = ami_utf8_easy(sel);
+ RefreshSetGadgetAttrs((struct Gadget *)gwin->objects[GID_URL],
+ gwin->win, NULL, STRINGA_TextVal, utf8text, TAG_DONE);
+ free(sel);
+ ami_utf8_free(utf8text);
+ }
+ }
+ else if(ami_gadget_hit(gwin->objects[GID_SEARCHSTRING], x, y))
+ {
+ if((sel = browser_window_get_selection(g->bw)))
+ {
+ utf8text = ami_utf8_easy(sel);
+ RefreshSetGadgetAttrs((struct Gadget *)gwin->objects[GID_SEARCHSTRING],
+ gwin->win, NULL, STRINGA_TextVal, utf8text, TAG_DONE);
+ free(sel);
+ ami_utf8_free(utf8text);
+ }
+ }
+ else
+ {
+ DisplayBeep(scrn);
+ }
+ }
+}
+
+bool ami_easy_clipboard(const char *text)
+{
+ gui_set_clipboard(text, strlen(text), NULL, 0);
+ return true;
+}
+
+bool ami_easy_clipboard_bitmap(struct bitmap *bitmap)
+{
+ Object *dto = NULL;
+
+ if((dto = ami_datatype_object_from_bitmap(bitmap)))
+ {
+ DoDTMethod(dto,NULL,NULL,DTM_COPY,NULL);
+ DisposeDTObject(dto);
+ }
+ return true;
+}
+
+#ifdef WITH_NS_SVG
+bool ami_easy_clipboard_svg(struct hlcache_handle *c)
+{
+ const char *source_data;
+ ULONG 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(!(OpenIFF(iffh,IFFF_WRITE)))
+ {
+ ami_svg_to_dr2d(iffh, source_data, source_size, nsurl_access(hlcache_handle_get_url(c)));
+ CloseIFF(iffh);
+ }
+
+ return true;
+}
+#endif
+
+static struct gui_clipboard_table clipboard_table = {
+ .get = gui_get_clipboard,
+ .set = gui_set_clipboard,
+};
+
+struct gui_clipboard_table *amiga_clipboard_table = &clipboard_table;
diff --git a/frontends/amiga/clipboard.h b/frontends/amiga/clipboard.h
new file mode 100755
index 000000000..bc5b779ef
--- /dev/null
+++ b/frontends/amiga/clipboard.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2008-2009, 2011 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/>.
+ */
+
+#ifndef AMIGA_CLIPBOARD_H
+#define AMIGA_CLIPBOARD_H
+#include <stdbool.h>
+
+struct bitmap;
+struct hlcache_handle;
+struct selection;
+struct gui_window;
+struct gui_window_2;
+struct gui_clipboard_table;
+
+extern struct gui_clipboard_table *amiga_clipboard_table;
+
+void gui_start_selection(struct gui_window *g);
+
+void ami_clipboard_init(void);
+void ami_clipboard_free(void);
+void ami_drag_selection(struct gui_window *g);
+bool ami_easy_clipboard(const char *text);
+bool ami_easy_clipboard_bitmap(struct bitmap *bitmap);
+#ifdef WITH_NS_SVG
+bool ami_easy_clipboard_svg(struct hlcache_handle *c);
+#endif
+#endif
diff --git a/frontends/amiga/cookies.c b/frontends/amiga/cookies.c
new file mode 100755
index 000000000..0ca17413e
--- /dev/null
+++ b/frontends/amiga/cookies.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2008, 2009 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 <proto/exec.h>
+
+#include "desktop/cookie_manager.h"
+#include "desktop/mouse.h"
+#include "desktop/gui_window.h"
+
+#include "amiga/cookies.h"
+#include "amiga/tree.h"
+
+void ami_cookies_initialise(void)
+{
+ cookies_window = ami_tree_create(TREE_COOKIES, NULL);
+
+ if(!cookies_window) return;
+}
+
+void ami_cookies_free()
+{
+ ami_tree_destroy(cookies_window);
+ cookies_window = NULL;
+}
diff --git a/frontends/amiga/cookies.h b/frontends/amiga/cookies.h
new file mode 100755
index 000000000..d6922750c
--- /dev/null
+++ b/frontends/amiga/cookies.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2008, 2009 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/>.
+ */
+
+#ifndef AMIGA_COOKIES_H
+#define AMIGA_COOKIES_H
+#include "desktop/tree.h"
+#include "amiga/tree.h"
+
+void ami_cookies_initialise(void);
+void ami_cookies_free(void);
+
+struct treeview_window *cookies_window;
+#endif
diff --git a/frontends/amiga/ctxmenu.c b/frontends/amiga/ctxmenu.c
new file mode 100644
index 000000000..cc612da24
--- /dev/null
+++ b/frontends/amiga/ctxmenu.c
@@ -0,0 +1,607 @@
+/*
+ * Copyright 2015 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
+ * Intuition-based context menu operations
+ */
+
+#ifdef __amigaos4__
+#include <string.h>
+
+#include <stdlib.h>
+#include <proto/exec.h>
+#include <proto/intuition.h>
+
+#include <proto/bitmap.h>
+#include <images/bitmap.h>
+#include <proto/window.h>
+#include <classes/window.h>
+
+#include <intuition/menuclass.h>
+#include <reaction/reaction_macros.h>
+
+#include "utils/utils.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/nsoption.h"
+#include "utils/nsurl.h"
+#include "content/hlcache.h"
+#include "desktop/browser.h"
+#include "desktop/browser_history.h"
+#include "desktop/mouse.h"
+#include "desktop/searchweb.h"
+#include "desktop/textinput.h"
+
+#include "amiga/bitmap.h"
+#include "amiga/clipboard.h"
+#include "amiga/ctxmenu.h"
+#include "amiga/filetype.h"
+#include "amiga/gui.h"
+#include "amiga/libs.h"
+#include "amiga/plugin_hack.h"
+#include "amiga/theme.h"
+#include "amiga/utf8.h"
+
+
+enum {
+ AMI_CTX_ID_NONE = 0,
+
+ /* Text selection */
+ AMI_CTX_ID_SELCOPY,
+ AMI_CTX_ID_WEBSEARCH,
+
+ /* Links */
+ AMI_CTX_ID_URLOPENTAB,
+ AMI_CTX_ID_URLOPENWIN,
+ AMI_CTX_ID_URLDOWNLOAD,
+ AMI_CTX_ID_URLCOPY,
+
+ /* Objects */
+ AMI_CTX_ID_OBJSHOW,
+ AMI_CTX_ID_OBJCOPY,
+ AMI_CTX_ID_OBJCMD,
+
+ /* Frames */
+ AMI_CTX_ID_FRAMESHOW,
+
+ /* History */
+ AMI_CTX_ID_HISTORY,
+ AMI_CTX_ID_HISTORY0,
+ AMI_CTX_ID_HISTORY9F = AMI_CTX_ID_HISTORY0 + 19,
+
+ /* Tabs */
+ AMI_CTX_ID_TABNEW,
+ AMI_CTX_ID_TABCLOSE_OTHER,
+
+ AMI_CTX_ID_MAX
+};
+
+static Object *ctxmenu_obj = NULL;
+
+static struct Hook ctxmenu_item_hook[AMI_CTX_ID_MAX];
+static char *ctxmenu_item_label[AMI_CTX_ID_MAX];
+static char *ctxmenu_item_shortcut[AMI_CTX_ID_MAX];
+static Object *ctxmenu_item_image[AMI_CTX_ID_MAX];
+
+/****************************
+ * Menu item hook functions *
+ ****************************/
+
+/** Menu functions - called automatically by RA_HandleInput **/
+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);
+}
+
+HOOKF(void, ami_ctxmenu_item_websearch, APTR, window, struct IntuiMessage *)
+{
+ nserror ret = NSERROR_OK;
+ nsurl *url;
+
+ struct gui_window_2 *gwin = (struct gui_window_2 *)hook->h_Data;
+ char *sel = browser_window_get_selection(gwin->gw->bw);
+
+ ret = search_web_omni(sel, SEARCH_WEB_OMNI_SEARCHONLY, &url);
+ if (ret == NSERROR_OK) {
+ browser_window_navigate(gwin->gw->bw,
+ url,
+ NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ if (ret != NSERROR_OK) {
+ amiga_warn_user(messages_get_errorcode(ret), 0);
+ }
+
+ free(sel);
+}
+
+HOOKF(void, ami_ctxmenu_item_urlopentab, APTR, window, struct IntuiMessage *)
+{
+ struct browser_window *bw;
+ nsurl *url = (nsurl *)hook->h_Data;
+ struct gui_window_2 *gwin;
+
+ 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,
+ &bw);
+
+ if (error != NSERROR_OK)
+ amiga_warn_user(messages_get_errorcode(error), 0);
+}
+
+HOOKF(void, ami_ctxmenu_item_urlopenwin, APTR, window, struct IntuiMessage *)
+{
+ struct browser_window *bw;
+ nsurl *url = (nsurl *)hook->h_Data;
+ struct gui_window_2 *gwin;
+
+ 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,
+ &bw);
+
+ if (error != NSERROR_OK)
+ amiga_warn_user(messages_get_errorcode(error), 0);
+}
+
+HOOKF(void, ami_ctxmenu_item_urldownload, APTR, window, struct IntuiMessage *)
+{
+ nsurl *url = (nsurl *)hook->h_Data;
+ struct gui_window_2 *gwin;
+
+ GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
+
+ browser_window_navigate(gwin->gw->bw,
+ url,
+ browser_window_get_url(gwin->gw->bw),
+ BW_NAVIGATE_DOWNLOAD,
+ NULL,
+ NULL,
+ NULL);
+}
+
+HOOKF(void, ami_ctxmenu_item_urlcopy, APTR, window, struct IntuiMessage *)
+{
+ nsurl *url = (nsurl *)hook->h_Data;
+ ami_easy_clipboard(nsurl_access(url));
+}
+
+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,
+ hlcache_handle_get_url(hook->h_Data),
+ browser_window_get_url(gwin->gw->bw),
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+}
+
+HOOKF(void, ami_ctxmenu_item_objcopy, APTR, window, struct IntuiMessage *)
+{
+ struct bitmap *bm;
+ struct gui_window_2 *gwin;
+ GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
+
+ struct hlcache_handle *object = (struct hlcache_handle *)hook->h_Data;
+ if((bm = content_get_bitmap(object)))
+ {
+ ami_bitmap_set_url(bm, hlcache_handle_get_url(object));
+ ami_bitmap_set_title(bm, content_get_title(object));
+ ami_easy_clipboard_bitmap(bm);
+ }
+#ifdef WITH_NS_SVG
+ else if(ami_mime_compare(object, "svg") == true)
+ {
+ ami_easy_clipboard_svg(object);
+ }
+#endif
+}
+
+HOOKF(void, ami_ctxmenu_item_objcmd, APTR, window, struct IntuiMessage *)
+{
+ amiga_plugin_hack_execute((struct hlcache_handle *)hook->h_Data);
+}
+
+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,
+ hlcache_handle_get_url(hook->h_Data),
+ browser_window_get_url(gwin->gw->bw),
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+}
+
+/** Hooks for clicktab context menu entries **/
+HOOKF(void, ami_ctxmenu_item_tabnew, APTR, window, struct IntuiMessage *)
+{
+ struct gui_window_2 *gwin;
+
+ GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
+ ami_gui_new_blank_tab(gwin);
+}
+
+HOOKF(void, ami_ctxmenu_item_tabclose_other, APTR, window, struct IntuiMessage *)
+{
+ struct gui_window_2 *gwin;
+
+ GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
+ ami_gui_close_inactive_tabs(gwin);
+}
+
+/** Hook for history context menu entries **/
+HOOKF(void, ami_ctxmenu_item_history, APTR, window, struct IntuiMessage *)
+{
+ struct gui_window_2 *gwin;
+
+ GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
+
+ browser_window_history_go(gwin->gw->bw, (struct history_entry *)hook->h_Data, false);
+}
+
+
+/*************************
+ * Browser context menus *
+ *************************/
+
+/** Add an initialised item to a context menu **/
+static void ami_ctxmenu_add_item(Object *root_menu, int id, APTR data)
+{
+ ctxmenu_item_hook[id].h_Data = data;
+
+ IDoMethod(root_menu, OM_ADDMEMBER, MStrip,
+ MA_Type, T_ITEM,
+ MA_ID, id,
+ MA_Label, ctxmenu_item_label[id],
+ MA_Key, ctxmenu_item_shortcut[id],
+ MA_Image, ctxmenu_item_image[id],
+ MA_UserData, &ctxmenu_item_hook[id],
+ MEnd);
+}
+
+/** Hook function called by Intuition, creates context menu structure **/
+static uint32 ami_ctxmenu_hook_func(struct Hook *hook, struct Window *window, struct ContextMenuMsg *msg)
+{
+ 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 browser_window_features ccdata;
+ int mx = window->MouseX;
+ int my = window->MouseY;
+ int x, y;
+ char *sel;
+
+ if(msg->State != CM_QUERY) return 0;
+ if(nsoption_bool(kiosk_mode) == true) return 0;
+// check window is active
+
+ if(ctxmenu_obj != NULL) DisposeObject(ctxmenu_obj);
+
+ ctxmenu_obj = MStrip,
+ MA_Type, T_ROOT,
+ MA_AddChild, root_menu = MStrip,
+ MA_Type, T_MENU,
+ MA_Label, NULL, //"NetSurf",
+ MA_EmbeddedKey, FALSE,
+ MA_FreeImage, FALSE,
+ MEnd,
+ MEnd;
+
+ if(ami_mouse_to_ns_coords(gwin, &x, &y, mx, my) == false) {
+ /* Outside browser render area */
+ return 0;
+ }
+
+ browser_window_get_features(gwin->gw->bw, 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))) {
+
+ ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_SELCOPY, gwin);
+ ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_WEBSEARCH, gwin);
+
+ ctxmenu_has_content = true;
+ free(sel);
+ }
+
+ if(ccdata.link) {
+ if(ctxmenu_has_content == true)
+ ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_NONE, NULL);
+
+ ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_URLOPENTAB, ccdata.link);
+ ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_URLOPENWIN, ccdata.link);
+ ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_URLDOWNLOAD, ccdata.link);
+ ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_URLCOPY, ccdata.link);
+ ctxmenu_has_content = true;
+ }
+
+ if(ccdata.object) {
+ if(ctxmenu_has_content == true)
+ ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_NONE, NULL);
+
+ ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_OBJSHOW, ccdata.object);
+
+ if(content_get_type(ccdata.object) == CONTENT_IMAGE)
+ ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_OBJCOPY, ccdata.object);
+
+ if(ami_mime_content_to_cmd(ccdata.object))
+ ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_OBJCMD, ccdata.object);
+
+ ctxmenu_has_content = true;
+ }
+
+ if(ccdata.main && (ccdata.main != cc)) {
+ if(ctxmenu_has_content == true)
+ ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_NONE, NULL);
+
+ ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_FRAMESHOW, ccdata.main);
+
+ ctxmenu_has_content = true;
+ }
+
+ if(ctxmenu_has_content == true) {
+ msg->Menu = ctxmenu_obj;
+ ami_set_pointer(gwin, GUI_POINTER_DEFAULT, false);
+ }
+
+ return 0;
+}
+
+/** Initial menu item creation **/
+static void ami_ctxmenu_alloc_item(int id, const char *label, const char *key, const char *image, void *func)
+{
+ if(label == ML_SEPARATOR) {
+ ctxmenu_item_label[id] = ML_SEPARATOR;
+ } else {
+ ctxmenu_item_label[id] = ami_utf8_easy(messages_get(label));
+ }
+
+ if(key != NULL) {
+ ctxmenu_item_shortcut[id] = strdup(key);
+ } else {
+ ctxmenu_item_shortcut[id] = NULL;
+ }
+
+ if(image != NULL) {
+ ctxmenu_item_image[id] = BitMapObj,
+ BITMAP_Screen, scrn,
+ BITMAP_SourceFile, image,
+ BITMAP_Masking, TRUE,
+ BitMapEnd;
+
+ SetAttrs(ctxmenu_item_image[id],
+ BITMAP_Width, 16,
+ BITMAP_Height, 16,
+ TAG_DONE);
+ }
+
+ ctxmenu_item_hook[id].h_Entry = func;
+ ctxmenu_item_hook[id].h_Data = 0;
+}
+
+/** Exported interface documented in ctxmenu.h **/
+struct Hook *ami_ctxmenu_get_hook(APTR data)
+{
+ return AllocSysObjectTags(ASOT_HOOK,
+ ASOHOOK_Entry, (HOOKFUNC)ami_ctxmenu_hook_func,
+ ASOHOOK_Data, data,
+ TAG_DONE);
+}
+
+/** Exported interface documented in ctxmenu.h **/
+void ami_ctxmenu_release_hook(struct Hook *hook)
+{
+ FreeSysObject(ASOT_HOOK, hook);
+}
+
+/** Exported interface documented in ctxmenu.h **/
+void ami_ctxmenu_free(void)
+{
+ for(int i = 1; i < AMI_CTX_ID_MAX; i++) {
+ if((ctxmenu_item_label[i] != NULL) && (ctxmenu_item_label[i] != ML_SEPARATOR)) {
+ ami_utf8_free(ctxmenu_item_label[i]);
+ }
+ ctxmenu_item_label[i] = NULL;
+
+ if(ctxmenu_item_shortcut[i] != NULL) {
+ free(ctxmenu_item_shortcut[i]);
+ ctxmenu_item_shortcut[i] = NULL;
+ }
+
+ if(ctxmenu_item_image[i] != NULL) {
+ DisposeObject(ctxmenu_item_image[i]);
+ ctxmenu_item_image[i] = NULL;
+ }
+ }
+
+ if(ctxmenu_obj != NULL) DisposeObject(ctxmenu_obj);
+ ctxmenu_obj = NULL;
+}
+
+/** Exported interface documented in ctxmenu.h **/
+void ami_ctxmenu_init(void)
+{
+ ami_ctxmenu_alloc_item(AMI_CTX_ID_NONE, ML_SEPARATOR, NULL, NULL, NULL);
+
+ ami_ctxmenu_alloc_item(AMI_CTX_ID_SELCOPY, "CopyNS", "C", "TBImages:list_copy",
+ ami_ctxmenu_item_selcopy);
+ ami_ctxmenu_alloc_item(AMI_CTX_ID_WEBSEARCH, "SearchWeb", NULL, "TBImages:list_search",
+ ami_ctxmenu_item_websearch);
+
+ ami_ctxmenu_alloc_item(AMI_CTX_ID_URLOPENTAB, "LinkNewTab", NULL, "TBImages:list_tab",
+ ami_ctxmenu_item_urlopentab);
+ ami_ctxmenu_alloc_item(AMI_CTX_ID_URLOPENWIN, "LinkNewWin", NULL, "TBImages:list_app",
+ ami_ctxmenu_item_urlopenwin);
+ ami_ctxmenu_alloc_item(AMI_CTX_ID_URLDOWNLOAD, "LinkDload", NULL, "TBImages:list_save",
+ ami_ctxmenu_item_urldownload);
+ ami_ctxmenu_alloc_item(AMI_CTX_ID_URLCOPY, "CopyURL", NULL, "TBImages:list_copy",
+ ami_ctxmenu_item_urlcopy);
+
+ ami_ctxmenu_alloc_item(AMI_CTX_ID_OBJSHOW, "ObjShow", NULL, "TBImages:list_preview",
+ ami_ctxmenu_item_objshow);
+ ami_ctxmenu_alloc_item(AMI_CTX_ID_OBJCOPY, "CopyClip", NULL, "TBImages:list_copy",
+ ami_ctxmenu_item_objcopy);
+ ami_ctxmenu_alloc_item(AMI_CTX_ID_OBJCMD, "ExternalApp", NULL, "TBImages:list_tool",
+ ami_ctxmenu_item_objcmd);
+
+ ami_ctxmenu_alloc_item(AMI_CTX_ID_FRAMESHOW, "FrameOnly", NULL, "TBImages:list_preview",
+ ami_ctxmenu_item_frameshow);
+
+ ami_ctxmenu_alloc_item(AMI_CTX_ID_TABNEW, "NewTab", "T", "TBImages:list_tab",
+ ami_ctxmenu_item_tabnew);
+ ami_ctxmenu_alloc_item(AMI_CTX_ID_TABCLOSE_OTHER, "CloseInactive", "K", "TBImages:list_cancel",
+ ami_ctxmenu_item_tabclose_other);
+}
+
+/********************************
+ * History button context menus *
+ ********************************/
+
+/** Create menu entries from browser history **/
+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;
+ if(direction == AMI_CTXMENU_HISTORY_FORWARD) id += 10;
+
+ if(gwin->temp >= 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);
+
+ IDoMethod(history_root, OM_ADDMEMBER, MStrip,
+ MA_Type, T_ITEM,
+ MA_Label, browser_window_history_entry_get_title(entry),
+ MA_ID, id,
+ MA_Image, NULL,
+ MA_UserData, &ctxmenu_item_hook[id],
+ MEnd);
+
+ gwin->temp++;
+
+ return true;
+}
+
+/** Callback for browser_window_history_enumerate **/
+static bool ami_ctxmenu_history_back(const struct browser_window *bw,
+ int x0, int y0, int x1, int y1,
+ const struct history_entry *entry, void *user_data)
+{
+ return ami_ctxmenu_history(AMI_CTXMENU_HISTORY_BACK, (struct gui_window_2 *)user_data, entry);
+}
+
+/** Callback for browser_window_history_enumerate **/
+static bool ami_ctxmenu_history_forward(const struct browser_window *bw,
+ int x0, int y0, int x1, int y1,
+ const struct history_entry *entry, void *user_data)
+{
+ return ami_ctxmenu_history(AMI_CTXMENU_HISTORY_FORWARD, (struct gui_window_2 *)user_data, entry);
+}
+
+/** Exported interface documented in ctxmenu.h **/
+struct Menu *ami_ctxmenu_history_create(int direction, struct gui_window_2 *gwin)
+{
+ Object *obj;
+
+ if(gwin->history_ctxmenu[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,
+ MA_Type, T_ROOT,
+ MA_AddChild, MStrip,
+ MA_Type, T_MENU,
+ MA_ID, AMI_CTX_ID_HISTORY,
+ MA_Label, ctxmenu_item_label[AMI_CTX_ID_HISTORY],
+ MA_EmbeddedKey, FALSE,
+ //MA_FreeImage, FALSE,
+ MEnd,
+ MEnd;
+ } else {
+ for (int i = 0; i < 20; i++) {
+ obj = (Object *)IDoMethod(gwin->history_ctxmenu[direction],
+ MM_FINDID, 0, AMI_CTX_ID_HISTORY0 + i);
+ if(obj != NULL) IDoMethod(gwin->history_ctxmenu[direction], OM_REMMEMBER, obj);
+ }
+
+ gwin->temp = 0;
+
+ if(direction == AMI_CTXMENU_HISTORY_BACK) {
+ browser_window_history_enumerate_back(gwin->gw->bw, ami_ctxmenu_history_back, gwin);
+ } else {
+ browser_window_history_enumerate_forward(gwin->gw->bw, ami_ctxmenu_history_forward, gwin);
+ }
+ }
+
+ return (struct Menu *)gwin->history_ctxmenu[direction];
+}
+
+
+/**************************
+ * ClickTab context menus *
+ **************************/
+
+/** Exported interface documented in ctxmenu.h **/
+struct Menu *ami_ctxmenu_clicktab_create(struct gui_window_2 *gwin)
+{
+ Object *root_menu;
+
+ if(gwin->clicktab_ctxmenu != NULL) return (struct Menu *)gwin->clicktab_ctxmenu;
+
+ gwin->clicktab_ctxmenu = MStrip,
+ MA_Type, T_ROOT,
+ MA_AddChild, root_menu = MStrip,
+ MA_Type, T_MENU,
+ MA_Label, NULL,
+ MA_EmbeddedKey, FALSE,
+ MEnd,
+ MEnd;
+
+ 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;
+}
+
+
+#endif
+
diff --git a/frontends/amiga/ctxmenu.h b/frontends/amiga/ctxmenu.h
new file mode 100644
index 000000000..08a5fe582
--- /dev/null
+++ b/frontends/amiga/ctxmenu.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2015 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
+ * Interface to Intuition-based context menu operations
+ */
+
+#ifndef AMIGA_CTXMENU_H
+#define AMIGA_CTXMENU_H 1
+struct Hook;
+struct Menu;
+struct gui_window_2;
+
+enum {
+ AMI_CTXMENU_HISTORY_BACK = 0,
+ AMI_CTXMENU_HISTORY_FORWARD = 1
+};
+
+#ifdef __amigaos4__
+/**
+ * Initialise context menus code (allocate label text, etc)
+ * Must be called *after* NetSurf's screen pointer is obtained.
+ */
+void ami_ctxmenu_init(void);
+
+/**
+ * Cleanup context menus code
+ */
+void ami_ctxmenu_free(void);
+
+/**
+ * Get a Hook for WA_ContextMenuHook
+ *
+ * \param data ptr for the hook to use (struct gui_window_2 *)
+ * \returns pointer to a struct Hook
+ */
+struct Hook *ami_ctxmenu_get_hook(APTR data);
+
+/**
+ * Release a Hook for WA_ContextMenuHook
+ *
+ * \param hook ptr to hook
+ */
+void ami_ctxmenu_release_hook(struct Hook *hook);
+
+/**
+ * Create history context menu
+ * The first time this is run it will create an empty menu,
+ * Subsequent runs will (re-)populate with the history.
+ * This is to allow the pointer to be obtained before the browser_window is opened.
+ *
+ * \param direction AMI_CTXMENU_HISTORY_(BACK|FORWARD)
+ * \param gwin struct gui_window_2 *
+ * \returns pointer to menu (for convenience, is also stored in gwin structure)
+ * The returned pointer MUST be disposed of with DisposeObject before program exit.
+ */
+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)
+ * The returned pointer MUST be disposed of with DisposeObject before program exit.
+ */
+struct Menu *ami_ctxmenu_clicktab_create(struct gui_window_2 *gwin);
+
+#else //__amigaos4__
+inline void ami_ctxmenu_init(void) {}
+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;}
+#endif //__amigaos4__
+#endif //AMIGA_CTXMENU_H
+
diff --git a/frontends/amiga/datatypes.c b/frontends/amiga/datatypes.c
new file mode 100644
index 000000000..6018b107f
--- /dev/null
+++ b/frontends/amiga/datatypes.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2011 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/>.
+ */
+
+#ifdef WITH_AMIGA_DATATYPES
+#include "amiga/datatypes.h"
+
+nserror amiga_datatypes_init(void)
+{
+ nserror err = NSERROR_OK;
+
+ err = amiga_dt_picture_init();
+ if(err != NSERROR_OK) return err;
+
+#ifdef WITH_DTANIM
+ err = amiga_dt_anim_init();
+ if(err != NSERROR_OK) return err;
+#endif
+
+ err = amiga_dt_sound_init();
+ if(err != NSERROR_OK) return err;
+
+ return NSERROR_OK;
+}
+
+#endif
diff --git a/frontends/amiga/datatypes.h b/frontends/amiga/datatypes.h
new file mode 100644
index 000000000..00a9b4e5a
--- /dev/null
+++ b/frontends/amiga/datatypes.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2011 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/>.
+ */
+
+#ifndef NETSURF_AMIGA_DATATYPES_H_
+#define NETSURF_AMIGA_DATATYPES_H_
+
+#include "utils/config.h"
+#include "utils/errors.h"
+
+#ifdef WITH_AMIGA_DATATYPES
+
+nserror amiga_datatypes_init(void);
+
+nserror amiga_dt_picture_init(void);
+
+nserror amiga_dt_anim_init(void);
+
+nserror amiga_dt_sound_init(void);
+
+#else
+
+#define amiga_datatypes_init() NSERROR_OK
+
+#endif /* WITH_AMIGA_DATATYPES */
+
+#endif
diff --git a/frontends/amiga/dist/Install b/frontends/amiga/dist/Install
new file mode 100755
index 000000000..e8d9d0ed7
--- /dev/null
+++ b/frontends/amiga/dist/Install
@@ -0,0 +1,397 @@
+; Installation script for NetSurf
+
+(procedure p_append #filename #text
+ (set #file-path (tackon "ENVARC:launch-handler/URL" #protocol))
+ (set #def-file-path (tackon "ENVARC:launch-handler/URL/defaults" #protocol))
+
+ (if (exists #file-path)
+ (
+ (set #inc #file-path)
+ )
+ ;else
+ (
+ (set #inc #def-file-path)
+ )
+ )
+
+ (textfile
+ (dest #file-path)
+ (include #inc)
+ (append #text)
+ )
+)
+
+(procedure p_chk_launch-handler #protocol
+ (if (exists (tackon "ENVARC:launch-handler/URL" #protocol))
+ (
+ (run "C:Search >T:NS_Install.tmp " (tackon "ENVARC:launch-handler/URL" #protocol) " NetSurf" (safe))
+ )
+ ;else
+ (
+ (run "C:Search >T:NS_Install.tmp " (tackon "ENVARC:launch-handler/URL/defaults" #protocol) " NetSurf" (safe))
+ )
+ )
+
+ (set #has_entry (getsize "T:NS_Install.tmp"))
+)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Script execution starts here ;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(set osver (getversion "libs:version.library"))
+(set osver (/ osver 65536))
+
+(if (= @app-name "NetSurfAutoInstall") (set #AutoInstall 1))
+(set @app-name "NetSurf")
+
+(set #netsurf-readme "NetSurf.readme")
+(if (= (exists #netsurf-readme) 0)
+ (
+ (set #netsurf-readme "NetSurf_os3.readme")
+ (if (OR (>= osver 50) (< osver 44))
+ (abort "This archive is for AmigaOS 3.5 or 3.9 ONLY.")
+ )
+ )
+ ;else
+ (
+ (if (< osver 50)
+ (abort "This archive is for AmigaOS 4.0 and higher ONLY.")
+ )
+ )
+)
+
+(if (<> #AutoInstall 1) (welcome))
+
+; (hopefully temporary) workaround for a bug in Installer:
+(if (= @language "dutch") (set @askdir-help ""))
+
+(complete 0)
+
+(set @default-dest (getenv "AppPaths/NetSurf"))
+
+; If env-var did not exist, this is a first time install.
+; For novice users we must take care to put the files somewhere sensible.
+(if (= @default-dest "")
+ (
+ ; Workaround for Installer bug picking TEXTCLIP: as a sensible location
+ (if (= @default-dest "TextClip:") (set @default-dest "SYS:Internet"))
+
+ (if (= @user-level 0)
+ (
+ (makedir (tackon @default-dest "NetSurf") (infos))
+ (set @default-dest (tackon @default-dest "NetSurf"))
+ )
+ )
+ )
+)
+
+(set @default-dest
+ (askdir
+ (prompt "Where would you like to install NetSurf?\n"
+ "(a drawer WILL NOT be created)")
+ (help @askdir-help)
+ (default @default-dest)
+ )
+)
+
+(complete 5)
+
+(working "Checking existing installation...")
+(set #icon-exists (exists (tackon @default-dest "NetSurf.info")))
+
+(complete 10)
+
+(set #user (getenv "user"))
+(if (= #user "") (set #user "Default"))
+
+(set #user-dir (tackon (tackon @default-dest "Users") #user))
+(set #user-options (tackon #user-dir "Choices"))
+(set #options-exist (exists #user-options))
+(set #searchengines-exist (exists (tackon @default-dest "Resources/SearchEngines")))
+(set #user-hotlist (tackon #user-dir "Hotlist"))
+(set #hotlist-exist (exists #user-hotlist))
+(set #old-hotlist (tackon @default-dest "Resources/Hotlist"))
+(set #old-hotlist-exist (exists #old-hotlist))
+(set #aiss-theme "")
+
+(if (= #options-exist 0)
+ (
+ (if (exists "TBimages:" (noreq))
+ (set #aiss-theme "AISS")
+ )
+
+ (set #themename
+ (askchoice
+ (prompt "Please select theme")
+ (help "AISS theme requires AISS (and def_pointers for 32-bit "
+ "pointers), and will only be shown as an option if "
+ "AISS is installed.\n\n"
+ @askchoice-help)
+ (choices "Default" #aiss-theme)
+ (default 0)
+ )
+ )
+
+ (select #themename
+ (set #themeshort "Default")
+ (set #themeshort "AISS")
+ )
+
+ (set #theme (tackon "PROGDIR:Resources/Themes/" #themeshort))
+ )
+)
+
+(complete 15)
+
+(if (>= osver 53)
+ (
+ (if (= #AutoInstall 1)
+ (
+ (set #addlaunchhandler 0)
+ )
+ ;else
+ (
+ (set #addlaunchhandler
+ (askbool
+ (prompt "Add NetSurf to launch-handler? (recommended)")
+ (help "launch-handler is part of OS4.1 which opens URLs "
+ " by launching a web browser.\n\n"
+ "The installation will update the configuration of "
+ "OS4.1 to allow URLs to be opened by NetSurf.")
+ (default 1)
+ )
+ )
+ )
+ )
+ )
+ ;else
+ (
+ (set #addlaunchhandler 0)
+ )
+)
+
+(complete 20)
+
+(set #runfixfonts
+ (askbool
+ (prompt "Installer will run FixFonts after NetSurf is installed. "
+ "Unless you have a *very* good reason you should not skip this step.")
+ (help "FixFonts corrects inconsistencies in the Amiga FONTS: structure. "
+ "Running it will prevent NetSurf hitting problems when the fonts are scanned.")
+ (default 1)
+ (choices "Run FixFonts" "Skip")
+ )
+)
+
+(complete 25)
+
+(working "Installing NetSurf")
+
+(if (= #AutoInstall 0)
+ (
+ (copyfiles
+ (prompt "Copying NetSurf...")
+ (help @copyfiles-help)
+ (source "NetSurf")
+ (dest @default-dest)
+ (newname "NetSurf")
+ (optional "askuser" "force" "oknodelete")
+ (confirm "expert")
+ )
+ )
+;else
+ (
+ (run "CopyStore NetSurf" @default-dest)
+ )
+)
+
+(complete 40)
+
+(if #searchengines-exist
+ (rename (tackon @default-dest "Resources/SearchEngines") (tackon @default-dest "Resources/SearchEngines.backup"))
+)
+
+(run "c:filenote Rexx/CloseTabs.nsrx \"Close other tabs\"")
+(run "c:filenote Rexx/ViewSource.nsrx \"View source\"")
+
+(complete 50)
+
+(copyfiles
+ (prompt "Copying files")
+ (source "")
+ (choices "Resources" "Rexx" "NetSurf.guide" #netsurf-readme)
+ (help @copyfiles-help)
+ (dest @default-dest)
+ (infos)
+ (optional "nofail")
+; (all)
+)
+
+(complete 65)
+
+(copyfiles
+ (prompt "Copying additional documentation")
+ (source "")
+ (pattern "(COPYING|ChangeLog)")
+ (help @copyfiles-help)
+ (dest @default-dest)
+ (infos)
+ (optional "nofail")
+)
+
+(complete 70)
+
+(if #themeshort
+ (
+ (set #theme-icon
+ (tackon "Resources/Themes"
+ (tackon #themeshort "NetSurf.info")
+ )
+ )
+
+ (if (exists #theme-icon)
+ (
+ (copyfiles
+ (prompt "Copying theme icon")
+ (help @copyfiles-help)
+ (source #theme-icon)
+ (dest @default-dest)
+ )
+ )
+ )
+
+ (makedir #user-dir)
+
+ (textfile
+ (prompt "Setting default options")
+ (help @textfile-help)
+ (dest #user-options)
+ (append "theme:" #theme "\n")
+ (append "pubscreen_name:Workbench\n")
+ )
+
+ (if (= #hotlist-exist 0)
+ (if (= #old-hotlist-exist 1)
+ (
+ (copyfiles
+ (prompt "Migrating NetSurf 2.x Hotlist")
+ (help @copyfiles-help)
+ (source #old-hotlist)
+ (dest #user-dir)
+ (optional "askuser" "force" "oknodelete")
+ )
+ )
+ )
+ )
+ )
+)
+
+(complete 75)
+
+(if (= (exists "ENVARC:Sys/def_css.info") 0)
+ (copyfiles
+ (prompt "Copying default CSS icon")
+ (source "Resources/default.css.info")
+ (newname "def_css.info")
+ (help @copyfiles-help)
+ (dest "ENVARC:Sys")
+ (optional "nofail")
+ )
+)
+
+(complete 80)
+
+(if (>= osver 53)
+ (if (= (exists "Rexx:NetSurf") 0)
+ (
+ (textfile
+ (prompt "Creating NetSurf launch helper")
+ (help @textfile-help)
+ (dest "Rexx:NetSurf")
+ (append "/*\n"
+" * Copyright 2013 Chris Young <chris@unsatisfactorysoftware.co.uk>\n"
+" *\n"
+" * This file is part of NetSurf, http://www.netsurf-browser.org/\n"
+" *\n"
+" * NetSurf is free software; you can redistribute it and/or modify\n"
+" * it under the terms of the GNU General Public License as published by\n"
+" * the Free Software Foundation; version 2 of the License.\n"
+" *\n"
+" * NetSurf is distributed in the hope that it will be useful,\n"
+" * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+" * GNU General Public License for more details.\n"
+" *\n"
+" * You should have received a copy of the GNU General Public License\n"
+" * along with this program. If not, see <http://www.gnu.org/licenses/>.\n"
+" */\n"
+"\n"
+"/* This is a convenience script for launching NetSurf from the Shell.\n"
+" * If NetSurf is already running it will open the supplied URL in a new tab.\n"
+" * This can be used in URL Prefs in place of directly calling APPDIR:NetSurf.\n"
+" */\n"
+"\n"
+"options results\n"
+"parse arg url\n"
+"\n"
+"if show('P', 'NETSURF') then do\n"
+" address NETSURF 'OPEN' url 'NEWTAB'\n"
+" address NETSURF 'TOFRONT'\n"
+"end\n"
+"else do\n"
+" address command 'APPDIR:NetSurf URL' url\n"
+"end\n")
+ )
+ (protect "Rexx:NetSurf" "+se")
+ )
+ )
+)
+
+(complete 85)
+
+(if (= #addlaunchhandler 1)
+ (
+ (working "Adding NetSurf to launch-handler config")
+ (if (= (p_chk_launch-handler "FILE.LH") 0)
+ (p_append "FILE.LH" "ClientName=\"NETSURF\" ClientPath=\"Rexx:NetSurf\" CMDFORMAT=\"*\"file:///%s*\"\"")
+ )
+
+ (if (= (p_chk_launch-handler "HTTP.LH") 0)
+ (p_append "HTTP.LH" "ClientName=\"NETSURF\" ClientPath=\"Rexx:NetSurf\" CMDFORMAT=\"*\"http://%s*\"\"")
+ )
+
+ (if (= (p_chk_launch-handler "HTTPS.LH") 0)
+ (p_append "HTTPS.LH" "ClientName=\"NETSURF\" ClientPath=\"Rexx:NetSurf\" CMDFORMAT=\"*\"https://%s*\"\"")
+ )
+
+ (if (= (p_chk_launch-handler "WWW.LH") 0)
+ (p_append "WWW.LH" "ClientName=\"NETSURF\" ClientPath=\"Rexx:NetSurf\" CMDFORMAT=\"*\"http://www.%s*\"\"")
+ )
+
+; (if (= (p_chk_launch-handler "FTP.LH") 0)
+; (p_append "FTP.LH" "ClientName=\"NETSURF\" ClientPath=\"Rexx:NetSurf\" CMDFORMAT=\"*\"ftp://%s*\"\"")
+; )
+ )
+)
+
+(complete 90)
+
+(working "Running FixFonts")
+
+(if #runfixfonts
+ (
+ (run "SYS:System/FixFonts")
+ )
+)
+
+(complete 100)
+
+(if (= #AutoInstall 1)
+ (
+ (exit (quiet))
+ )
+ (
+ (exit)
+ )
+)
diff --git a/frontends/amiga/dist/Install.info b/frontends/amiga/dist/Install.info
new file mode 100644
index 000000000..944fcc69d
--- /dev/null
+++ b/frontends/amiga/dist/Install.info
Binary files differ
diff --git a/frontends/amiga/dist/NetSurf.guide b/frontends/amiga/dist/NetSurf.guide
new file mode 100755
index 000000000..a1c3941df
--- /dev/null
+++ b/frontends/amiga/dist/NetSurf.guide
@@ -0,0 +1,411 @@
+@database NetSurf.guide
+@author Chris Young
+@wordwrap
+
+@node Main "NetSurf"
+@{b}NetSurf@{ub} Amiga-specific documentation
+http://www.netsurf-browser.org
+
+@{" GUI " link GUI}
+@{" Preferences GUI " link Prefs}
+
+@{" Command line options " link CLI}
+@{" Options file " link Options}
+@{" Fonts " link Fonts}
+@{" ARexx port " link ARexx}
+@{" OpenURL/URL Prefs " link OpenURL}
+@{" Hotlist menu " link Hotlist}
+@{" Hotlist toolbar " link HotlistToolbar}
+@{" Local MIME types " link MIMETypes}
+@{" Keyboard controls " link Keyboard}
+
+@{" Optimising for speed " link Speed}
+
+@{" Credits " link Contact}
+@endnode
+
+@node GUI "Main window"
+NetSurf's main GUI consists of a toolbar across the top, an (optional) tab bar, an (optional) hotlist toolbar and the main browser area. It also encompasses a pull-down @{"menu" link Menu}.
+
+The toolbar buttons are, from left to right:
+@{b}Back@{ub} Go back one page in history. Right-clicking gives a menu showing the last ten pages visited.
+@{b}Forward@{ub} Go forward one page in history. Right-clicking gives a menu showing up to ten pages available.
+@{b}Stop@{ub} Stop loading the page.
+@{b}Reload@{ub} Reload the current page. Shift-clicking will reload all elements on the page.
+@{b}Home@{ub} Load the home page.
+
+The gadget to the right of the buttons is the URL bar to type web addresses into. On the far right is the search bar. Typing into here will search for the text using your default search provider (see preferences @{"Advanced tab" link Prefs-Advanced}.
+
+Below these is the (optional) @{"hotlist toolbar" link HotlistToolbar}.
+Below this is the (optional) tab bar. This usually only displays when more than one tab is open, but can be set in @{"preferences" link Prefs-Tabs} to be always present. At the far right is a button to open a new tab. On OS4.0 the current tab can be closed using the button on the far left. On OS4.1 the close gadget for the tab is embedded in the tab itself.
+
+The rest of the window is taken up with the @{"browser rendering area" link Browser}. This is where the pages visited will be displayed.
+@endnode
+
+@node Browser
+@toc GUI
+This is the main browser rendering area.
+
+Drag and drop is supported throughout, so files can be dropped onto text fields, text on pages can be highlighted and dragged to Workbench or text fields. Other elements can be saved by dragging them to Workbench with Ctrl or Shift held down.
+
+Note that dragging to Workbench only works when NetSurf is running on the Workbench screen.
+@endnode
+
+@node Menu "Menu"
+@toc GUI
+Project Browser Edit @{"Hotlist" link Hotlist} @{"ARexx" link arexx}
+
+@endnode
+
+@node Prefs "Preferences GUI"
+@{"General" link Prefs-General} @{"Display" link Prefs-Display} @{"Connection" link Prefs-Connection} @{"Rendering" link Prefs-Rendering} @{"Fonts" link Prefs-Fonts} @{"Cache" link Prefs-Cache} @{"Tabs" link Prefs-Tabs} @{"Advanced" link Prefs-Advanced} @{"Export" link Prefs-Export}
+@endnode
+
+@node Prefs-General "Prefs - General"
+@toc Prefs
+@remark todo
+@endnode
+
+@node Prefs-Display "Prefs - Display"
+@toc Prefs
+@remark todo
+@{"Themes" link Themes}
+@endnode
+
+@node Prefs-Connection "Prefs - Connection"
+@toc Prefs
+@remark todo
+@endnode
+
+@node Prefs-Rendering "Prefs - Rendering"
+@toc Prefs
+@remark todo
+@endnode
+
+@node Prefs-Fonts "Prefs - Fonts"
+@toc Prefs
+@remark todo
+See @{"Fonts" link Fonts}
+@endnode
+
+@node Prefs-Cache "Prefs - Cache"
+@toc Prefs
+@remark todo
+@endnode
+
+@node Prefs-Tabs "Prefs - Tabs"
+@toc Prefs
+@remark todo
+@endnode
+
+@node Prefs-Advanced "Prefs - Advanced"
+@toc Prefs
+@remark todo
+@endnode
+
+@node Prefs-Export "Prefs - Export"
+@toc Prefs
+This section contains options for exporting to PDF. It is not enabled in current builds of NetSurf.
+@endnode
+
+@node cli "Command line options"
+NetSurf NSOPTS/M,URL/K,USERSDIR/K,FORCE/S
+
+Where:
+URL = Address of page to open on startup
+USERSDIR = Locations of user directories (see @{"tooltypes" link tooltypes})
+FORCE = Force new instance of NetSurf to open (has some limitations, use for debugging only)
+NSOPTS = Catches everything else and passes it to the NetSurf core command line parser
+@endnode
+
+@node tooltypes "ToolTypes"
+Supported tooltypes are:
+
+@{b}USERSDIR@{ub}
+Location of the Users directory. This should contain the "Users" part of the path, NetSurf will append the username. Defaults to PROGDIR:Users.
+The user directories contain user-specific preferences and cache data. Always locate them on fast, non-volatile, writeable media.
+
+@{b}USER@{ub}
+Current user. Defaults to the value of the USER env-var, or Default.
+@endnode
+
+@node options "Options file"
+The options file is stored in @{"Users/Default/Choices" link Users/Default/Choices/Main} by default. Most of the settings can be changed from within NetSurf by selecting Edit preferences from the Settings menu.
+
+There are a couple of Amiga-specific options which can only be changed directly in the file. These are:
+
+@{b}kiosk_mode@{ub} No gadgets
+@{b}printer_unit@{ub} Specifies which printer.device unit to print to
+@{b}drag_save_icons@{ub} Enables displaying Workbench-style transparent icons under the pointer when performing drag saves (ctrl-drag of objects available if NetSurf is running on the Workbench screen) and text selection drags. If set to 0 the pointer style will change instead. OS 4.0 users may want to set this to 0 as icons will appear opaque and obscure the drop position.
+@{b}monitor_aspect_x@{ub}/@{b}monitor_aspect_y@{ub} Correct aspect ratio for displays (default of 0 means "assume square pixels").
+@{b}screen_compositing@{ub} Use compositing on NetSurf's own screen. 0=disable, 1=enable, 2=default (NB: This is indirectly modified by changing the "simple refresh" option in the GUI)
+@{b}resize_with_contents@{ub} Set to 1 to respect GUI prefs' "resize with contents" option. Default is to use old-style "resize on release"
+@{b}reformat_delay@{ub} Sets a delay on performing content reformats (eg. if the window has been resized). Set to a higher value to make "resize with contents" more responsive. Defaults to 0 (immediate).
+@{b}redraw_tile_size_x@{ub}/@{b}redraw_tile_size_y@{ub} Specify the size of the off-screen bitmap. Higher will speed up redraws at the expense of memory. 0 disables tiling (will use a bitmap at least the size of the screen NetSurf is running on)
+@{b}web_search_width@{ub} Defaults to 0. Larger values will increase the size of the web search gadget next to the URL bar.
+
+@{b}mask_alpha@{ub} Threshold to use when determining which alpha values to convert to full transparency (0 - 255, where 255 will convert even opaque pixels to transparent). Defaults to 50 (0x32). This is only used in palette-mapped modes where alpha blending is not currently supported.
+
+@{b}url_file@{ub} Path to URL database file
+@{b}hotlist_file@{ub} Path to Hotlist file
+@{b}arexx_dir@{ub} Path to ARexx scripts dir
+@{b}arexx_startup@{ub} ARexx script to run at startup (in above dir)
+@{b}arexx_shutdown@{ub} ARexx script to run on quit (in above dir)
+@endnode
+
+@node Fonts
+The font to use for each font type can be defined in NetSurf's options. OS4 NetSurf supports soft styles for bold and italic, however designed fonts look better and it is highly recommended to set them as follows:
+
+Within @{"TypeManager" system "SYS:System/TypeManager"} select a font being used by NetSurf and click on Modify.
+On the Files tab, Font family section, choose the @{b}bold@{ub}, @{i}italic@{ui} and @{b}@{i}bold-italic@{ui}@{ub} version of the font.
+Click Save.
+
+@{b}Unicode fallback font@{ub}
+
+If the font NetSurf is trying to use does not contain a specific character used on a web page, it will try the Unicode/fallback font. It is recommended to use a font which either:
+(a) Contains as complete a Unicode character set as possible or
+(b) Is complete for the pages you are likely to visit (eg. if you visit a lot of Japanese pages, set the Unicode fallback font to one with a complete Japanese character set)
+
+For most users, installing and selecting @{"Code2000" rxs "address netsurf 'open http://code2000.sf.net'"} or @{"Bitstream Cyberbit" rxs "address netsurf 'open http://ftp.netscape.com/pub/communicator/extras/fonts/windows/'"} is the best option.
+
+Additional fall-back fonts can be provided since NetSurf 3.0. These need to go into Users/user/Choices as a comma-separated list, for the font_unicode option.
+
+NB: Since NetSurf 3.0, NetSurf will scan the provided Unicode fonts, and the rest of the system fonts, on first startup. Setting font_unicode_only:1 will prevent fonts not in the preferred Unicode fonts list from being scanned or used as fallback fonts. If the system fonts or NetSurf's fallback fonts list changes, this cache will need to be re-generated. This can be forced by deleting the font glyph cache (which defaults to Users/user/FontGlyphCache).
+
+Since NetSurf 3.4, Unicode glyphs above 0xFFFF are supported. These are mainly used for Emoji. The option to specify a fallback font for this range is font_surrogate - there is no scanning of system fonts. If @{"Symbola" rxs "address netsurf 'open http://users.teilar.gr/~g1951d/'"} font is installed it will be selected automatically.
+
+@{b}Font sizes@{ub}
+
+The default and minimum font sizes can also be set.
+NB: The resolution setting on the "Rendering" tab in NetSurf's preferences affects how big text appears on screen (the conversion between point and pixel sizes) amongst other things. To find the correct value, divide the number of pixels on the screen vertically by the physical height of the screen in inches (horizontal resolution is calculated automatically if NetSurf is running on a custom screen, square pixels are assumed on all other screens).
+If the monitor is widescreen, monitor_aspect_x and monitor_aspect_y values in Users/Default/Choices may also need modifying.
+@endnode
+
+@node Themes
+AmigaOS NetSurf supports basic theming of gadget imagery. Themes live in the Resources/Themes directory, and two are included by default:
+
+Default - default theme with no external dependencies.
+AISS - theme using Mason's AISS images for buttons, and the def_pointers package for 32-bit pointer images.
+
+The file "Theme" in the theme directory contains the files used for that theme. See @{"Default Theme file" link Resources/Themes/Default/Theme/Main} for more details.
+
+Theme directories should be copied and renamed if themes are modified, as update installation of NetSurf will overwrite any changes.
+AmigaOS NetSurf themes are not compatible with NetSurf for other platforms.
+@endnode
+
+@node arexx "ARexx port"
+NetSurf's ARexx port is called NETSURF.
+
+Commands are:
+
+@{b}OPEN URL/A,NEW=NEWWINDOW/S,NEWTAB/S,SAVEAS/K,W=WINDOW/K/N,T=TAB/K/N@{ub}
+Opens URL in current window or a new window/tab if NEWWINDOW/NEWTAB is specified. Saves the location without displaying if SAVEAS and a filename is specified (SAVEAS available in 2.6325)
+Note that if the URL is non-ASCII it is expected to be encoded in UTF-8 (file: references should always be in local charset due to filesystem limitations). Usually this is not relevant, as all normalised URLs will be in their ASCII form.
+
+@{b}SAVE FILENAME/A,W=WINDOW/K/N,T=TAB/K/N@{ub} (2.6027)
+Saves current page source to FILENAME
+
+@{b}QUIT@{ub}
+Quits NetSurf
+
+@{b}TOFRONT@{ub}
+Brings NetSurf's screen to the front
+
+@{b}GETURL W=WINDOW/K/N,T=TAB/K/N@{ub}
+Puts the URL displayed in the current window/tab into RESULT
+
+@{b}GETTITLE W=WINDOW/K/N,T=TAB/K/N@{ub}
+Puts the title of the page displayed in the current window/tab into RESULT
+
+@{b}GETSCREENNAME@{ub} (2.8303)
+Puts the name of the screen NetSurf is running on into RESULT.
+
+@{b}BACK W=WINDOW/K/N,T=TAB/K/N@{ub} (2.10626)
+Move back one page in history.
+
+@{b}FORWARD W=WINDOW/K/N,T=TAB/K/N@{ub} (2.10626)
+Move forward one page in history.
+
+@{b}HOME W=WINDOW/K/N,T=TAB/K/N@{ub} (2.10626)
+Move back to the home page.
+
+@{b}RELOAD FORCE/S,W=WINDOW/K/N,T=TAB/K/N@{ub} (2.10626)
+Reload the current page, FORCE will do a full reload.
+
+@{b}CLOSE W=WINDOW/K/N,T=TAB/K/N@{ub} (2.10718)
+Close the current page. A window or window and tab can be specified. Note that when a tab is closed, the tab number of tabs to the right of it will change, and the currently active tab may also change. If the last tab or window is closed, NetSurf will usually exit. Make sure you account for these situations in your code.
+
+@{b}VERSION VERSION/N REVISION/N RELEASE/S@{ub}
+Returns the current version of NetSurf in RESULT. You can also do version checking by supplying a VERSION and optional REVISION to check against. If the version of NetSurf is the same or higher 1 will be returned, if it is older 0. If RELEASE is specified, the command operates on the release version rather than the internal version number.
+
+@{b}ACTIVE T=TAB/S@{ub} (2.10718)
+Returns the active window (or tab if TAB is specified). Commands automatically operate on the active window/tab so you do not normally need to use this.
+
+@{b}WINDOWS W=WINDOW/K/N@{ub} (2.10656)
+Puts the number of windows into RESULT. If the WINDOW keyword is specified, will put the number of tabs in that window into RESULT.
+
+@{b}HOTLIST A=ACTION/A@{ub} (3.1 - CI build #471)
+Possible actions for the hotlist window are OPEN and CLOSE.
+
+The W=WINDOW/K/N,T=TAB/K/N parameters were added in 2.10656 and allow targetting a window other than the current one. Both WINDOW and TAB must be specified (TAB=1 for tabless window) except in the special case of the CLOSE command.
+
+The ARexx menu will be populated with scripts named #?.nsrx in @{"arexx_dir" link options 12}, up to a maximum of 20 entries. The titles of these entries will be the comments field of the file (or the filename if comments field is empty).
+
+Special scripts @{"arexx_startup" link options 13} and @{"arexx_shutdown" link options 14} will be run at startup and shutdown of NetSurf. These will execute after NetSurf has fully initialised with the initial window and before NetSurf frees resources (ie. at the last stage of startup, and the first stage of shutdown)
+@endnode
+
+@node OpenURL
+@{b}OpenURL configuration@{ub}
+
+Click Add on the Browsers page and fill in the details as follows:
+Name: NetSurf
+Path: NetSurf URL="%u"
+ARexx port: NETSURF
+Show:
+To front: TOFRONT
+Open URL: OPEN "%u"
+New window: OPEN "%u" NEW
+
+On the Misc tab, please ensure "Send mailto: URLs to email application" is set.
+
+@{b}URL Prefs (OS4.1)@{ub}
+Under OS4.1 Update 1, launch-handler is used in preference to OpenURL. The
+Installer script can add the relevant configuration to launch URLs in NetSurf.
+Please ensure your email application is configured in URL Prefs for mailto:
+links clicked within NetSurf.
+
+Note that a helper script is installed in S:ARexx which can be used instead of
+the main executable, to stop the NetSurf executable from being loaded again if
+it is already running.
+@endnode
+
+@node hotlist "Hotlist menu"
+Items from the hotlist can be added to the Hotlist menu as follows:
+
+Select Hotlist => Show hotlist...
+
+Items in the "Hotlist menu" folder node, up to a maximum (currently) of 40 items, will be added to the Hotlist menu, within the limits of the Intuition menu system.
+
+Items in folders within the Menu folder node will be converted to subitems in the menu.
+
+Folders more than one level down in the heirarchy will become menu items with no action. Items deeper will not be included in the menu at all (until we switch to using menuclass).
+
+Folders with no items in them will show up disabled in the menu. If they are named "--" they will be displayed as separator bars.
+
+eg.
+
+- Hotlist Menu
+ |
+ +- Netsurf
+ | |
+ | +- NetSurf Homepage
+ | |
+ | +- More NetSurf links
+ | |
+ | +- NetSurf bugtracker
+ |
+ +- --
+ |
+ +- Google
+
+Will look something like the following within the menu:
+
+|NetSurf »| - |NetSurf Homepage |
+|---------| |More NetSurf links|
+|Google |
+
+@endnode
+
+@node HotlistToolbar "Hotlist toolbar"
+A toolbar for frequently-accessed sites can be added to the main window. To do show, follow these steps:
+
+* Select Show Hotlist from the Hotlist menu
+The Hotlist window will be displayed.
+
+* Locate the "Hotlist toolbar" folder in the tree (NetSurf creates this when it starts up)
+
+* Move or create entries in this folder. Any entries directly inside the Hotlist toolbar folder will appear on the toolbar when the hotlist window is closed. If it is empty the toolbar will disappear to save space.
+
+Note that sub-folders are not currently supported on the toolbar.
+
+@endnode
+
+@node mimetypes "Local MIME Types"
+NetSurf determines the MIME types of local files primarily by checking the icon of the file. If the icon is not found it will check the default icon for the file type.
+
+It looks for a tooltype MIMETYPE and, if found, will use the contents as the filetype of the file. If not found it will use datatypes.library and do a reverse lookup based on the contents of Resources/mimetypes[.user]
+
+The Installer script will set the MIMETYPE tooltype on basic relevant default filetype icons. If you get problems:
+* If the file has a real icon, add MIMETYPE=<MIME type of file> to the tooltypes.
+* If the file does not have an icon, check:
+1. The file type is showing in DefIcons Prefs editor
+2. The icon ENVARC:Sys/def_<filetype> contains the MIMETYPE tooltype.
+@endnode
+
+@node Keyboard "Keyboard Controls"
+This is a list of the keyboard shortcuts used in NetSurf
+
+- RAmiga + R or F5 (reload the current page)
+- PageUp/Down/Space (scroll up/down to one page)
+- Home/End (go to top/bottom of the page)
+- Left/Right/Up/Down (scroll the page)
+- RAmiga + U (activate the URL bar)
+- Alt + Left/Right (keyboard navigation of tabs)
+- Backspace (go back to one page in history)
+
+Keyboard shortcuts used in NetSurf menu
+
+- RAmiga + N (open a new window)
+- RAmiga + T (open a new tab)
+- RAmiga + O (open a local file)
+- RAmiga + S (save source page)
+- RAmiga + K (close current tab)
+- RAmiga + P (print a page)
+- RAmiga + ? (about NetSurf)
+- RAmiga + Q (quit NetSurf)
+- RAmiga + X (cut)
+- RAmiga + C (copy)
+- RAmiga + V (paste)
+- RAmiga + A (select all)
+- RAmiga + Z (undo)
+- RAmiga + Y (redo)
+- RAmiga + F (find a string/text)
+- RAmiga + - or F9 (decrease scale)
+- RAmiga + = or F8 (normal scale)
+- RAmiga + + or F10 (increase scale)
+- RAmiga + B (add link to bookmark)
+- RAmiga + H (show bookmarks)
+- RAmiga + E (execute script)
+
+@endnode
+
+@node Speed "Optimising for speed"
+There are a number of options which can be changed that will affect the speed of NetSurf's rendering. Here are a list of the fastest settings which may help decrease rendering time on slower platforms:
+
+@{lindent 2}* Ensure NetSurf is running on a @{b}32-bit screen@{ub} if possible. NetSurf down-converts from 32-bit ARGB for display, which can impact performance.@{lindent 0}
+
+@{lindent 2}* In preferences, General tab, enable @{b}Fast scrolling@{ub}.@{lindent 0}
+
+@{lindent 2}* In preferences, Rendering tab set:
+@{b}Cache native versions@{ub} to @{b}Scaled@{ub} (or preferably @{b}All@{ub}, but this will use more graphics mem, and scaling images is a bigger performance hit)
+Deselect @{b}Higher quality scaling@{ub}, this will be very slow if not done in hardware.@{lindent 0}
+
+@{lindent 2}* In @{"Options" link Options}, increase redraw_tile_size_x/y (increasing this value uses more graphics mem)@{lindent 0}
+
+@{lindent 2}* In @{"Options" link Options}, set font_antialiasing:0@{lindent 0}
+@endnode
+
+@node contact "Credits"
+NetSurf was ported to AmigaOS 4 by Chris Young
+chris\@unsatisfactorysoftware.co.uk
+
+The pointer images, AISS theme icon and Throbber were drawn by Martin 'Mason' Merz.
+http://www.masonicons.de
+
+The default theme icon was adapted from the NetSurf logo by Marko K. Seppänen.
+
+All other code and files are the same for all platforms and credited in the files and/or on the NetSurf website.
+http://www.netsurf-browser.org
+
+The source code can be obtained from http://source.netsurf-browser.org or (in the event the service is unavailable) chris\@unsatisfactorysoftware.co.uk or any other of the NetSurf developers.
+@endnode
diff --git a/frontends/amiga/dist/NetSurf.guide.info b/frontends/amiga/dist/NetSurf.guide.info
new file mode 100644
index 000000000..d6d529d31
--- /dev/null
+++ b/frontends/amiga/dist/NetSurf.guide.info
Binary files differ
diff --git a/frontends/amiga/dist/Rexx.info b/frontends/amiga/dist/Rexx.info
new file mode 100644
index 000000000..908b01843
--- /dev/null
+++ b/frontends/amiga/dist/Rexx.info
Binary files differ
diff --git a/frontends/amiga/dist/Rexx/CloseTabs.nsrx b/frontends/amiga/dist/Rexx/CloseTabs.nsrx
new file mode 100644
index 000000000..276ae11a3
--- /dev/null
+++ b/frontends/amiga/dist/Rexx/CloseTabs.nsrx
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2010 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/>.
+ */
+
+/* This script closes all tabs other than the current one */
+
+options results
+address netsurf
+
+/* Find the currently active window and tab */
+active
+awin = result
+active tab
+atab = result
+
+/* Find out how many tabs are in the active window */
+windows window awin
+tabs = result
+
+if tabs=1 then exit
+
+/* Close all tabs above the current one */
+do t=tabs to atab+1 by -1
+ close window awin tab t
+end
+
+/* Close all tabs below the current one
+ * NB: The active tab number will change when lower-numbered tabs are closed!
+ */
+
+do t=1 to atab-1
+ close window awin tab 1
+end
diff --git a/frontends/amiga/dist/Rexx/SMTube.nsrx b/frontends/amiga/dist/Rexx/SMTube.nsrx
new file mode 100644
index 000000000..5f1ab209a
--- /dev/null
+++ b/frontends/amiga/dist/Rexx/SMTube.nsrx
@@ -0,0 +1,29 @@
+/*
+ * 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/>.
+ */
+
+/* This script launches SMTube (OS4Depot:video/play/smtube) */
+
+options results
+geturl
+
+if open('smtube','APPDIR:SMTube','R') then do
+ close('smtube')
+ address COMMAND 'APPDIR:SMTube' result
+end
+else
+ address command 'requestchoice >NIL: "NetSurf" "SMTube must be installed for this script to function.*n*nIt can be downloaded from OS4Depot:video/play/smtube" "OK"'
diff --git a/frontends/amiga/dist/Rexx/ShowTitles.nsrx b/frontends/amiga/dist/Rexx/ShowTitles.nsrx
new file mode 100644
index 000000000..27de74122
--- /dev/null
+++ b/frontends/amiga/dist/Rexx/ShowTitles.nsrx
@@ -0,0 +1,18 @@
+/* Show all NetSurf windows and tabs open */
+
+options results
+address netsurf
+
+windows
+wins = result
+
+do w=1 to wins
+ windows window w
+ tabs = result
+ say "Window" w "(" || tabs "tabs)"
+
+ do t=1 to tabs
+ gettitle window w tab t
+ say " Tab" t || ":" result
+ end
+end
diff --git a/frontends/amiga/dist/Rexx/viewsource.nsrx b/frontends/amiga/dist/Rexx/viewsource.nsrx
new file mode 100755
index 000000000..755e7a3b6
--- /dev/null
+++ b/frontends/amiga/dist/Rexx/viewsource.nsrx
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2009 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/>.
+ */
+
+/* This scripts shows the source of the current page in Notepad */
+options results
+
+'save t:nstmp'
+getscreenname
+address command 'sys:utilities/notepad t:nstmp pubscreen' result
diff --git a/frontends/amiga/download.c b/frontends/amiga/download.c
new file mode 100644
index 000000000..a0bc5c47b
--- /dev/null
+++ b/frontends/amiga/download.c
@@ -0,0 +1,451 @@
+/*
+ * Copyright 2008-2010 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 <string.h>
+
+#include <proto/wb.h>
+#include <proto/asl.h>
+#include <proto/exec.h>
+#include <proto/dos.h>
+#include <proto/intuition.h>
+#include <proto/utility.h>
+#include <proto/icon.h>
+#ifdef __amigaos4__
+#include <proto/application.h>
+#endif
+
+#include <workbench/icon.h>
+
+#include <proto/window.h>
+#include <proto/layout.h>
+
+#include <proto/fuelgauge.h>
+#include <classes/window.h>
+#include <gadgets/fuelgauge.h>
+#include <gadgets/layout.h>
+
+#include <reaction/reaction_macros.h>
+
+#include "utils/errors.h"
+#include "utils/nsurl.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "utils/nsoption.h"
+#include "utils/string.h"
+#include "desktop/download.h"
+#include "desktop/save_complete.h"
+#include "desktop/browser.h"
+#include "desktop/mouse.h"
+#include "desktop/gui_window.h"
+#include "desktop/gui_download.h"
+#include "image/ico.h"
+
+#include "amiga/gui.h"
+#include "amiga/download.h"
+#include "amiga/object.h"
+#include "amiga/bitmap.h"
+#include "amiga/icon.h"
+#include "amiga/file.h"
+#include "amiga/drag.h"
+#include "amiga/iff_dr2d.h"
+#include "amiga/libs.h"
+#include "amiga/misc.h"
+#include "amiga/theme.h"
+#include "amiga/utf8.h"
+
+struct gui_download_window {
+ struct nsObject *node;
+ struct Window *win;
+ Object *objects[GID_LAST];
+ BPTR fh;
+ uint32 size;
+ uint32 downloaded;
+ struct dlnode *dln;
+ struct browser_window *bw;
+ struct download_context *ctx;
+ const char *url;
+ char fname[1024];
+ int result;
+};
+
+enum {
+ AMINS_DLOAD_OK = 0,
+ AMINS_DLOAD_ERROR,
+ AMINS_DLOAD_ABORT,
+};
+
+int downloads_in_progress = 0;
+
+static struct gui_download_window *gui_download_window_create(download_context *ctx,
+ struct gui_window *gui)
+{
+ const char *url = nsurl_access(download_context_get_url(ctx));
+ unsigned long total_size = download_context_get_total_length(ctx);
+ struct gui_download_window *dw;
+ char *dl_filename = ami_utf8_easy(download_context_get_filename(ctx));
+ APTR va[3];
+
+ dw = ami_misc_allocvec_clear(sizeof(struct gui_download_window), 0);
+
+ if(gui && (!IsListEmpty(&gui->dllist)) && (dw->dln = (struct dlnode *)FindName(&gui->dllist,url)))
+ {
+ strcpy(dw->fname, dw->dln->filename);
+ free(dw->dln->node.ln_Name);
+ dw->dln->node.ln_Name = NULL;
+ }
+ else
+ {
+ if(AslRequestTags(savereq,
+ ASLFR_Window, gui->shared->win,
+ ASLFR_SleepWindow, TRUE,
+ ASLFR_TitleText, messages_get("NetSurf"),
+ ASLFR_Screen, scrn,
+ 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))
+ {
+ FreeVec(dw);
+ return NULL;
+ }
+ }
+ else
+ {
+ FreeVec(dw);
+ return NULL;
+ }
+ }
+
+ if(dl_filename) ami_utf8_free(dl_filename);
+ dw->size = total_size;
+ dw->downloaded = 0;
+ if(gui) dw->bw = gui->bw;
+ dw->url = url;
+
+ va[0] = (APTR)dw->downloaded;
+ va[1] = (APTR)dw->size;
+ va[2] = 0;
+
+ if(!(dw->fh = FOpen((STRPTR)&dw->fname,MODE_NEWFILE,0)))
+ {
+ FreeVec(dw);
+ return NULL;
+ }
+
+ dw->objects[OID_MAIN] = WindowObj,
+ WA_ScreenTitle, ami_gui_get_screen_title(),
+ WA_Title, dw->url,
+ WA_Activate, TRUE,
+ WA_DepthGadget, TRUE,
+ WA_DragBar, TRUE,
+ WA_CloseGadget, FALSE,
+ WA_SizeGadget, TRUE,
+ WA_PubScreen,scrn,
+ WINDOW_SharedPort,sport,
+ 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,
+ GA_Text,messages_get("amiDownload"),
+ FUELGAUGE_Min,0,
+ FUELGAUGE_Max,total_size,
+ FUELGAUGE_Level,0,
+ FUELGAUGE_Ticks,11,
+ FUELGAUGE_ShortTicks,TRUE,
+ FUELGAUGE_VarArgs,va,
+ FUELGAUGE_Percent,FALSE,
+ FUELGAUGE_Justification,FGJ_CENTER,
+ FuelGaugeEnd,
+ CHILD_NominalSize,TRUE,
+ CHILD_WeightedHeight,0,
+ LAYOUT_AddChild, dw->objects[GID_CANCEL] = ButtonObj,
+ GA_ID,GID_CANCEL,
+ GA_RelVerify,TRUE,
+ GA_Text,messages_get("Abort"),
+ GA_TabCycle,TRUE,
+ ButtonEnd,
+ EndGroup,
+ EndWindow;
+
+ dw->win = (struct Window *)RA_OpenWindow(dw->objects[OID_MAIN]);
+ dw->ctx = ctx;
+
+ dw->node = AddObject(window_list,AMINS_DLWINDOW);
+ dw->node->objstruct = dw;
+
+ downloads_in_progress++;
+
+ return dw;
+}
+
+static nserror gui_download_window_data(struct gui_download_window *dw,
+ const char *data, unsigned int size)
+{
+ APTR va[3];
+ if(!dw) return NSERROR_SAVE_FAILED;
+
+ FWrite(dw->fh,data,1,size);
+
+ dw->downloaded = dw->downloaded + size;
+
+ va[0] = (APTR)dw->downloaded;
+ va[1] = (APTR)dw->size;
+ va[2] = 0;
+
+ if(dw->size)
+ {
+ RefreshSetGadgetAttrs((struct Gadget *)dw->objects[GID_STATUS], dw->win, NULL,
+ FUELGAUGE_Level, dw->downloaded,
+ GA_Text, messages_get("amiDownload"),
+ FUELGAUGE_VarArgs, va,
+ TAG_DONE);
+ }
+ else
+ {
+ RefreshSetGadgetAttrs((struct Gadget *)dw->objects[GID_STATUS], dw->win, NULL,
+ FUELGAUGE_Level, dw->downloaded,
+ GA_Text, messages_get("amiDownloadU"),
+ FUELGAUGE_VarArgs, va,
+ TAG_DONE);
+ }
+
+ return NSERROR_OK;
+}
+
+static void gui_download_window_done(struct gui_download_window *dw)
+{
+ struct dlnode *dln,*dln2 = NULL;
+ struct browser_window *bw;
+ bool queuedl = false;
+
+ if(!dw) return;
+ bw = dw->bw;
+
+ if((nsoption_bool(download_notify)) && (dw->result == AMINS_DLOAD_OK))
+ {
+ Notify(ami_gui_get_app_id(), APPNOTIFY_Title, messages_get("amiDownloadComplete"),
+ APPNOTIFY_PubScreenName, "FRONT",
+ APPNOTIFY_BackMsg, dw->fname,
+ APPNOTIFY_CloseOnDC, TRUE,
+ APPNOTIFY_Text, dw->fname,
+ TAG_DONE);
+ }
+
+ download_context_destroy(dw->ctx);
+
+ if((dln = dw->dln))
+ {
+ dln2 = (struct dlnode *)GetSucc((struct Node *)dln);
+ if((dln!=dln2) && (dln2)) queuedl = true;
+
+ free(dln->filename);
+ Remove((struct Node *)dln);
+ FreeVec(dln);
+ }
+
+ FClose(dw->fh);
+ SetComment(dw->fname, dw->url);
+
+ downloads_in_progress--;
+
+ DisposeObject(dw->objects[OID_MAIN]);
+ DelObject(dw->node);
+ if(queuedl) {
+ nsurl *url;
+ if (nsurl_create(dln2->node.ln_Name, &url) != NSERROR_OK) {
+ amiga_warn_user("NoMemory", 0);
+ } else {
+ browser_window_navigate(bw,
+ url,
+ NULL,
+ BW_NAVIGATE_DOWNLOAD,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ }
+ ami_try_quit(); /* In case the only window open was this download */
+}
+
+static void gui_download_window_error(struct gui_download_window *dw,
+ const char *error_msg)
+{
+ amiga_warn_user("Unwritten","");
+ dw->result = AMINS_DLOAD_ERROR;
+ gui_download_window_done(dw);
+}
+
+void ami_download_window_abort(struct gui_download_window *dw)
+{
+ download_context_abort(dw->ctx);
+ dw->result = AMINS_DLOAD_ABORT;
+ gui_download_window_done(dw);
+}
+
+BOOL ami_download_window_event(struct gui_download_window *dw)
+{
+ /* return TRUE if window destroyed */
+ ULONG result;
+ uint16 code;
+
+ while((result = RA_HandleInput(dw->objects[OID_MAIN], &code)) != WMHI_LASTMSG)
+ {
+ switch(result & WMHI_CLASSMASK) // class
+ {
+ case WMHI_GADGETUP:
+ switch(result & WMHI_GADGETMASK)
+ {
+ case GID_CANCEL:
+ ami_download_window_abort(dw);
+ return TRUE;
+ break;
+ }
+ break;
+ }
+ }
+ return FALSE;
+}
+
+void ami_free_download_list(struct List *dllist)
+{
+ struct dlnode *node;
+ struct dlnode *nnode;
+
+ if(!dllist) return;
+ if(IsListEmpty(dllist)) return;
+
+ node = (struct dlnode *)GetHead((struct List *)dllist);
+
+ do
+ {
+ nnode=(struct dlnode *)GetSucc((struct Node *)node);
+ free(node->node.ln_Name);
+ free(node->filename);
+ Remove((struct Node *)node);
+ FreeVec((struct Node *)node);
+ }while((node=nnode));
+}
+
+nserror
+gui_window_save_link(struct gui_window *g, nsurl *url, const char *title)
+{
+ char fname[1024];
+ STRPTR openurlstring,linkname;
+ struct DiskObject *dobj = NULL;
+
+ linkname = ASPrintf("Link_to_%s",FilePart(nsurl_access(url)));
+
+ if(AslRequestTags(savereq,
+ ASLFR_Window, g->shared->win,
+ ASLFR_SleepWindow, TRUE,
+ ASLFR_TitleText,messages_get("NetSurf"),
+ ASLFR_Screen,scrn,
+ 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);
+
+ if(ami_download_check_overwrite(fname, g->shared->win, 0))
+ {
+ BPTR fh;
+
+ if((fh = FOpen(fname,MODE_NEWFILE,0)))
+ {
+ /* \todo Should be URLOpen on OS4.1 */
+ openurlstring = ASPrintf("openurl \"%s\"\n",nsurl_access(url));
+ FWrite(fh,openurlstring,1,strlen(openurlstring));
+ FClose(fh);
+ FreeVec(openurlstring);
+ SetComment(fname, nsurl_access(url));
+
+ dobj = GetIconTags(NULL,ICONGETA_GetDefaultName,"url",
+ ICONGETA_GetDefaultType,WBPROJECT,
+ TAG_DONE);
+
+ dobj->do_DefaultTool = "IconX";
+
+ PutIconTags(fname,dobj,
+ ICONPUTA_NotifyWorkbench,TRUE,
+ TAG_DONE);
+
+ FreeDiskObject(dobj);
+ }
+ FreeVec(linkname);
+ }
+ ami_reset_pointer(g->shared);
+ }
+ return NSERROR_OK;
+}
+
+BOOL ami_download_check_overwrite(const char *file, struct Window *win, ULONG size)
+{
+ /* Return TRUE if file can be (over-)written */
+ int32 res = 0;
+ BPTR lock = 0;
+ char *overwritetext;
+
+ if(nsoption_bool(ask_overwrite) == false) return TRUE;
+
+ lock = Lock(file, ACCESS_READ);
+
+ if(lock)
+ {
+ if(size) {
+ BPTR fh;
+ int64 oldsize = 0;
+
+ if((fh = OpenFromLock(lock))) {
+ oldsize = GetFileSize(fh);
+ Close(fh);
+ }
+ overwritetext = ASPrintf("%s\n\n%s %s\n%s %s",
+ messages_get("OverwriteFile"),
+ messages_get("amiSizeExisting"), human_friendly_bytesize((ULONG)oldsize),
+ messages_get("amiSizeNew"), human_friendly_bytesize(size));
+ } else {
+ UnLock(lock);
+ overwritetext = ASPrintf(messages_get("OverwriteFile"));
+ }
+
+ res = amiga_warn_user_multi(overwritetext, "Replace", "DontReplace", win);
+ FreeVec(overwritetext);
+ }
+ else return TRUE;
+
+ if(res == 1) return TRUE;
+ else return FALSE;
+}
+
+static struct gui_download_table download_table = {
+ .create = gui_download_window_create,
+ .data = gui_download_window_data,
+ .error = gui_download_window_error,
+ .done = gui_download_window_done,
+};
+
+struct gui_download_table *amiga_download_table = &download_table;
diff --git a/frontends/amiga/download.h b/frontends/amiga/download.h
new file mode 100755
index 000000000..51981ede8
--- /dev/null
+++ b/frontends/amiga/download.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2008-9 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/>.
+ */
+
+#ifndef AMIGA_DOWNLOAD_H
+#define AMIGA_DOWNLOAD_H
+
+#include "amiga/os3support.h"
+
+extern struct gui_download_table *amiga_download_table;
+
+struct download_context;
+struct gui_download_window;
+struct gui_window;
+struct nsurl;
+
+struct dlnode
+{
+ struct Node node;
+ char *filename;
+};
+
+void ami_download_window_abort(struct gui_download_window *dw);
+BOOL ami_download_window_event(struct gui_download_window *dw);
+void ami_free_download_list(struct List *dllist);
+BOOL ami_download_check_overwrite(const char *file, struct Window *win, ULONG size);
+
+nserror gui_window_save_link(struct gui_window *g, struct nsurl *url, const char *title);
+
+#endif
diff --git a/frontends/amiga/drag.c b/frontends/amiga/drag.c
new file mode 100644
index 000000000..67d17223e
--- /dev/null
+++ b/frontends/amiga/drag.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright 2010 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/>.
+ */
+#ifdef __amigaos4__
+#include <string.h>
+
+#include <proto/wb.h>
+#include <proto/exec.h>
+#include <proto/dos.h>
+#include <proto/intuition.h>
+#include <proto/utility.h>
+#include <proto/icon.h>
+#include <proto/layers.h>
+
+#include <graphics/blitattr.h>
+#include <workbench/icon.h>
+
+#include "utils/errors.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "utils/nsoption.h"
+#include "content/hlcache.h"
+#include "desktop/mouse.h"
+
+#include "amiga/bitmap.h"
+#include "amiga/clipboard.h"
+#include "amiga/download.h"
+#include "amiga/drag.h"
+#include "amiga/file.h"
+#include "amiga/filetype.h"
+#include "amiga/gui.h"
+#include "amiga/theme.h"
+
+
+struct Window *drag_icon = NULL;
+ULONG drag_icon_width;
+ULONG drag_icon_height;
+BOOL drag_in_progress = FALSE;
+
+void gui_drag_save_object(struct gui_window *g, struct hlcache_handle *c,
+ gui_save_type type)
+{
+ const char *filetype = NULL;
+
+ /* Check we are running on Workbench */
+ if(nsoption_charp(pubscreen_name) == NULL) return;
+ if(strcmp(nsoption_charp(pubscreen_name), "Workbench")) return;
+
+ switch(type) {
+ case GUI_SAVE_OBJECT_ORIG: // object
+ case GUI_SAVE_SOURCE:
+ filetype = ami_mime_content_to_filetype(c);
+ break;
+ case GUI_SAVE_COMPLETE:
+ filetype = "drawer";
+ break;
+ case GUI_SAVE_OBJECT_NATIVE:
+#ifdef WITH_NS_SVG
+ if(ami_mime_compare(c, "svg") == true)
+ {
+ filetype = "dr2d";
+ }
+ else
+#endif
+ {
+ filetype = "ilbm";
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ ami_drag_icon_show(g->shared->win, filetype);
+
+ drag_save_data = c;
+ drag_save_gui = g;
+ drag_save = type;
+}
+
+void gui_drag_save_selection(struct gui_window *g, const char *selection)
+{
+ ami_drag_icon_show(g->shared->win, "ascii");
+
+ ami_autoscroll = TRUE;
+ drag_save_data = g;
+ drag_save = GUI_SAVE_TEXT_SELECTION;
+}
+
+void ami_drag_save(struct Window *win)
+{
+ ULONG which = WBO_NONE, type;
+ char path[1025], dpath[1025];
+
+ ami_drag_icon_close(NULL);
+ ami_autoscroll = FALSE;
+
+ if(nsoption_charp(pubscreen_name) && (strcmp(nsoption_charp(pubscreen_name),"Workbench") == 0))
+ {
+ which = WhichWorkbenchObject(NULL,scrn->MouseX,scrn->MouseY,
+ WBOBJA_Type,&type,
+ WBOBJA_FullPath,&path,
+ WBOBJA_FullPathSize,1024,
+ WBOBJA_DrawerPath,&dpath,
+ WBOBJA_DrawerPathSize,1024,
+ TAG_DONE);
+ }
+
+ if((which == WBO_DRAWER) || ((which == WBO_ICON) && (type > WBDRAWER)))
+ {
+ strcpy(path,dpath);
+ }
+ else if(which == WBO_NONE)
+ {
+ if(drag_save == GUI_SAVE_TEXT_SELECTION)
+ ami_drag_selection((struct gui_window *)drag_save_data);
+ else DisplayBeep(scrn);
+
+ drag_save = 0;
+ drag_save_data = NULL;
+ return;
+ }
+
+ if(path[0] == '\0')
+ {
+ DisplayBeep(scrn);
+ drag_save = 0;
+ drag_save_data = NULL;
+ return;
+ }
+
+ ami_update_pointer(win, GUI_POINTER_WAIT);
+
+ switch(drag_save)
+ {
+ case GUI_SAVE_OBJECT_ORIG: // object
+ case GUI_SAVE_SOURCE:
+ {
+ struct hlcache_handle *c = drag_save_data;
+
+ AddPart(path, content_get_title(c), 1024);
+ ami_file_save(AMINS_SAVE_SOURCE, path, win, c, NULL, NULL);
+ }
+ break;
+
+ 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);
+ break;
+
+ case GUI_SAVE_COMPLETE:
+ {
+ 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);
+ }
+ break;
+
+ case GUI_SAVE_OBJECT_NATIVE:
+ {
+ hlcache_handle *c = drag_save_data;
+ AddPart(path, content_get_title(c), 1024);
+
+ ami_file_save(AMINS_SAVE_IFF, path, win, c, NULL, NULL);
+ }
+ break;
+
+ default:
+ LOG("Unsupported drag save operation %d", drag_save);
+ break;
+ }
+
+ drag_save = 0;
+ drag_save_data = NULL;
+
+ ami_update_pointer(win, GUI_POINTER_DEFAULT);
+}
+
+void ami_drag_icon_show(struct Window *win, const char *type)
+{
+ struct DiskObject *dobj = NULL;
+ ULONG width, height;
+ int deftype = WBPROJECT;
+
+ drag_in_progress = TRUE;
+
+ if(nsoption_bool(drag_save_icons) == false)
+ {
+ ami_update_pointer(win, AMI_GUI_POINTER_DRAG);
+ return;
+ }
+ else
+ {
+ ami_update_pointer(win, GUI_POINTER_DEFAULT);
+ }
+
+ if(!strcmp(type, "drawer")) deftype = WBDRAWER;
+
+ dobj = GetIconTags(NULL, ICONGETA_GetDefaultName, type,
+ ICONGETA_GetDefaultType, deftype,
+ TAG_DONE);
+
+ IconControl(dobj,
+ ICONCTRLA_GetWidth,&width,
+ ICONCTRLA_GetHeight,&height,
+ TAG_DONE);
+
+ drag_icon_width = width;
+ drag_icon_height = height;
+
+ drag_icon = OpenWindowTags(NULL,
+ WA_Left, scrn->MouseX - (width/2),
+ WA_Top, scrn->MouseY - (height/2),
+ WA_Width, width,
+ WA_Height, height,
+ WA_PubScreen, scrn,
+ WA_Borderless, TRUE,
+ WA_ToolBox, TRUE,
+ WA_StayTop, TRUE,
+ WA_Opaqueness, 128,
+ WA_OverrideOpaqueness, TRUE,
+ TAG_DONE);
+
+/* probably need layouticon and drawinfo stuff too */
+
+ DrawIconState(drag_icon->RPort, dobj, NULL, 0, 0, IDS_NORMAL,
+ ICONDRAWA_Frameless, TRUE,
+ ICONDRAWA_Borderless, TRUE,
+ TAG_DONE);
+}
+
+void ami_drag_icon_move(void)
+{
+ if(drag_icon == NULL) return;
+
+ ChangeWindowBox(drag_icon, scrn->MouseX - (drag_icon_width / 2),
+ scrn->MouseY - (drag_icon_height / 2),
+ drag_icon_width, drag_icon_height);
+}
+
+/**
+ * Close the drag icon (invisible) window if it is open
+ *
+ * \param win pointer to window to clear drag pointer
+ */
+
+void ami_drag_icon_close(struct Window *win)
+{
+ if(drag_icon) CloseWindow(drag_icon);
+ if(win) ami_update_pointer(win, GUI_POINTER_DEFAULT);
+ drag_icon = NULL;
+ drag_in_progress = FALSE;
+}
+
+BOOL ami_drag_in_progress(void)
+{
+ return drag_in_progress;
+}
+
+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 "amiga/drag.h"
+
+void gui_drag_save_object(struct gui_window *g, struct hlcache_handle *c,
+ gui_save_type type)
+{
+}
+
+void gui_drag_save_selection(struct gui_window *g, const char *selection)
+{
+}
+
+void ami_drag_save(struct Window *win)
+{
+}
+
+void ami_drag_icon_show(struct Window *win, const char *type)
+{
+}
+
+void ami_drag_icon_close(struct Window *win)
+{
+}
+
+void ami_drag_icon_move(void)
+{
+}
+
+BOOL ami_drag_in_progress(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
new file mode 100644
index 000000000..59a1a8467
--- /dev/null
+++ b/frontends/amiga/drag.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2010 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/>.
+ */
+
+#ifndef AMIGA_DRAG_H
+#define AMIGA_DRAG_H
+#include <exec/types.h>
+#include "desktop/browser.h"
+#include "desktop/gui_window.h"
+
+#define AMI_DRAG_THRESHOLD 10
+
+struct hlcache_handle;
+struct Window;
+
+int drag_save;
+void *drag_save_data;
+struct gui_window *drag_save_gui;
+
+void gui_drag_save_selection(struct gui_window *g, const char *selection);
+void gui_drag_save_object(struct gui_window *g, struct hlcache_handle *c, gui_save_type type);
+
+void ami_drag_save(struct Window *win);
+void ami_drag_icon_show(struct Window *win, const char *type);
+void ami_drag_icon_close(struct Window *win);
+void ami_drag_icon_move(void);
+BOOL ami_drag_in_progress(void);
+
+void *ami_window_at_pointer(int type);
+#endif
+
diff --git a/frontends/amiga/dt_anim.c b/frontends/amiga/dt_anim.c
new file mode 100644
index 000000000..a3bfb1d66
--- /dev/null
+++ b/frontends/amiga/dt_anim.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright 2011 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
+ * DataTypes animation handler (implementation)
+*/
+
+#ifdef WITH_AMIGA_DATATYPES
+#include "amiga/os3support.h"
+
+#include <stdlib.h>
+#include <proto/datatypes.h>
+#include <proto/dos.h>
+#include <proto/exec.h>
+#include <proto/intuition.h>
+#include <datatypes/animationclass.h>
+#include <datatypes/pictureclass.h>
+#ifdef __amigaos4__
+#include <graphics/blitattr.h>
+#endif
+#include <intuition/classusr.h>
+
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "content/content_protected.h"
+#include "desktop/plotters.h"
+#include "image/bitmap.h"
+
+#include "amiga/bitmap.h"
+#include "amiga/filetype.h"
+#include "amiga/datatypes.h"
+#include "amiga/misc.h"
+#include "amiga/plotters.h"
+
+typedef struct amiga_dt_anim_content {
+ struct content base;
+
+ struct bitmap *bitmap; /**< Created NetSurf bitmap */
+
+ Object *dto;
+ int x;
+ int y;
+ int w;
+ int h;
+} amiga_dt_anim_content;
+
+APTR ami_colormap_to_clut(struct ColorMap *cmap);
+
+static nserror amiga_dt_anim_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 bool amiga_dt_anim_convert(struct content *c);
+static void amiga_dt_anim_reformat(struct content *c, int width, int height);
+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,
+ struct content *page, struct object_params *params);
+static void 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);
+
+static void *amiga_dt_anim_get_internal(const struct content *c, void *context)
+{
+ amiga_dt_anim_content *adta_c = (amiga_dt_anim_content *)c;
+
+ return adta_c->bitmap;
+}
+
+static const content_handler amiga_dt_anim_content_handler = {
+ .create = amiga_dt_anim_create,
+ .data_complete = amiga_dt_anim_convert,
+ .reformat = amiga_dt_anim_reformat,
+ .destroy = amiga_dt_anim_destroy,
+ .redraw = amiga_dt_anim_redraw,
+ .open = amiga_dt_anim_open,
+ .close = amiga_dt_anim_close,
+ .clone = amiga_dt_anim_clone,
+ .get_internal = amiga_dt_anim_get_internal,
+ .type = amiga_dt_anim_content_type,
+ .no_share = false,
+};
+
+nserror amiga_dt_anim_init(void)
+{
+ struct DataType *dt, *prevdt = NULL;
+ lwc_string *type;
+ nserror error;
+ struct Node *node = NULL;
+
+ while((dt = ObtainDataType(DTST_RAM, NULL,
+ DTA_DataType, prevdt,
+ DTA_GroupID, GID_ANIMATION,
+ TAG_DONE)) != NULL)
+ {
+ ReleaseDataType(prevdt);
+ prevdt = dt;
+
+ do {
+ node = ami_mime_from_datatype(dt, &type, node);
+
+ if(node)
+ {
+ error = content_factory_register_handler(
+ lwc_string_data(type),
+ &amiga_dt_anim_content_handler);
+
+ if (error != NSERROR_OK)
+ return error;
+ }
+
+ }while (node != NULL);
+
+ }
+
+ ReleaseDataType(prevdt);
+
+ return NSERROR_OK;
+}
+
+nserror amiga_dt_anim_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)
+{
+ amiga_dt_anim_content *plugin;
+ nserror error;
+
+ plugin = calloc(1, sizeof(amiga_dt_anim_content));
+ if (plugin == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&plugin->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ free(plugin);
+ return error;
+ }
+
+ *c = (struct content *) plugin;
+
+ return NSERROR_OK;
+}
+
+bool amiga_dt_anim_convert(struct content *c)
+{
+ LOG("amiga_dt_anim_convert");
+
+ amiga_dt_anim_content *plugin = (amiga_dt_anim_content *) c;
+ union content_msg_data msg_data;
+ int width, height;
+ const uint8 *data;
+ UBYTE *bm_buffer;
+ ULONG size;
+ struct BitMapHeader *bmh;
+ unsigned int bm_flags = BITMAP_NEW | BITMAP_OPAQUE;
+ struct adtFrame adt_frame;
+ APTR clut;
+
+ data = (uint8 *)content__get_source_data(c, &size);
+
+ if((plugin->dto = NewDTObject(NULL,
+ DTA_SourceType, DTST_MEMORY,
+ DTA_SourceAddress, data,
+ DTA_SourceSize, size,
+ DTA_GroupID, GID_ANIMATION,
+ TAG_DONE))) {
+ if(GetDTAttrs(plugin->dto, PDTA_BitMapHeader, &bmh, TAG_DONE)) {
+ width = (int)bmh->bmh_Width;
+ height = (int)bmh->bmh_Height;
+
+ plugin->bitmap = amiga_bitmap_create(width, height, bm_flags);
+ if (!plugin->bitmap) {
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ bm_buffer = amiga_bitmap_get_buffer(plugin->bitmap);
+
+ adt_frame.MethodID = ADTM_LOADFRAME;
+ adt_frame.alf_TimeStamp = 0;
+ IDoMethodA(plugin->dto, (Msg)&adt_frame);
+
+ clut = ami_colormap_to_clut(adt_frame.alf_CMap);
+#ifdef __amigaos4__
+ BltBitMapTags(
+ BLITA_Width, width,
+ BLITA_Height, height,
+ BLITA_Source, adt_frame.alf_BitMap,
+ BLITA_SrcType, BLITT_BITMAP,
+ BLITA_Dest, bm_buffer,
+ BLITA_DestType, BLITT_RGB24,
+ BLITA_DestBytesPerRow, width,
+ BLITA_CLUT, clut,
+ TAG_DONE);
+#else
+#warning FIXME: Need to use a different blitter function for OS3!
+#endif
+ FreeVec(clut);
+
+ adt_frame.MethodID = ADTM_UNLOADFRAME;
+ IDoMethodA(plugin->dto, (Msg)&adt_frame);
+ }
+ else return false;
+ }
+ else return false;
+
+ c->width = width;
+ c->height = height;
+
+/*
+ snprintf(title, sizeof(title), "image (%lux%lu, %lu bytes)",
+ width, height, size);
+ content__set_title(c, title);
+*/
+
+ amiga_bitmap_modified(plugin->bitmap);
+
+ content_set_ready(c);
+ content_set_done(c);
+
+ content_set_status(c, "");
+ return true;
+}
+
+void amiga_dt_anim_destroy(struct content *c)
+{
+ amiga_dt_anim_content *plugin = (amiga_dt_anim_content *) c;
+
+ LOG("amiga_dt_anim_destroy");
+
+ if (plugin->bitmap != NULL)
+ amiga_bitmap_destroy(plugin->bitmap);
+
+ DisposeDTObject(plugin->dto);
+
+ return;
+}
+
+bool amiga_dt_anim_redraw(struct content *c,
+ struct content_redraw_data *data, const struct rect *clip,
+ const struct redraw_context *ctx)
+{
+ amiga_dt_anim_content *plugin = (amiga_dt_anim_content *) c;
+ bitmap_flags_t flags = BITMAPF_NONE;
+
+ LOG("amiga_dt_anim_redraw");
+
+ if (data->repeat_x)
+ flags |= BITMAPF_REPEAT_X;
+ if (data->repeat_y)
+ flags |= BITMAPF_REPEAT_Y;
+
+ return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
+ plugin->bitmap, data->background_colour, flags);
+}
+
+/**
+ * Handle a window containing a CONTENT_PLUGIN being opened.
+ *
+ * \param c content that has been opened
+ * \param bw browser window containing the content
+ * \param page content of type CONTENT_HTML containing c, or 0 if not an
+ * object within a page
+ * \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,
+ struct content *page, struct object_params *params)
+{
+ LOG("amiga_dt_anim_open");
+
+ return;
+}
+
+void amiga_dt_anim_close(struct content *c)
+{
+ LOG("amiga_dt_anim_close");
+ return;
+}
+
+void amiga_dt_anim_reformat(struct content *c, int width, int height)
+{
+ LOG("amiga_dt_anim_reformat");
+ return;
+}
+
+nserror amiga_dt_anim_clone(const struct content *old, struct content **newc)
+{
+ amiga_dt_anim_content *plugin;
+ nserror error;
+
+ LOG("amiga_dt_anim_clone");
+
+ plugin = calloc(1, sizeof(amiga_dt_anim_content));
+ if (plugin == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &plugin->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&plugin->base);
+ return error;
+ }
+
+ /* We "clone" the old content by replaying conversion */
+ if (old->status == CONTENT_STATUS_READY ||
+ old->status == CONTENT_STATUS_DONE) {
+ if (amiga_dt_anim_convert(&plugin->base) == false) {
+ content_destroy(&plugin->base);
+ return NSERROR_CLONE_FAILED;
+ }
+ }
+
+ *newc = (struct content *) plugin;
+
+ return NSERROR_OK;
+}
+
+content_type amiga_dt_anim_content_type(void)
+{
+ return CONTENT_IMAGE;
+}
+
+APTR ami_colormap_to_clut(struct ColorMap *cmap)
+{
+ int i;
+ UBYTE *clut = ami_misc_allocvec_clear(256 * 4, 0); /* NB: Was not MEMF_PRIVATE */
+ ULONG colr[256 * 4];
+
+ if(!clut) return NULL;
+
+ /* Get the palette from the ColorMap */
+ GetRGB32(cmap, 0, 256, (ULONG *)&colr);
+
+ /* convert it to a table of ARGB values */
+ for(i = 0; i < 1024; i += 4)
+ {
+ clut[i] = (0xff << 24) |
+ ((colr[i] & 0xff000000) >> 8) |
+ ((colr[i + 1] & 0xff000000) >> 16) |
+ ((colr[i + 2] & 0xff000000) >> 24);
+ }
+
+ return clut;
+}
+
+#endif
diff --git a/frontends/amiga/dt_picture.c b/frontends/amiga/dt_picture.c
new file mode 100644
index 000000000..aa2418dca
--- /dev/null
+++ b/frontends/amiga/dt_picture.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright 2011 - 2012 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
+ * DataTypes picture handler (implementation)
+*/
+
+#ifdef WITH_AMIGA_DATATYPES
+#include "amiga/os3support.h"
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <proto/datatypes.h>
+#include <proto/dos.h>
+#include <proto/intuition.h>
+#include <datatypes/pictureclass.h>
+#include <intuition/classusr.h>
+
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "content/content_protected.h"
+#include "desktop/plotters.h"
+#include "image/bitmap.h"
+#include "image/image_cache.h"
+
+#include "amiga/bitmap.h"
+#include "amiga/filetype.h"
+#include "amiga/datatypes.h"
+
+
+static nserror amiga_dt_picture_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 bool amiga_dt_picture_convert(struct content *c);
+static nserror amiga_dt_picture_clone(const struct content *old, struct content **newc);
+static void amiga_dt_picture_destroy(struct content *c);
+
+static const content_handler amiga_dt_picture_content_handler = {
+ .create = amiga_dt_picture_create,
+ .data_complete = amiga_dt_picture_convert,
+ .destroy = amiga_dt_picture_destroy,
+ .redraw = image_cache_redraw,
+ .clone = amiga_dt_picture_clone,
+ .get_internal = image_cache_get_internal,
+ .type = image_cache_content_type,
+ .no_share = false,
+};
+
+struct amiga_dt_picture_content {
+ struct content c;
+ Object *dto;
+};
+
+nserror amiga_dt_picture_init(void)
+{
+ struct DataType *dt, *prevdt = NULL;
+ lwc_string *type;
+ nserror error;
+ struct Node *node = NULL;
+
+ while((dt = ObtainDataType(DTST_RAM, NULL,
+ DTA_DataType, prevdt,
+ DTA_GroupID, GID_PICTURE, // we only support images for now
+ TAG_DONE)) != NULL)
+ {
+ if(prevdt) ReleaseDataType(prevdt);
+ prevdt = dt;
+
+ do {
+ node = ami_mime_from_datatype(dt, &type, node);
+
+ if(node)
+ {
+ error = content_factory_register_handler(
+ lwc_string_data(type),
+ &amiga_dt_picture_content_handler);
+
+ if (error != NSERROR_OK)
+ return error;
+ }
+
+ }while (node != NULL);
+
+ }
+
+ ReleaseDataType(prevdt);
+
+ return NSERROR_OK;
+}
+
+nserror amiga_dt_picture_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 amiga_dt_picture_content *adt;
+ nserror error;
+
+ adt = calloc(1, sizeof(struct amiga_dt_picture_content));
+ if (adt == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init((struct content *)adt, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ free(adt);
+ return error;
+ }
+
+ *c = (struct content *)adt;
+
+ return NSERROR_OK;
+}
+
+static Object *amiga_dt_picture_newdtobject(struct amiga_dt_picture_content *adt)
+{
+ const uint8 *data;
+ ULONG size;
+
+ if(adt->dto == NULL) {
+ data = (uint8 *)content__get_source_data((struct content *)adt, &size);
+
+ adt->dto = NewDTObject(NULL,
+ DTA_SourceType, DTST_MEMORY,
+ DTA_SourceAddress, data,
+ DTA_SourceSize, size,
+ DTA_GroupID, GID_PICTURE,
+ PDTA_DestMode, PMODE_V43,
+ PDTA_PromoteMask, TRUE,
+ TAG_DONE);
+ }
+
+ return adt->dto;
+}
+
+static char *amiga_dt_picture_datatype(struct content *c)
+{
+ const uint8 *data;
+ ULONG size;
+ struct DataType *dt;
+ char *filetype = NULL;
+
+ data = (uint8 *)content__get_source_data(c, &size);
+
+ if((dt = ObtainDataType(DTST_MEMORY, NULL,
+ DTA_SourceAddress, data,
+ DTA_SourceSize, size,
+ DTA_GroupID, GID_PICTURE,
+ TAG_DONE))) {
+ filetype = strdup(dt->dtn_Header->dth_Name);
+ ReleaseDataType(dt);
+ }
+
+ if(filetype == NULL) filetype = strdup("DataTypes");
+ return filetype;
+}
+
+static struct bitmap *amiga_dt_picture_cache_convert(struct content *c)
+{
+ LOG("amiga_dt_picture_cache_convert");
+
+ union content_msg_data msg_data;
+ UBYTE *bm_buffer;
+ Object *dto;
+ struct bitmap *bitmap;
+ struct amiga_dt_picture_content *adt = (struct amiga_dt_picture_content *)c;
+
+ if((dto = amiga_dt_picture_newdtobject(adt)))
+ {
+ bitmap = amiga_bitmap_create(c->width, c->height, BITMAP_NEW);
+ if (!bitmap) {
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return NULL;
+ }
+
+ bm_buffer = amiga_bitmap_get_buffer(bitmap);
+
+ IDoMethod(dto, PDTM_READPIXELARRAY,
+ bm_buffer, PBPAFMT_RGBA,
+ amiga_bitmap_get_rowstride(bitmap),
+ 0, 0, c->width, c->height);
+
+ amiga_bitmap_set_opaque(bitmap, amiga_bitmap_test_opaque(bitmap));
+
+ DisposeDTObject(dto);
+ adt->dto = NULL;
+ }
+ else return NULL;
+
+ return bitmap;
+}
+
+bool amiga_dt_picture_convert(struct content *c)
+{
+ LOG("amiga_dt_picture_convert");
+
+ int width, height;
+ char *title;
+ Object *dto;
+ struct BitMapHeader *bmh;
+ char *filetype;
+
+ if((dto = amiga_dt_picture_newdtobject((struct amiga_dt_picture_content *)c))) {
+ if(GetDTAttrs(dto, PDTA_BitMapHeader, &bmh, TAG_DONE)) {
+ width = (int)bmh->bmh_Width;
+ height = (int)bmh->bmh_Height;
+ }
+ else return false;
+ }
+ else return false;
+
+ c->width = width;
+ c->height = height;
+ c->size = width * height * 4;
+
+ /* set title text */
+ if((filetype = amiga_dt_picture_datatype(c))) {
+ title = messages_get_buff("DataTypesTitle",
+ nsurl_access_leaf(llcache_handle_get_url(c->llcache)),
+ filetype, c->width, c->height);
+ if (title != NULL) {
+ content__set_title(c, title);
+ free(title);
+ }
+ free(filetype);
+ }
+
+ image_cache_add(c, NULL, amiga_dt_picture_cache_convert);
+
+ content_set_ready(c);
+ content_set_done(c);
+ content_set_status(c, "");
+ return true;
+}
+
+nserror amiga_dt_picture_clone(const struct content *old, struct content **newc)
+{
+ struct content *adt;
+ nserror error;
+
+ LOG("amiga_dt_picture_clone");
+
+ adt = calloc(1, sizeof(struct content));
+ if (adt == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, adt);
+ if (error != NSERROR_OK) {
+ content_destroy(adt);
+ return error;
+ }
+
+ /* We "clone" the old content by replaying conversion */
+ if ((old->status == CONTENT_STATUS_READY) ||
+ (old->status == CONTENT_STATUS_DONE)) {
+ if (amiga_dt_picture_convert(adt) == false) {
+ content_destroy(adt);
+ return NSERROR_CLONE_FAILED;
+ }
+ }
+
+ *newc = adt;
+
+ return NSERROR_OK;
+}
+
+static void amiga_dt_picture_destroy(struct content *c)
+{
+ struct amiga_dt_picture_content *adt = (struct amiga_dt_picture_content *)c;
+
+ DisposeDTObject(adt->dto);
+ adt->dto = NULL;
+
+ image_cache_destroy(c);
+}
+
+#endif
diff --git a/frontends/amiga/dt_sound.c b/frontends/amiga/dt_sound.c
new file mode 100644
index 000000000..fe1b1fc43
--- /dev/null
+++ b/frontends/amiga/dt_sound.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2011 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
+ * DataTypes sound handler (implementation)
+*/
+
+#ifdef WITH_AMIGA_DATATYPES
+#include "amiga/os3support.h"
+
+#include "amiga/filetype.h"
+#include "amiga/datatypes.h"
+#include "content/content_protected.h"
+#include "desktop/plotters.h"
+#include "render/box.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+
+#include <proto/datatypes.h>
+#include <proto/dos.h>
+#include <proto/intuition.h>
+#include <datatypes/soundclass.h>
+#include <intuition/classusr.h>
+
+typedef struct amiga_dt_sound_content {
+ struct content base;
+
+ Object *dto;
+ bool immediate;
+} amiga_dt_sound_content;
+
+static nserror amiga_dt_sound_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 bool amiga_dt_sound_convert(struct content *c);
+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,
+ 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);
+
+static const content_handler amiga_dt_sound_content_handler = {
+ .create = amiga_dt_sound_create,
+ .data_complete = amiga_dt_sound_convert,
+ .destroy = amiga_dt_sound_destroy,
+ .redraw = amiga_dt_sound_redraw,
+ .open = amiga_dt_sound_open,
+ .clone = amiga_dt_sound_clone,
+ .type = amiga_dt_sound_content_type,
+ .no_share = false,
+};
+
+
+static void amiga_dt_sound_play(Object *dto)
+{
+ LOG("Playing...");
+ IDoMethod(dto, DTM_TRIGGER, NULL, STM_PLAY, NULL);
+}
+
+
+nserror amiga_dt_sound_init(void)
+{
+ struct DataType *dt, *prevdt = NULL;
+ lwc_string *type;
+ nserror error;
+ struct Node *node = NULL;
+
+ while((dt = ObtainDataType(DTST_RAM, NULL,
+ DTA_DataType, prevdt,
+ DTA_GroupID, GID_SOUND,
+ TAG_DONE)) != NULL)
+ {
+ ReleaseDataType(prevdt);
+ prevdt = dt;
+
+ do {
+ node = ami_mime_from_datatype(dt, &type, node);
+
+ if(node)
+ {
+ error = content_factory_register_handler(
+ lwc_string_data(type),
+ &amiga_dt_sound_content_handler);
+
+ if (error != NSERROR_OK)
+ return error;
+ }
+
+ }while (node != NULL);
+
+ }
+
+ ReleaseDataType(prevdt);
+
+ return NSERROR_OK;
+}
+
+nserror amiga_dt_sound_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)
+{
+ amiga_dt_sound_content *plugin;
+ nserror error;
+
+ LOG("amiga_dt_sound_create");
+
+ plugin = calloc(1, sizeof(amiga_dt_sound_content));
+ if (plugin == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&plugin->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ free(plugin);
+ return error;
+ }
+
+ *c = (struct content *) plugin;
+
+ return NSERROR_OK;
+}
+
+bool amiga_dt_sound_convert(struct content *c)
+{
+ LOG("amiga_dt_sound_convert");
+
+ amiga_dt_sound_content *plugin = (amiga_dt_sound_content *) c;
+ int width = 50, height = 50;
+ const uint8 *data;
+ ULONG size;
+
+ data = (uint8 *)content__get_source_data(c, &size);
+
+ plugin->dto = NewDTObject(NULL,
+ DTA_SourceType, DTST_MEMORY,
+ DTA_SourceAddress, data,
+ DTA_SourceSize, size,
+ DTA_GroupID, GID_SOUND,
+ TAG_DONE);
+
+ if(plugin->dto == NULL) return false;
+
+ c->width = width;
+ c->height = height;
+
+ if(plugin->immediate == true) amiga_dt_sound_play(plugin->dto);
+
+ content_set_ready(c);
+ content_set_done(c);
+
+ content_set_status(c, "");
+ return true;
+}
+
+void amiga_dt_sound_destroy(struct content *c)
+{
+ amiga_dt_sound_content *plugin = (amiga_dt_sound_content *) c;
+
+ LOG("amiga_dt_sound_destroy");
+
+ DisposeDTObject(plugin->dto);
+
+ return;
+}
+
+bool amiga_dt_sound_redraw(struct content *c,
+ struct content_redraw_data *data, const struct rect *clip,
+ const struct redraw_context *ctx)
+{
+ plot_style_t pstyle = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+ .fill_colour = 0xffffff,
+ .stroke_colour = 0x000000,
+ .stroke_width = 1,
+ };
+
+ LOG("amiga_dt_sound_redraw");
+
+ /* this should be some sort of play/stop control */
+
+ ctx->plot->rectangle(data->x, data->y, data->x + data->width,
+ data->y + data->height, &pstyle);
+
+ return ctx->plot->text(data->x, data->y+20,
+ lwc_string_data(content__get_mime_type(c)),
+ lwc_string_length(content__get_mime_type(c)),
+ plot_style_font);
+
+}
+
+
+void 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;
+ struct object_param *param;
+
+ LOG("amiga_dt_sound_open");
+
+ plugin->immediate = false;
+
+ if(params && (param = params->params))
+ {
+ do
+ {
+ LOG("%s = %s", param->name, param->value);
+ if((strcmp(param->name, "autoplay") == 0) &&
+ (strcmp(param->value, "true") == 0)) plugin->immediate = true;
+ if((strcmp(param->name, "autoStart") == 0) &&
+ (strcmp(param->value, "1") == 0)) plugin->immediate = true;
+ param = param->next;
+ } while(param != NULL);
+ }
+
+ if(plugin->dto && (plugin->immediate == true))
+ amiga_dt_sound_play(plugin->dto);
+
+ return;
+}
+
+
+nserror amiga_dt_sound_clone(const struct content *old, struct content **newc)
+{
+ amiga_dt_sound_content *plugin;
+ nserror error;
+
+ LOG("amiga_dt_sound_clone");
+
+ plugin = calloc(1, sizeof(amiga_dt_sound_content));
+ if (plugin == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &plugin->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&plugin->base);
+ return error;
+ }
+
+ /* We "clone" the old content by replaying conversion */
+ if (old->status == CONTENT_STATUS_READY ||
+ old->status == CONTENT_STATUS_DONE) {
+ if (amiga_dt_sound_convert(&plugin->base) == false) {
+ content_destroy(&plugin->base);
+ return NSERROR_CLONE_FAILED;
+ }
+ }
+
+ *newc = (struct content *) plugin;
+
+ return NSERROR_OK;
+}
+
+content_type amiga_dt_sound_content_type(void)
+{
+ return CONTENT_PLUGIN;
+}
+
+#endif
diff --git a/frontends/amiga/file.c b/frontends/amiga/file.c
new file mode 100644
index 000000000..8957ecfe6
--- /dev/null
+++ b/frontends/amiga/file.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright 2011 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 <proto/asl.h>
+#include <proto/dos.h>
+#include <proto/exec.h>
+#include <proto/icon.h>
+#include <workbench/icon.h>
+
+#include "utils/utils.h"
+#include "utils/nsoption.h"
+#include "utils/file.h"
+#include "utils/messages.h"
+#include "content/hlcache.h"
+#include "content/content.h"
+#include "content/fetch.h"
+#include "desktop/browser.h"
+#include "desktop/save_complete.h"
+#include "desktop/save_pdf.h"
+#include "desktop/save_text.h"
+#include "desktop/gui_window.h"
+
+#include "amiga/gui.h"
+#include "amiga/bitmap.h"
+#include "amiga/download.h"
+#include "amiga/file.h"
+#include "amiga/filetype.h"
+#include "amiga/icon.h"
+#include "amiga/iff_dr2d.h"
+#include "amiga/misc.h"
+#include "amiga/save_pdf.h"
+#include "amiga/theme.h"
+
+static struct Hook aslhookfunc;
+
+HOOKF(ULONG, ami_file_asl_mime_hook, struct FileRequester *, fr, struct AnchorPathOld *)
+{
+ char fname[1024];
+ BOOL ret = FALSE;
+ char *mt = NULL;
+ lwc_string *lwc_mt = NULL;
+ lwc_error lerror;
+ content_type ct;
+
+ if(msg->ap_Info.fib_DirEntryType > 0) return(TRUE);
+
+ strcpy(fname,fr->fr_Drawer);
+ AddPart(fname, msg->ap_Info.fib_FileName,1024);
+
+ mt = strdup(fetch_filetype(fname));
+ lerror = lwc_intern_string(mt, strlen(mt), &lwc_mt);
+ if (lerror != lwc_error_ok)
+ return FALSE;
+
+ ct = content_factory_type_from_mime_type(lwc_mt);
+ lwc_string_unref(lwc_mt);
+
+ if(ct != CONTENT_NONE) ret = TRUE;
+
+ free(mt);
+ return ret;
+}
+
+void ami_file_open(struct gui_window_2 *gwin)
+{
+ char *temp;
+ nsurl *url;
+
+ if(AslRequestTags(filereq,
+ ASLFR_TitleText, messages_get("NetSurf"),
+ ASLFR_Window, gwin->win,
+ ASLFR_SleepWindow, TRUE,
+ ASLFR_Screen, scrn,
+ ASLFR_DoSaveMode, FALSE,
+ ASLFR_RejectIcons, TRUE,
+ ASLFR_FilterFunc, &aslhookfunc,
+ TAG_DONE))
+ {
+ if((temp = AllocVecTagList(1024, NULL)))
+ {
+ strlcpy(temp, filereq->fr_Drawer, 1024);
+ AddPart(temp, filereq->fr_File, 1024);
+
+ if (netsurf_path_to_nsurl(temp, &url) != NSERROR_OK) {
+ amiga_warn_user("NoMemory", 0);
+ } else {
+ browser_window_navigate(gwin->gw->bw,
+ url,
+ NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+
+ FreeVec(temp);
+ }
+ }
+}
+
+static void ami_file_set_type(const char *path, lwc_string *mime_type)
+{
+ content_type type = content_factory_type_from_mime_type(mime_type);
+ const char *default_type;
+
+ switch(type) {
+ case CONTENT_HTML:
+ default_type = "html";
+ break;
+ default:
+ default_type = NULL;
+ break;
+ }
+
+ if (default_type != NULL) {
+ struct DiskObject *dobj = NULL;
+
+ dobj = GetIconTags(NULL,ICONGETA_GetDefaultName,default_type,
+ ICONGETA_GetDefaultType,WBPROJECT,
+ TAG_DONE);
+
+ PutIconTags(path, dobj,
+ ICONPUTA_NotifyWorkbench, TRUE, TAG_DONE);
+ }
+}
+
+void ami_file_save(int type, char *fname, struct Window *win,
+ struct hlcache_handle *object, struct hlcache_handle *favicon,
+ struct browser_window *bw)
+{
+ BPTR lock, fh;
+ const char *source_data;
+ ULONG source_size;
+ struct bitmap *bm;
+
+ ami_update_pointer(win, GUI_POINTER_WAIT);
+
+ if(ami_download_check_overwrite(fname, win, 0)) {
+ switch(type) {
+ case AMINS_SAVE_SOURCE:
+ if((source_data = content_get_source_data(object, &source_size))) {
+ BPTR fh;
+ if((fh = FOpen(fname, MODE_NEWFILE,0))) {
+ FWrite(fh, source_data, 1, source_size);
+ FClose(fh);
+ }
+ }
+ break;
+
+ case AMINS_SAVE_TEXT:
+ save_as_text(object, fname);
+ break;
+
+ case AMINS_SAVE_COMPLETE:
+ if((lock = CreateDir(fname))) {
+ UnLock(lock);
+ save_complete(object, fname, ami_file_set_type);
+ amiga_icon_superimpose_favicon(fname, favicon, NULL);
+ }
+ break;
+
+ case AMINS_SAVE_PDF:
+#ifdef WITH_PDF_EXPORT
+ if(save_as_pdf(object, fname))
+ amiga_icon_superimpose_favicon(fname, favicon, "pdf");
+#endif
+ break;
+
+ case AMINS_SAVE_IFF:
+ if((bm = content_get_bitmap(object))) {
+ ami_bitmap_set_url(bm, hlcache_handle_get_url(object));
+ ami_bitmap_set_title(bm, content_get_title(object));
+ amiga_bitmap_save(bm, fname, 0);
+ }
+#ifdef WITH_NS_SVG
+ else if(ami_mime_compare(object, "svg") == true) {
+ ami_save_svg(object, fname);
+ }
+#endif
+ 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));
+ FClose(fh);
+ }
+ free((void *)source_data);
+ }
+ break;
+ }
+ if(object) SetComment(fname, nsurl_access(hlcache_handle_get_url(object)));
+ }
+
+ ami_update_pointer(win, GUI_POINTER_DEFAULT);
+}
+
+void ami_file_save_req(int type, struct gui_window_2 *gwin,
+ struct hlcache_handle *object)
+{
+ char *fname = AllocVecTagList(1024, NULL);
+ char *initial_fname = NULL;
+ char *fname_with_ext = NULL;
+ bool strip_ext = true;
+
+ if(object) {
+ if(type == AMINS_SAVE_SOURCE) strip_ext = false;
+ nsurl_nice(hlcache_handle_get_url(object), &initial_fname, strip_ext);
+ }
+
+ if(initial_fname != NULL) {
+ fname_with_ext = AllocVecTagList(strlen(initial_fname) + 5, NULL); /* 5 = .ext\0 */
+
+ strcpy(fname_with_ext, initial_fname);
+
+ switch(type)
+ {
+ case AMINS_SAVE_TEXT:
+ case AMINS_SAVE_SELECTION:
+ strcat(fname_with_ext, ".txt");
+ break;
+ case AMINS_SAVE_IFF:
+ strcat(fname_with_ext, ".iff");
+ break;
+ case AMINS_SAVE_PDF:
+ strcat(fname_with_ext, ".pdf");
+ break;
+ default:
+ break;
+ }
+
+ if(initial_fname) free(initial_fname);
+ }
+
+ if(AslRequestTags(savereq,
+ ASLFR_Window, gwin->win,
+ ASLFR_SleepWindow, TRUE,
+ ASLFR_TitleText, messages_get("NetSurf"),
+ ASLFR_Screen, scrn,
+ 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);
+ }
+
+ if(fname) FreeVec(fname);
+ if(fname_with_ext) FreeVec(fname_with_ext);
+}
+
+void ami_file_req_init(void)
+{
+ const char *initial_dir = nsoption_charp(download_dir);
+ Tag initial_dir_tag = ASLFR_InitialDrawer;
+
+ if(initial_dir == NULL) initial_dir_tag = TAG_IGNORE;
+
+ filereq = (struct FileRequester *)AllocAslRequest(ASL_FileRequest, NULL);
+ savereq = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
+ ASLFR_DoSaveMode, TRUE,
+ ASLFR_RejectIcons, TRUE,
+ initial_dir_tag, initial_dir,
+ TAG_DONE);
+
+ aslhookfunc.h_Entry = (void *)&ami_file_asl_mime_hook;
+ aslhookfunc.h_SubEntry = NULL;
+ aslhookfunc.h_Data = NULL;
+}
+
+void ami_file_req_free(void)
+{
+ FreeAslRequest(filereq);
+ FreeAslRequest(savereq);
+}
+
diff --git a/frontends/amiga/file.h b/frontends/amiga/file.h
new file mode 100644
index 000000000..29a76c477
--- /dev/null
+++ b/frontends/amiga/file.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2011 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/>.
+ */
+
+
+struct hlcache_object;
+struct selection;
+struct gui_window_2;
+
+struct FileRequester *filereq;
+struct FileRequester *savereq;
+
+enum {
+ AMINS_SAVE_SOURCE,
+ AMINS_SAVE_TEXT,
+ AMINS_SAVE_COMPLETE,
+ AMINS_SAVE_PDF,
+ AMINS_SAVE_IFF,
+ AMINS_SAVE_SELECTION,
+};
+
+
+void ami_file_req_init(void);
+void ami_file_req_free(void);
+
+void ami_file_open(struct gui_window_2 *gwin);
+void ami_file_save_req(int type, struct gui_window_2 *gwin,
+ struct hlcache_handle *object);
+void ami_file_save(int type, char *fname, struct Window *win,
+ struct hlcache_handle *object, struct hlcache_handle *favicon,
+ struct browser_window *bw);
diff --git a/frontends/amiga/filetype.c b/frontends/amiga/filetype.c
new file mode 100644
index 000000000..39058b41c
--- /dev/null
+++ b/frontends/amiga/filetype.c
@@ -0,0 +1,647 @@
+/*
+ * Copyright 2008, 2011 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 <stdlib.h>
+#include <string.h>
+#include "amiga/filetype.h"
+#include "amiga/misc.h"
+#include "amiga/object.h"
+#include "content/fetch.h"
+#include "content/content.h"
+#include "utils/log.h"
+#include "utils/utils.h"
+#include <proto/icon.h>
+#include <proto/dos.h>
+#include <proto/datatypes.h>
+#include <proto/exec.h>
+#include <workbench/icon.h>
+
+/**
+ * filetype -- determine the MIME type of a local file
+ */
+
+struct MinList *ami_mime_list = NULL;
+
+struct ami_mime_entry
+{
+ lwc_string *mimetype;
+ lwc_string *datatype;
+ lwc_string *filetype;
+ lwc_string *plugincmd;
+};
+
+enum
+{
+ AMI_MIME_MIMETYPE,
+ AMI_MIME_DATATYPE,
+ AMI_MIME_FILETYPE,
+ AMI_MIME_PLUGINCMD
+};
+
+const char *fetch_filetype(const char *unix_path)
+{
+ static char mimetype[50];
+ struct DiskObject *dobj = NULL;
+ struct DataType *dtn;
+ BOOL found = FALSE;
+ lwc_string *lwc_mimetype;
+
+ /* First, check if we appear to have an icon.
+ We'll just do a filename check here for quickness, although the
+ first word ought to be checked against WB_DISKMAGIC really. */
+
+ if(strncmp(unix_path + strlen(unix_path) - 5, ".info", 5) == 0) {
+ strcpy(mimetype,"image/x-amiga-icon");
+ found = TRUE;
+ }
+
+
+ /* Secondly try getting a tooltype "MIMETYPE" and use that as the MIME type.
+ Will fail over to default icons if the file doesn't have a real icon. */
+
+ if(!found) {
+ if((dobj = GetIconTags(unix_path,ICONGETA_FailIfUnavailable,FALSE,
+ TAG_DONE))) {
+ STRPTR ttype = NULL;
+ ttype = FindToolType(dobj->do_ToolTypes, "MIMETYPE");
+ if(ttype) {
+ strcpy(mimetype,ttype);
+ found = TRUE;
+ }
+ FreeDiskObject(dobj);
+ }
+ }
+
+ /* If that didn't work, use the MIME file and DataTypes */
+
+ if(!found) {
+ BPTR lock;
+ if ((lock = Lock(unix_path, ACCESS_READ))) {
+ if ((dtn = ObtainDataTypeA (DTST_FILE, (APTR)lock, NULL))) {
+ if(ami_mime_from_datatype(dtn, &lwc_mimetype, NULL)) {
+ strcpy(mimetype, lwc_string_data(lwc_mimetype));
+ found = TRUE;
+ ReleaseDataType(dtn);
+ }
+ }
+ UnLock(lock);
+ }
+ }
+
+ /* Have a quick check for file extensions (inc RISC OS filetype).
+ * Makes detection a little more robust, and some of the redirects
+ * caused by links in the SVN tree prevent NetSurf from reading the
+ * MIME type from the icon (step two, above).
+ */
+
+ if((!found) || (strcmp("text/plain", mimetype) == 0))
+ {
+ if((strncmp(unix_path + strlen(unix_path) - 4, ".css", 4) == 0) ||
+ (strncmp(unix_path + strlen(unix_path) - 4, ",f79", 4) == 0))
+ {
+ strcpy(mimetype,"text/css");
+ found = TRUE;
+ }
+
+ if((strncmp(unix_path + strlen(unix_path) - 4, ".htm", 4) == 0) ||
+ (strncmp(unix_path + strlen(unix_path) - 5, ".html", 5) == 0) ||
+ (strncmp(unix_path + strlen(unix_path) - 4, ",faf", 4) == 0))
+ {
+ strcpy(mimetype,"text/html");
+ found = TRUE;
+ }
+ if(strncmp(unix_path + strlen(unix_path) - 3, ".js", 3) == 0) {
+ strcpy(mimetype,"application/javascript");
+ found = TRUE;
+ }
+ }
+
+ if(!found) strcpy(mimetype,"text/plain"); /* If all else fails */
+
+ return mimetype;
+}
+
+const char *ami_content_type_to_file_type(content_type type)
+{
+ switch(type)
+ {
+ case CONTENT_HTML:
+ return "html";
+ break;
+
+ case CONTENT_TEXTPLAIN:
+ return "ascii";
+ break;
+
+ case CONTENT_CSS:
+ return "css";
+ break;
+
+ case CONTENT_IMAGE:
+ return "picture";
+ break;
+
+ default:
+ return "project";
+ break;
+ }
+}
+
+static void ami_mime_entry_free(void *nso)
+{
+ struct ami_mime_entry *mimeentry = (struct ami_mime_entry *)nso;
+
+ if(mimeentry->mimetype) lwc_string_unref(mimeentry->mimetype);
+ if(mimeentry->datatype) lwc_string_unref(mimeentry->datatype);
+ if(mimeentry->filetype) lwc_string_unref(mimeentry->filetype);
+ if(mimeentry->plugincmd) lwc_string_unref(mimeentry->plugincmd);
+}
+
+nserror ami_mime_init(const char *mimefile)
+{
+ lwc_error lerror;
+ char buffer[256];
+ BPTR fh = 0;
+ struct RDArgs *rargs = NULL;
+ CONST_STRPTR template = "MIMETYPE/A,DT=DATATYPE/K,TYPE=DEFICON/K,CMD=PLUGINCMD/K";
+ long rarray[] = {0,0,0,0};
+ struct nsObject *node;
+ struct ami_mime_entry *mimeentry;
+
+ LOG("mimetypes file: %s", mimefile);
+
+ if(ami_mime_list == NULL)
+ ami_mime_list = NewObjList();
+
+ rargs = AllocDosObjectTags(DOS_RDARGS,TAG_DONE);
+ if(rargs == NULL) return NSERROR_NOMEM;
+
+ if((fh = FOpen(mimefile, MODE_OLDFILE, 0)))
+ {
+ while((FGets(fh, (STRPTR)&buffer, 256) != 0))
+ {
+ rargs->RDA_Source.CS_Buffer = (char *)&buffer;
+ rargs->RDA_Source.CS_Length = 256;
+ rargs->RDA_Source.CS_CurChr = 0;
+
+ rargs->RDA_DAList = NULL;
+ rargs->RDA_Buffer = NULL;
+ rargs->RDA_BufSiz = 0;
+ rargs->RDA_ExtHelp = NULL;
+ rargs->RDA_Flags = 0;
+
+ rarray[AMI_MIME_MIMETYPE] = 0;
+ rarray[AMI_MIME_DATATYPE] = 0;
+ rarray[AMI_MIME_FILETYPE] = 0;
+ rarray[AMI_MIME_PLUGINCMD] = 0;
+
+ if(ReadArgs(template, rarray, rargs))
+ {
+ if ((node = AddObject(ami_mime_list, AMINS_MIME))) {
+ ObjectCallback(node, ami_mime_entry_free);
+ mimeentry = ami_misc_allocvec_clear(sizeof(struct ami_mime_entry), 0);
+ node->objstruct = mimeentry;
+
+ if(rarray[AMI_MIME_MIMETYPE])
+ {
+ lerror = lwc_intern_string((char *)rarray[AMI_MIME_MIMETYPE],
+ strlen((char *)rarray[AMI_MIME_MIMETYPE]), &mimeentry->mimetype);
+ if (lerror != lwc_error_ok)
+ return NSERROR_NOMEM;
+ }
+
+ if(rarray[AMI_MIME_DATATYPE])
+ {
+ lerror = lwc_intern_string((char *)rarray[AMI_MIME_DATATYPE],
+ strlen((char *)rarray[AMI_MIME_DATATYPE]), &mimeentry->datatype);
+ if (lerror != lwc_error_ok)
+ return NSERROR_NOMEM;
+ }
+
+ if(rarray[AMI_MIME_FILETYPE])
+ {
+ lerror = lwc_intern_string((char *)rarray[AMI_MIME_FILETYPE],
+ strlen((char *)rarray[AMI_MIME_FILETYPE]), &mimeentry->filetype);
+ if (lerror != lwc_error_ok)
+ return NSERROR_NOMEM;
+ }
+
+ if(rarray[AMI_MIME_PLUGINCMD])
+ {
+ lerror = lwc_intern_string((char *)rarray[AMI_MIME_PLUGINCMD],
+ strlen((char *)rarray[AMI_MIME_PLUGINCMD]), &mimeentry->plugincmd);
+ if (lerror != lwc_error_ok)
+ return NSERROR_NOMEM;
+ }
+ }
+ FreeArgs(rargs);
+ }
+ }
+ FClose(fh);
+ }
+ FreeDosObject(DOS_RDARGS, rargs);
+
+ return NSERROR_OK;
+}
+
+void ami_mime_free(void)
+{
+ ami_mime_dump();
+ FreeObjList(ami_mime_list);
+}
+
+/**
+ * Return next matching MIME entry
+ *
+ * \param search lwc_string to search for (or NULL for all)
+ * \param type of value being searched for (AMI_MIME_#?)
+ * \param start_node node to continue search (updated on exit)
+ * \return entry or NULL if no match
+ */
+
+static struct ami_mime_entry *ami_mime_entry_locate(lwc_string *search,
+ int type, struct Node **start_node)
+{
+ struct nsObject *node;
+ struct nsObject *nnode;
+ struct ami_mime_entry *mimeentry;
+ lwc_error lerror;
+ bool ret = false;
+
+ if(IsMinListEmpty(ami_mime_list)) return NULL;
+
+ if(*start_node)
+ {
+ node = (struct nsObject *)GetSucc(*start_node);
+ if(node == NULL) return NULL;
+ }
+ else
+ {
+ node = (struct nsObject *)GetHead((struct List *)ami_mime_list);
+ }
+
+ do
+ {
+ nnode=(struct nsObject *)GetSucc((struct Node *)node);
+ mimeentry = node->objstruct;
+
+ lerror = lwc_error_ok;
+
+ switch(type)
+ {
+ case AMI_MIME_MIMETYPE:
+ if(search != NULL)
+ lerror = lwc_string_isequal(mimeentry->mimetype, search, &ret);
+ else if(mimeentry->mimetype != NULL)
+ ret = true;
+ break;
+
+ case AMI_MIME_DATATYPE:
+ if(search != NULL)
+ lerror = lwc_string_isequal(mimeentry->datatype, search, &ret);
+ else if(mimeentry->datatype != NULL)
+ ret = true;
+ break;
+
+ case AMI_MIME_FILETYPE:
+ if(search != NULL)
+ lerror = lwc_string_isequal(mimeentry->filetype, search, &ret);
+ else if(mimeentry->filetype != NULL)
+ ret = true;
+ break;
+
+ case AMI_MIME_PLUGINCMD:
+ if(search != NULL)
+ lerror = lwc_string_isequal(mimeentry->plugincmd, search, &ret);
+ else if(mimeentry->plugincmd != NULL)
+ ret = true;
+ break;
+ }
+
+ if((lerror == lwc_error_ok) && (ret == true))
+ break;
+
+ } while((node=nnode));
+
+ *start_node = (struct Node *)node;
+
+ if(ret == true) return mimeentry;
+ else return NULL;
+}
+
+
+static APTR ami_mime_guess_add_datatype(struct DataType *dt, lwc_string **lwc_mimetype)
+{
+ struct nsObject *node;
+ char mimetype[100];
+ char *dt_name_lwr;
+ struct ami_mime_entry *mimeentry;
+ lwc_error lerror;
+ struct DataTypeHeader *dth = dt->dtn_Header;
+ char *p;
+
+ node = AddObject(ami_mime_list, AMINS_MIME);
+ if(node == NULL) return NULL;
+
+ mimeentry = ami_misc_allocvec_clear(sizeof(struct ami_mime_entry), 0);
+ if(mimeentry == NULL) return NULL;
+
+ node->objstruct = mimeentry;
+ ObjectCallback(node, ami_mime_entry_free);
+
+ lerror = lwc_intern_string(dth->dth_Name, strlen(dth->dth_Name), &mimeentry->datatype);
+ if (lerror != lwc_error_ok)
+ return NULL;
+
+ dt_name_lwr = strdup(dth->dth_Name);
+ if(dt_name_lwr == NULL) return NULL;
+
+ strlwr(dt_name_lwr);
+ p = dt_name_lwr;
+
+ while(*p != '\0')
+ {
+ if(*p == ' ') *p = '-';
+ if(*p == '/') *p = '-';
+ p++;
+ }
+
+ switch(dth->dth_GroupID)
+ {
+ case GID_TEXT:
+ case GID_DOCUMENT:
+ if(strcmp("ascii", dt_name_lwr)==0)
+ {
+ strcpy(mimetype,"text/plain");
+ }
+ else
+ {
+ sprintf(mimetype,"text/%s", dt_name_lwr);
+ }
+ break;
+ case GID_SOUND:
+ case GID_INSTRUMENT:
+ case GID_MUSIC:
+ sprintf(mimetype,"audio/%s", dt_name_lwr);
+ break;
+ case GID_PICTURE:
+ if(strcmp("sprite", dt_name_lwr)==0)
+ {
+ strcpy(mimetype,"image/x-riscos-sprite");
+ }
+ else
+ {
+ sprintf(mimetype,"image/%s", dt_name_lwr);
+ }
+ break;
+ case GID_ANIMATION:
+ case GID_MOVIE:
+ sprintf(mimetype,"video/%s", dt_name_lwr);
+ break;
+ case GID_SYSTEM:
+ default:
+ if(strcmp("directory", dt_name_lwr)==0)
+ {
+ strcpy(mimetype,"application/x-netsurf-directory");
+ }
+ else if(strcmp("binary", dt_name_lwr)==0)
+ {
+ strcpy(mimetype,"application/octet-stream");
+ }
+ else sprintf(mimetype,"application/%s", dt_name_lwr);
+ break;
+ }
+
+ lerror = lwc_intern_string(mimetype, strlen(mimetype), &mimeentry->mimetype);
+ if (lerror != lwc_error_ok)
+ return NULL;
+
+ *lwc_mimetype = mimeentry->mimetype;
+
+ lerror = lwc_intern_string(dt_name_lwr, strlen(dt_name_lwr), &mimeentry->filetype);
+ if (lerror != lwc_error_ok)
+ return NULL;
+
+ free(dt_name_lwr);
+ return node;
+}
+
+/**
+ * Return a MIME Type matching a DataType
+ *
+ * \param dt a DataType structure
+ * \param mimetype lwc_string to hold the MIME type
+ * \param start_node node to feed back in to continue search
+ * \return node or NULL if no match
+ */
+
+struct Node *ami_mime_from_datatype(struct DataType *dt,
+ lwc_string **mimetype, struct Node *start_node)
+{
+ struct DataTypeHeader *dth;
+ struct Node *node;
+ struct ami_mime_entry *mimeentry;
+ lwc_string *dt_name;
+ lwc_error lerror;
+
+ if(dt == NULL) return NULL;
+
+ dth = dt->dtn_Header;
+ lerror = lwc_intern_string(dth->dth_Name, strlen(dth->dth_Name), &dt_name);
+ if (lerror != lwc_error_ok)
+ return NULL;
+
+ node = start_node;
+ mimeentry = ami_mime_entry_locate(dt_name, AMI_MIME_DATATYPE, &node);
+ lwc_string_unref(dt_name);
+
+ if(mimeentry != NULL)
+ {
+ *mimetype = mimeentry->mimetype;
+ return (struct Node *)node;
+ }
+ else
+ {
+ if(start_node == NULL)
+ {
+ /* If there are no matching entries in the file, guess */
+ return ami_mime_guess_add_datatype(dt, mimetype);
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+}
+
+/**
+ * Return the DefIcons type matching a MIME type
+ *
+ * \param mimetype lwc_string MIME type
+ * \param filetype ptr to lwc_string to hold DefIcons type
+ * \param start_node node to feed back in to continue search
+ * \return node or NULL if no match
+ */
+
+struct Node *ami_mime_to_filetype(lwc_string *mimetype,
+ lwc_string **filetype, struct Node *start_node)
+{
+ struct Node *node;
+ struct ami_mime_entry *mimeentry;
+
+ node = start_node;
+ mimeentry = ami_mime_entry_locate(mimetype, AMI_MIME_MIMETYPE, &node);
+
+ if(mimeentry != NULL)
+ {
+ *filetype = mimeentry->filetype;
+ return (struct Node *)node;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+const char *ami_mime_content_to_filetype(struct hlcache_handle *c)
+{
+ struct Node *node;
+ lwc_string *filetype;
+ lwc_string *mimetype;
+
+ mimetype = content_get_mime_type(c);
+
+ node = ami_mime_to_filetype(mimetype, &filetype, NULL);
+
+ if(node && (filetype != NULL))
+ return lwc_string_data(filetype);
+ else
+ return ami_content_type_to_file_type(content_get_type(c));
+}
+
+/**
+ * Return all MIME types containing a plugincmd
+ *
+ * \param mimetype ptr to lwc_string MIME type
+ * \param start_node node to feed back in to continue search
+ * \return node or NULL if no match
+ */
+
+struct Node *ami_mime_has_cmd(lwc_string **mimetype, struct Node *start_node)
+{
+ struct Node *node;
+ struct ami_mime_entry *mimeentry;
+
+ node = start_node;
+ mimeentry = ami_mime_entry_locate(NULL, AMI_MIME_PLUGINCMD, &node);
+
+ if(mimeentry != NULL)
+ {
+ *mimetype = mimeentry->mimetype;
+ return (struct Node *)node;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+/**
+ * Return the plugincmd matching a MIME type
+ *
+ * \param mimetype lwc_string MIME type
+ * \param plugincmd ptr to lwc_string to hold plugincmd
+ * \param start_node node to feed back in to continue search
+ * \return node or NULL if no match
+ */
+
+static struct Node *ami_mime_to_plugincmd(lwc_string *mimetype,
+ lwc_string **plugincmd, struct Node *start_node)
+{
+ struct Node *node;
+ struct ami_mime_entry *mimeentry;
+
+ node = start_node;
+ mimeentry = ami_mime_entry_locate(mimetype, AMI_MIME_MIMETYPE, &node);
+
+ if(mimeentry != NULL)
+ {
+ *plugincmd = mimeentry->plugincmd;
+ return (struct Node *)node;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+lwc_string *ami_mime_content_to_cmd(struct hlcache_handle *c)
+{
+ struct Node *node;
+ lwc_string *plugincmd;
+ lwc_string *mimetype;
+
+ mimetype = content_get_mime_type(c);
+
+ node = ami_mime_to_plugincmd(mimetype,
+ &plugincmd, NULL);
+
+ if(node && (plugincmd != NULL)) return plugincmd;
+ else return NULL;
+}
+
+/**
+ * Compare the MIME type of an hlcache_handle to a DefIcons type
+ */
+
+bool ami_mime_compare(struct hlcache_handle *c, const char *type)
+{
+ bool ret = false;
+ lwc_error lerror;
+ lwc_string *filetype;
+ lwc_string *mime_filetype;
+ lwc_string *mime = content_get_mime_type(c);
+
+ if(ami_mime_to_filetype(mime, &mime_filetype, NULL) == NULL)
+ return false;
+
+ lerror = lwc_intern_string(type, strlen(type), &filetype);
+ if (lerror != lwc_error_ok)
+ return false;
+
+ lerror = lwc_string_isequal(filetype, mime_filetype, &ret);
+ if (lerror != lwc_error_ok)
+ return false;
+
+ lwc_string_unref(filetype);
+
+ return ret;
+}
+
+
+void ami_mime_dump(void)
+{
+ struct Node *node = NULL;
+ struct ami_mime_entry *mimeentry;
+
+ while((mimeentry = ami_mime_entry_locate(NULL, AMI_MIME_MIMETYPE, &node))) {
+ LOG("%s DT=\"%s\" TYPE=\"%s\" CMD=\"%s\"", mimeentry->mimetype ? lwc_string_data(mimeentry->mimetype) : "", mimeentry->datatype ? lwc_string_data(mimeentry->datatype) : "", mimeentry->filetype ? lwc_string_data(mimeentry->filetype) : "", mimeentry->plugincmd ? lwc_string_data(mimeentry->plugincmd) : "");
+ };
+}
diff --git a/frontends/amiga/filetype.h b/frontends/amiga/filetype.h
new file mode 100644
index 000000000..fc27b1df2
--- /dev/null
+++ b/frontends/amiga/filetype.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010 - 2011 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/>.
+ */
+
+#ifndef AMIGA_FILETYPE_H
+#define AMIGA_FILETYPE_H
+#include <stdbool.h>
+#include <libwapcaplet/libwapcaplet.h>
+#include "content/content_type.h"
+#include "utils/errors.h"
+#include <datatypes/datatypes.h>
+
+struct hlcache_handle;
+struct ami_mime_entry;
+
+const char *fetch_filetype(const char *unix_path);
+
+nserror ami_mime_init(const char *mimefile);
+void ami_mime_free(void);
+void ami_mime_dump(void);
+
+struct Node *ami_mime_from_datatype(struct DataType *dt,
+ lwc_string **mimetype, struct Node *start_node);
+struct Node *ami_mime_to_filetype(lwc_string *mimetype,
+ lwc_string **filetype, struct Node *start_node);
+
+const char *ami_mime_content_to_filetype(struct hlcache_handle *c);
+lwc_string *ami_mime_content_to_cmd(struct hlcache_handle *c);
+
+struct Node *ami_mime_has_cmd(lwc_string **mimetype, struct Node *start_node);
+
+bool ami_mime_compare(struct hlcache_handle *c, const char *type);
+
+/* deprecated */
+const char *ami_content_type_to_file_type(content_type type);
+
+#endif
diff --git a/frontends/amiga/font.c b/frontends/amiga/font.c
new file mode 100644
index 000000000..1c9702af2
--- /dev/null
+++ b/frontends/amiga/font.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2008 - 2016 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 <proto/diskfont.h>
+#include <proto/exec.h>
+#include <proto/graphics.h>
+
+#include "utils/log.h"
+#include "utils/nsoption.h"
+#include "desktop/browser.h"
+#include "desktop/gui_layout.h"
+
+#include "amiga/font.h"
+#include "amiga/font_bullet.h"
+#include "amiga/font_diskfont.h"
+#include "amiga/font_scan.h"
+
+static ULONG ami_devicedpi = 72;
+static ULONG ami_xdpi = 72;
+
+ULONG ami_font_dpi_get_devicedpi(void)
+{
+ return ami_devicedpi;
+}
+
+ULONG ami_font_dpi_get_xdpi(void)
+{
+ return ami_xdpi;
+}
+
+void ami_font_setdevicedpi(int id)
+{
+ DisplayInfoHandle dih;
+ struct DisplayInfo dinfo;
+
+ if(nsoption_bool(bitmap_fonts) == true) {
+ LOG("WARNING: Using diskfont.library for text. Forcing DPI to 72.");
+ nsoption_set_int(screen_ydpi, 72);
+ }
+
+ ULONG ydpi = nsoption_int(screen_ydpi);
+ ULONG xdpi = nsoption_int(screen_ydpi);
+ browser_set_dpi(nsoption_int(screen_ydpi));
+
+ if(id && (nsoption_int(monitor_aspect_x) != 0) && (nsoption_int(monitor_aspect_y) != 0))
+ {
+ if((dih = FindDisplayInfo(id)))
+ {
+ if(GetDisplayInfoData(dih, &dinfo, sizeof(struct DisplayInfo),
+ DTAG_DISP, 0))
+ {
+ int xres = dinfo.Resolution.x;
+ int yres = dinfo.Resolution.y;
+
+ if((nsoption_int(monitor_aspect_x) != 4) || (nsoption_int(monitor_aspect_y) != 3))
+ {
+ /* AmigaOS sees 4:3 modes as square in the DisplayInfo database,
+ * so we correct other modes to "4:3 equiv" here. */
+ xres = (xres * nsoption_int(monitor_aspect_x)) / 4;
+ yres = (yres * nsoption_int(monitor_aspect_y)) / 3;
+ }
+
+ xdpi = (yres * ydpi) / xres;
+
+ LOG("XDPI = %ld, YDPI = %ld (DisplayInfo resolution %d x %d, corrected %d x %d)", xdpi, ydpi, dinfo.Resolution.x, dinfo.Resolution.y, xres, yres);
+ }
+ }
+ }
+
+ ami_xdpi = xdpi;
+ ami_devicedpi = (xdpi << 16) | ydpi;
+}
+
+/* The below are simple font routines which should not be used for page rendering */
+
+struct TextFont *ami_font_open_disk_font(struct TextAttr *tattr)
+{
+ struct TextFont *tfont = OpenDiskFont(tattr);
+ return tfont;
+}
+
+void ami_font_close_disk_font(struct TextFont *tfont)
+{
+ CloseFont(tfont);
+}
+
+/* Font initialisation */
+void ami_font_init(void)
+{
+ if(nsoption_bool(bitmap_fonts) == false) {
+ ami_font_bullet_init();
+ } else {
+ ami_font_diskfont_init();
+ }
+}
+
+void ami_font_fini(void)
+{
+ if(nsoption_bool(bitmap_fonts) == false) {
+ ami_font_bullet_fini();
+ }
+}
+
+/* Stub entry points */
+static nserror ami_font_width(const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int *width)
+{
+ if(__builtin_expect(ami_nsfont == NULL, 0)) return false;
+ return ami_nsfont->width(fstyle, string, length, width);
+}
+
+static nserror ami_font_position(const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x)
+{
+ if(__builtin_expect(ami_nsfont == NULL, 0)) return false;
+ return ami_nsfont->posn(fstyle, string, length, x, char_offset, actual_x);
+}
+
+static nserror ami_font_split(const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x)
+{
+ if(__builtin_expect(ami_nsfont == NULL, 0)) return false;
+ return ami_nsfont->split(fstyle, string, length, x, char_offset, actual_x);
+}
+
+static struct gui_layout_table layout_table = {
+ .width = ami_font_width,
+ .position = ami_font_position,
+ .split = ami_font_split,
+};
+
+struct gui_layout_table *ami_layout_table = &layout_table;
diff --git a/frontends/amiga/font.h b/frontends/amiga/font.h
new file mode 100755
index 000000000..cd526057f
--- /dev/null
+++ b/frontends/amiga/font.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008, 2009, 2012, 2016 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/>.
+ */
+
+#ifndef AMIGA_FONT_H
+#define AMIGA_FONT_H
+
+#include "desktop/plotters.h"
+#include "utils/errors.h"
+#include <graphics/rastport.h>
+#include <graphics/text.h>
+
+void ami_font_init(void);
+void ami_font_fini(void);
+
+/* DPI stuff */
+void ami_font_setdevicedpi(int id);
+ULONG ami_font_dpi_get_devicedpi(void);
+ULONG ami_font_dpi_get_xdpi(void);
+
+/* Simple diskfont functions for graphics.library use (not page rendering) */
+struct TextFont *ami_font_open_disk_font(struct TextAttr *tattr);
+void ami_font_close_disk_font(struct TextFont *tfont);
+
+/* Font engine tables */
+struct ami_font_functions {
+ nserror (*width)(const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int *width);
+
+ nserror (*posn)(const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x);
+
+ nserror (*split)(const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x);
+
+ ULONG (*text)(struct RastPort *rp, const char *string,
+ ULONG length, const plot_font_style_t *fstyle,
+ ULONG x, ULONG y, bool aa);
+};
+
+const struct ami_font_functions *ami_nsfont;
+
+struct gui_layout_table *ami_layout_table;
+
+#endif
+
diff --git a/frontends/amiga/font_bullet.c b/frontends/amiga/font_bullet.c
new file mode 100644
index 000000000..3032b9735
--- /dev/null
+++ b/frontends/amiga/font_bullet.c
@@ -0,0 +1,895 @@
+/*
+ * Copyright 2008 - 2016 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 <stdlib.h>
+
+#ifndef __amigaos4__
+#include <proto/bullet.h>
+#endif
+#include <proto/diskfont.h>
+#include <proto/exec.h>
+#include <proto/graphics.h>
+#include <proto/utility.h>
+
+#include <diskfont/diskfonttag.h>
+#include <diskfont/oterrors.h>
+
+#include "amiga/font.h"
+#include "amiga/font_bullet.h"
+#include "amiga/font_cache.h"
+#include "amiga/font_scan.h"
+
+#include "utils/log.h"
+#include "utils/nsoption.h"
+#include "utils/utf8.h"
+#include "utils/utils.h"
+
+#define NSA_UNICODE_FONT PLOT_FONT_FAMILY_COUNT
+
+#define NSA_NORMAL 0
+#define NSA_ITALIC 1
+#define NSA_BOLD 2
+#define NSA_BOLDITALIC 3
+#define NSA_OBLIQUE 4
+#define NSA_BOLDOBLIQUE 6
+
+#define NSA_VALUE_BOLDX (1 << 12)
+#define NSA_VALUE_BOLDY 0
+#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)
+
+const uint16 sc_table[] = {
+ 0x0061, 0x1D00, /* a */
+ 0x0062, 0x0299, /* b */
+ 0x0063, 0x1D04, /* c */
+ 0x0064, 0x1D05, /* d */
+ 0x0065, 0x1D07, /* e */
+ 0x0066, 0xA730, /* f */
+ 0x0067, 0x0262, /* g */
+ 0x0068, 0x029C, /* h */
+ 0x0069, 0x026A, /* i */
+ 0x006A, 0x1D0A, /* j */
+ 0x006B, 0x1D0B, /* k */
+ 0x006C, 0x029F, /* l */
+ 0x006D, 0x1D0D, /* m */
+ 0x006E, 0x0274, /* n */
+ 0x006F, 0x1D0F, /* o */
+ 0x0070, 0x1D18, /* p */
+ 0x0071, 0xA7EE, /* q (proposed) (Adobe codepoint 0xF771) */
+ 0x0072, 0x0280, /* r */
+ 0x0073, 0xA731, /* s */
+ 0x0074, 0x1D1B, /* t */
+ 0x0075, 0x1D1C, /* u */
+ 0x0076, 0x1D20, /* v */
+ 0x0077, 0x1D21, /* w */
+ 0x0078, 0xA7EF, /* x (proposed) (Adobe codepoint 0xF778) */
+ 0x0079, 0x028F, /* y */
+ 0x007A, 0x1D22, /* z */
+
+ 0x00C6, 0x1D01, /* ae */
+ 0x0153, 0x0276, /* oe */
+
+#if 0
+/* TODO: fill in the non-small caps character ids for these */
+ 0x0000, 0x1D03, /* barred b */
+ 0x0000, 0x0281, /* inverted r */
+ 0x0000, 0x1D19, /* reversed r */
+ 0x0000, 0x1D1A, /* turned r */
+ 0x0000, 0x029B, /* g with hook */
+ 0x0000, 0x1D06, /* eth Ð */
+ 0x0000, 0x1D0C, /* l with stroke */
+ 0x0000, 0xA7FA, /* turned m */
+ 0x0000, 0x1D0E, /* reversed n */
+ 0x0000, 0x1D10, /* open o */
+ 0x0000, 0x1D15, /* ou */
+ 0x0000, 0x1D23, /* ezh */
+ 0x0000, 0x1D26, /* gamma */
+ 0x0000, 0x1D27, /* lamda */
+ 0x0000, 0x1D28, /* pi */
+ 0x0000, 0x1D29, /* rho */
+ 0x0000, 0x1D2A, /* psi */
+ 0x0000, 0x1D2B, /* el */
+ 0x0000, 0xA776, /* rum */
+
+ 0x0000, 0x1DDB, /* combining g */
+ 0x0000, 0x1DDE, /* combining l */
+ 0x0000, 0x1DDF, /* combining m */
+ 0x0000, 0x1DE1, /* combining n */
+ 0x0000, 0x1DE2, /* combining r */
+
+ 0x0000, 0x1DA6, /* modifier i */
+ 0x0000, 0x1DA7, /* modifier i with stroke */
+ 0x0000, 0x1DAB, /* modifier l */
+ 0x0000, 0x1DB0, /* modifier n */
+ 0x0000, 0x1DB8, /* modifier u */
+#endif
+ 0, 0};
+
+lwc_string *glypharray[0xffff + 1];
+
+static struct List ami_diskfontlib_list;
+
+static inline int32 ami_font_plot_glyph(struct OutlineFont *ofont, struct RastPort *rp,
+ uint16 *char1, uint16 *char2, uint32 x, uint32 y, uint32 emwidth, bool aa);
+static inline int32 ami_font_width_glyph(struct OutlineFont *ofont,
+ const uint16 *char1, const uint16 *char2, uint32 emwidth);
+static struct OutlineFont *ami_open_outline_font(const plot_font_style_t *fstyle,
+ const uint16 *codepoint);
+static inline ULONG ami_font_unicode_width(const char *string, ULONG length,
+ const plot_font_style_t *fstyle, ULONG x, ULONG y, bool aa);
+
+static inline int amiga_nsfont_utf16_char_length(const uint16 *char1)
+{
+ if (__builtin_expect(((*char1 < 0xD800) || (0xDBFF < *char1)), 1)) {
+ return 1;
+ } else {
+ return 2;
+ }
+}
+
+static inline uint32 amiga_nsfont_decode_surrogate(const uint16 *char1)
+{
+ if(__builtin_expect((amiga_nsfont_utf16_char_length(char1) == 2), 0)) {
+ return ((uint32)char1[0] << 10) + char1[1] - 0x35FDC00;
+ } else {
+ return (uint32)*char1;
+ }
+}
+
+static nserror amiga_nsfont_width(const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int *width)
+{
+ *width = ami_font_unicode_width(string, length, fstyle, 0, 0, false);
+
+ if(*width <= 0) *width == length; // fudge
+
+ return NSERROR_OK;
+}
+
+/**
+ * Find the position in a string where an x coordinate falls.
+ *
+ * \param fstyle style for this text
+ * \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
+ * \return true on success, false on error and error reported
+ */
+
+static nserror amiga_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)
+{
+ uint16 *utf16 = NULL, *outf16 = NULL;
+ uint16 *utf16next = NULL;
+ struct OutlineFont *ofont, *ufont = NULL;
+ int tx = 0;
+ uint32 utf8_pos = 0;
+ int utf16charlen;
+ ULONG emwidth = (ULONG)NSA_FONT_EMWIDTH(fstyle->size);
+ int32 tempx;
+
+ if(utf8_to_enc(string,"UTF-16",length,(char **)&utf16) != NSERROR_OK) return NSERROR_INVALID;
+ outf16 = utf16;
+ if(!(ofont = ami_open_outline_font(fstyle, 0))) return NSERROR_INVALID;
+
+ *char_offset = 0;
+ *actual_x = 0;
+
+ while (utf8_pos < length) {
+ utf16charlen = amiga_nsfont_utf16_char_length(utf16);
+ utf16next = &utf16[utf16charlen];
+
+ tempx = ami_font_width_glyph(ofont, utf16, utf16next, emwidth);
+
+ if (tempx == 0) {
+ if (ufont == NULL)
+ ufont = ami_open_outline_font(fstyle, utf16);
+
+ if (ufont)
+ tempx = ami_font_width_glyph(ufont, utf16,
+ utf16next, emwidth);
+ }
+
+ tx += tempx;
+ utf16 = utf16next;
+ utf8_pos = utf8_next(string, length, utf8_pos);
+
+ if(tx < x) {
+ *actual_x = tx;
+ *char_offset = utf8_pos;
+ } else {
+ if((x - *actual_x) > (tx - x)) {
+ *actual_x = tx;
+ *char_offset = utf8_pos;
+ }
+ free(outf16);
+ return NSERROR_OK;
+ }
+ }
+
+ *actual_x = tx;
+ *char_offset = length;
+
+ free(outf16);
+ return NSERROR_OK;
+}
+
+
+/**
+ * Find where to split a string to make it fit a width.
+ *
+ * \param fstyle style for this text
+ * \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, [1..length]
+ * \param actual_x updated to x coordinate of character closest to x
+ * \return true on success, false on error and error reported
+ *
+ * On exit, char_offset indicates first character after split point.
+ *
+ * Note: char_offset of 0 should never be returned.
+ *
+ * Returns:
+ * char_offset giving split point closest to x, where actual_x <= x
+ * else
+ * char_offset giving split point closest to x, where actual_x > x
+ *
+ * Returning char_offset == length means no split possible
+ */
+
+static nserror amiga_nsfont_split(const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x)
+{
+ uint16 *utf16_str = NULL;
+ const uint16 *utf16 = NULL;
+ const uint16 *utf16next = NULL;
+ struct OutlineFont *ofont, *ufont = NULL;
+ int tx = 0;
+ uint32 utf8_pos = 0;
+ int32 tempx = 0;
+ ULONG emwidth = (ULONG)NSA_FONT_EMWIDTH(fstyle->size);
+
+ /* Get utf16 conversion of string for glyph measuring routines */
+ if (utf8_to_enc(string, "UTF-16", length, (char **)&utf16_str) !=
+ NSERROR_OK)
+ return NSERROR_INVALID;
+
+ utf16 = utf16_str;
+ if (!(ofont = ami_open_outline_font(fstyle, 0)))
+ return NSERROR_INVALID;
+
+ *char_offset = 0;
+ *actual_x = 0;
+
+ if (*utf16 == 0xFEFF) utf16++;
+
+ while (utf8_pos < length) {
+ if ((*utf16 < 0xD800) || (0xDBFF < *utf16))
+ utf16next = utf16 + 1;
+ else
+ utf16next = utf16 + 2;
+
+ tempx = ami_font_width_glyph(ofont, utf16, utf16next, emwidth);
+
+ if (tempx == 0) {
+ if (ufont == NULL)
+ ufont = ami_open_outline_font(fstyle, utf16);
+
+ if (ufont)
+ tempx = ami_font_width_glyph(ufont, utf16,
+ utf16next, emwidth);
+ }
+
+ /* Check whether we have a space */
+ if (*(string + utf8_pos) == ' ') {
+ /* Got a space */
+ *actual_x = tx;
+ *char_offset = utf8_pos;
+ }
+
+ tx += tempx;
+ if ((x < tx) && (*char_offset != 0)) {
+ /* Reached available width, and a space was found;
+ * split there. */
+ free(utf16_str);
+ return NSERROR_OK;
+ }
+
+ utf16 = utf16next;
+ utf8_pos = utf8_next(string, length, utf8_pos);
+ }
+
+ free(utf16_str);
+
+ /* No spaces to split at, or everything fits */
+ assert(*char_offset == 0 || x >= tx);
+
+ *char_offset = length;
+ *actual_x = tx;
+ return NSERROR_OK;
+}
+
+/**
+ * Search for a font in the list and load from disk if not present
+ */
+static struct ami_font_cache_node *ami_font_open(const char *font, bool critical)
+{
+ struct ami_font_cache_node *nodedata = ami_font_cache_locate(font);
+ if(nodedata) return nodedata;
+
+ nodedata = ami_font_cache_alloc_entry(font);
+
+ if(nodedata == NULL) {
+ amiga_warn_user("NoMemory", "");
+ return NULL;
+ }
+
+ nodedata->font = OpenOutlineFont(font, &ami_diskfontlib_list, OFF_OPEN);
+
+ if(!nodedata->font)
+ {
+ LOG("Requested font not found: %s", font);
+ if(critical == true) amiga_warn_user("CompError", font);
+ FreeVec(nodedata);
+ return NULL;
+ }
+
+ nodedata->bold = (char *)GetTagData(OT_BName, 0, nodedata->font->olf_OTagList);
+ if(nodedata->bold)
+ LOG("Bold font defined for %s is %s", font, nodedata->bold);
+ else
+ LOG("Warning: No designed bold font defined for %s", font);
+
+ nodedata->italic = (char *)GetTagData(OT_IName, 0, nodedata->font->olf_OTagList);
+ if(nodedata->italic)
+ LOG("Italic font defined for %s is %s", font, nodedata->italic);
+ else
+ LOG("Warning: No designed italic font defined for %s", font);
+
+ nodedata->bolditalic = (char *)GetTagData(OT_BIName, 0, nodedata->font->olf_OTagList);
+ if(nodedata->bolditalic)
+ LOG("Bold-italic font defined for %s is %s", font, nodedata->bolditalic);
+ else
+ LOG("Warning: No designed bold-italic font defined for %s", font);
+
+ ami_font_cache_insert(nodedata, font);
+ return nodedata;
+}
+
+/**
+ * Open an outline font in the specified size and style
+ *
+ * \param fstyle font style structure
+ * \param codepoint open a default font instead of the one specified by fstyle
+ * \return outline font or NULL on error
+ */
+static struct OutlineFont *ami_open_outline_font(const plot_font_style_t *fstyle,
+ const uint16 *codepoint)
+{
+ struct ami_font_cache_node *node;
+ struct ami_font_cache_node *designed_node = NULL;
+ struct OutlineFont *ofont;
+ char *fontname;
+ ULONG ysize;
+ int tstyle = 0;
+ plot_font_generic_family_t fontfamily;
+ ULONG emboldenx = 0;
+ ULONG emboldeny = 0;
+ ULONG shearsin = 0;
+ ULONG shearcos = (1 << 16);
+
+ if(codepoint) fontfamily = NSA_UNICODE_FONT;
+ else fontfamily = fstyle->family;
+
+ switch(fontfamily)
+ {
+ case PLOT_FONT_FAMILY_SANS_SERIF:
+ fontname = nsoption_charp(font_sans);
+ break;
+ case PLOT_FONT_FAMILY_SERIF:
+ fontname = nsoption_charp(font_serif);
+ break;
+ case PLOT_FONT_FAMILY_MONOSPACE:
+ fontname = nsoption_charp(font_mono);
+ break;
+ case PLOT_FONT_FAMILY_CURSIVE:
+ fontname = nsoption_charp(font_cursive);
+ break;
+ case PLOT_FONT_FAMILY_FANTASY:
+ fontname = nsoption_charp(font_fantasy);
+ break;
+ case NSA_UNICODE_FONT:
+ default:
+ if(__builtin_expect((amiga_nsfont_utf16_char_length(codepoint) == 2), 0)) {
+ /* Multi-byte character */
+ fontname = nsoption_charp(font_surrogate);
+ } else {
+ fontname = (char *)ami_font_scan_lookup(codepoint, glypharray);
+ }
+ if(fontname == NULL) return NULL;
+ break;
+ }
+
+ node = ami_font_open(fontname, true);
+ if(!node) return NULL;
+
+ if (fstyle->flags & FONTF_OBLIQUE)
+ tstyle = NSA_OBLIQUE;
+
+ if (fstyle->flags & FONTF_ITALIC)
+ tstyle = NSA_ITALIC;
+
+ if (fstyle->weight >= 700)
+ tstyle += NSA_BOLD;
+
+ switch(tstyle)
+ {
+ case NSA_ITALIC:
+ if(node->italic) designed_node = ami_font_open(node->italic, false);
+
+ if(designed_node == NULL) {
+ shearsin = NSA_VALUE_SHEARSIN;
+ shearcos = NSA_VALUE_SHEARCOS;
+ }
+ break;
+
+ case NSA_OBLIQUE:
+ shearsin = NSA_VALUE_SHEARSIN;
+ shearcos = NSA_VALUE_SHEARCOS;
+ break;
+
+ case NSA_BOLD:
+ if(node->bold) designed_node = ami_font_open(node->bold, false);
+
+ if(designed_node == NULL) {
+ emboldenx = NSA_VALUE_BOLDX;
+ emboldeny = NSA_VALUE_BOLDY;
+ }
+ break;
+
+ case NSA_BOLDOBLIQUE:
+ shearsin = NSA_VALUE_SHEARSIN;
+ shearcos = NSA_VALUE_SHEARCOS;
+
+ if(node->bold) designed_node = ami_font_open(node->bold, false);
+
+ if(designed_node == NULL) {
+ emboldenx = NSA_VALUE_BOLDX;
+ emboldeny = NSA_VALUE_BOLDY;
+ }
+ break;
+
+ case NSA_BOLDITALIC:
+ if(node->bolditalic) designed_node = ami_font_open(node->bolditalic, false);
+
+ if(designed_node == NULL) {
+ emboldenx = NSA_VALUE_BOLDX;
+ emboldeny = NSA_VALUE_BOLDY;
+ shearsin = NSA_VALUE_SHEARSIN;
+ shearcos = NSA_VALUE_SHEARCOS;
+ }
+ break;
+ }
+
+ /* Scale to 16.16 fixed point */
+ ysize = fstyle->size * ((1 << 16) / FONT_SIZE_SCALE);
+
+ if(designed_node == NULL) {
+ ofont = node->font;
+ } else {
+ ofont = designed_node->font;
+ }
+
+#ifndef __amigaos4__
+ struct BulletBase *BulletBase = ofont->BulletBase;
+#endif
+
+ if(ESetInfo(AMI_OFONT_ENGINE,
+ OT_DeviceDPI, ami_font_dpi_get_devicedpi(),
+ OT_PointHeight, ysize,
+ OT_EmboldenX, emboldenx,
+ OT_EmboldenY, emboldeny,
+ OT_ShearSin, shearsin,
+ OT_ShearCos, shearcos,
+ TAG_END) == OTERR_Success)
+ return ofont;
+
+ return NULL;
+}
+
+static inline int32 ami_font_plot_glyph(struct OutlineFont *ofont, struct RastPort *rp,
+ uint16 *char1, uint16 *char2, uint32 x, uint32 y, uint32 emwidth, bool aa)
+{
+ struct GlyphMap *glyph;
+ UBYTE *glyphbm;
+ int32 char_advance = 0;
+ FIXED kern = 0;
+ ULONG glyphmaptag;
+ ULONG template_type;
+ uint32 long_char_1 = 0, long_char_2 = 0;
+#ifndef __amigaos4__
+ struct BulletBase *BulletBase = ofont->BulletBase;
+#endif
+
+#ifndef __amigaos4__
+ if (__builtin_expect(((*char1 >= 0xD800) && (*char1 <= 0xDBFF)), 0)) {
+ /* We don't support UTF-16 surrogates yet, so just return. */
+ return 0;
+ }
+
+ if (__builtin_expect(((*char2 >= 0xD800) && (*char2 <= 0xDBFF)), 0)) {
+ /* Don't attempt to kern a UTF-16 surrogate */
+ *char2 = 0;
+ }
+#endif
+
+#ifdef __amigaos4__
+ if(__builtin_expect(aa == true, 1)) {
+ glyphmaptag = OT_GlyphMap8Bit;
+ template_type = BLITT_ALPHATEMPLATE;
+ } else {
+#endif
+ glyphmaptag = OT_GlyphMap;
+#ifdef __amigaos4__
+ template_type = BLITT_TEMPLATE;
+ }
+#endif
+
+ long_char_1 = amiga_nsfont_decode_surrogate(char1);
+ long_char_2 = amiga_nsfont_decode_surrogate(char2);
+ /**\todo use OT_GlyphCode_32 so we get an error for old font engines */
+
+ if(ESetInfo(AMI_OFONT_ENGINE,
+ OT_GlyphCode, long_char_1,
+ OT_GlyphCode2, long_char_2,
+ TAG_END) == OTERR_Success)
+ {
+ if(EObtainInfo(AMI_OFONT_ENGINE,
+ glyphmaptag, &glyph,
+ TAG_END) == 0)
+ {
+ glyphbm = glyph->glm_BitMap;
+ if(!glyphbm) return 0;
+
+ if(rp) {
+#ifdef __amigaos4__
+ BltBitMapTags(BLITA_SrcX, glyph->glm_BlackLeft,
+ BLITA_SrcY, glyph->glm_BlackTop,
+ BLITA_DestX, x - glyph->glm_X0 + glyph->glm_BlackLeft,
+ BLITA_DestY, y - glyph->glm_Y0 + glyph->glm_BlackTop,
+ BLITA_Width, glyph->glm_BlackWidth,
+ BLITA_Height, glyph->glm_BlackHeight,
+ BLITA_Source, glyphbm,
+ BLITA_SrcType, template_type,
+ BLITA_Dest, rp,
+ BLITA_DestType, BLITT_RASTPORT,
+ BLITA_SrcBytesPerRow, glyph->glm_BMModulo,
+ TAG_DONE);
+#else
+ /* On OS3 the glyph needs to be in chip RAM */
+ void *chip_glyph = AllocVec(glyph->glm_BMModulo * glyph->glm_BMRows, MEMF_CHIP);
+ if(chip_glyph != NULL) {
+ CopyMem(glyphbm, chip_glyph, glyph->glm_BMModulo * glyph->glm_BMRows);
+
+ BltTemplate(chip_glyph + (glyph->glm_BMModulo * glyph->glm_BlackTop) +
+ ((glyph->glm_BlackLeft >> 4) << 1),
+ glyph->glm_BlackLeft & 0xF, glyph->glm_BMModulo, rp,
+ x - glyph->glm_X0 + glyph->glm_BlackLeft,
+ y - glyph->glm_Y0 + glyph->glm_BlackTop,
+ glyph->glm_BlackWidth, glyph->glm_BlackHeight);
+
+ FreeVec(chip_glyph);
+ }
+#endif
+ }
+
+ kern = 0;
+
+ if(*char2) EObtainInfo(AMI_OFONT_ENGINE,
+ OT_TextKernPair, &kern,
+ TAG_END);
+
+ char_advance = (ULONG)(((glyph->glm_Width - kern) * emwidth) / 65536);
+
+ EReleaseInfo(AMI_OFONT_ENGINE,
+ glyphmaptag, glyph,
+ TAG_END);
+
+ if(*char2) EReleaseInfo(AMI_OFONT_ENGINE,
+ OT_TextKernPair, kern,
+ TAG_END);
+ }
+ }
+
+ return char_advance;
+}
+
+static inline int32 ami_font_width_glyph(struct OutlineFont *ofont,
+ const uint16 *char1, const uint16 *char2, uint32 emwidth)
+{
+ int32 char_advance = 0;
+ FIXED kern = 0;
+ struct MinList *gwlist = NULL;
+ FIXED char1w = 0;
+ struct GlyphWidthEntry *gwnode;
+ bool skip_c2 = false;
+ uint32 long_char_1 = 0;
+ uint32 long_char_2;
+#ifndef __amigaos4__
+ struct BulletBase *BulletBase = ofont->BulletBase;
+#endif
+
+#ifndef __amigaos4__
+ if (__builtin_expect(((*char1 >= 0xD800) && (*char1 <= 0xDBFF)), 0)) {
+ /* We don't support UTF-16 surrogates yet, so just return. */
+ return 0;
+ }
+
+ if (__builtin_expect(((*char2 >= 0xD800) && (*char2 <= 0xDBFF)), 0)) {
+ /* Don't attempt to kern a UTF-16 surrogate */
+ skip_c2 = true;
+ }
+#endif
+
+ if (*char2 < 0x0020) skip_c2 = true;
+
+ long_char_1 = amiga_nsfont_decode_surrogate(char1);
+ /**\todo use OT_GlyphCode_32 so we get an error for old font engines */
+
+ if(ESetInfo(AMI_OFONT_ENGINE,
+ OT_GlyphCode, long_char_1,
+ OT_GlyphCode2, long_char_1,
+ TAG_END) == OTERR_Success)
+ {
+ if(EObtainInfo(AMI_OFONT_ENGINE,
+ OT_WidthList, &gwlist,
+ TAG_END) == 0)
+ {
+ gwnode = (struct GlyphWidthEntry *)GetHead((struct List *)gwlist);
+ if(gwnode) char1w = gwnode->gwe_Width;
+
+ kern = 0;
+
+ if(!skip_c2) {
+ long_char_2 = amiga_nsfont_decode_surrogate(char2);
+ if(ESetInfo(AMI_OFONT_ENGINE,
+ OT_GlyphCode, long_char_1,
+ OT_GlyphCode2, long_char_2,
+ TAG_END) == OTERR_Success)
+ {
+ EObtainInfo(AMI_OFONT_ENGINE,
+ OT_TextKernPair, &kern,
+ TAG_END);
+ }
+ }
+ char_advance = (ULONG)(((char1w - kern) * emwidth) / 65536);
+
+ if(!skip_c2) EReleaseInfo(AMI_OFONT_ENGINE,
+ OT_TextKernPair, kern,
+ TAG_END);
+
+ EReleaseInfo(AMI_OFONT_ENGINE,
+ OT_WidthList, gwlist,
+ TAG_END);
+ }
+ }
+
+ return char_advance;
+}
+
+static const uint16 *ami_font_translate_smallcaps(uint16 *utf16char)
+{
+ const uint16 *p;
+ p = &sc_table[0];
+
+ while (*p != 0)
+ {
+ if(*p == *utf16char) return &p[1];
+ p++;
+ }
+
+ return utf16char;
+}
+
+static ULONG amiga_nsfont_text(struct RastPort *rp, const char *string, ULONG length,
+ const plot_font_style_t *fstyle, ULONG dx, ULONG dy, bool aa)
+{
+ uint16 *utf16 = NULL, *outf16 = NULL;
+ uint16 *utf16charsc = 0, *utf16nextsc = 0;
+ uint16 *utf16next = 0;
+ int utf16charlen;
+ struct OutlineFont *ofont, *ufont = NULL;
+ uint32 x=0;
+ int32 tempx = 0;
+ ULONG emwidth = (ULONG)NSA_FONT_EMWIDTH(fstyle->size);
+ uint16 utf16_a = 0x41;
+
+ if(!string || string[0]=='\0') return 0;
+ if(!length) return 0;
+ if(rp == NULL) return 0;
+
+ if(utf8_to_enc(string,"UTF-16",length,(char **)&utf16) != NSERROR_OK) return 0;
+ outf16 = utf16;
+ if(!(ofont = ami_open_outline_font(fstyle, 0))) {
+ if(!(ofont = ami_open_outline_font(fstyle, &utf16_a))) return 0;
+ }
+
+ while(*utf16 != 0)
+ {
+ utf16charlen = amiga_nsfont_utf16_char_length(utf16);
+ utf16next = &utf16[utf16charlen];
+
+ if(fstyle->flags & FONTF_SMALLCAPS)
+ {
+ utf16charsc = (uint16 *)ami_font_translate_smallcaps(utf16);
+ utf16nextsc = (uint16 *)ami_font_translate_smallcaps(utf16next);
+
+ tempx = ami_font_plot_glyph(ofont, rp, utf16charsc, utf16nextsc,
+ dx + x, dy, emwidth, aa);
+ }
+ else tempx = 0;
+
+ if(tempx == 0) {
+ tempx = ami_font_plot_glyph(ofont, rp, utf16, utf16next,
+ dx + x, dy, emwidth, aa);
+ }
+
+ if(tempx == 0)
+ {
+ if(ufont == NULL)
+ {
+ ufont = ami_open_outline_font(fstyle, utf16);
+ }
+
+ if(ufont) {
+ tempx = ami_font_plot_glyph(ufont, rp, utf16, utf16next,
+ dx + x, dy, emwidth, aa);
+ }
+ }
+
+ x += tempx;
+
+ utf16 += utf16charlen;
+ }
+
+ free(outf16);
+ return x;
+}
+
+static inline ULONG ami_font_unicode_width(const char *string, ULONG length,
+ const plot_font_style_t *fstyle, ULONG dx, ULONG dy, bool aa)
+{
+ uint16 *utf16 = NULL, *outf16 = NULL;
+ uint16 *utf16charsc = 0, *utf16nextsc = 0;
+ uint16 *utf16next = 0;
+ int utf16charlen;
+ struct OutlineFont *ofont, *ufont = NULL;
+ uint32 x=0;
+ int32 tempx = 0;
+ ULONG emwidth = (ULONG)NSA_FONT_EMWIDTH(fstyle->size);
+ uint16 utf16_a = 0x41;
+
+ if(!string || string[0]=='\0') return 0;
+ if(!length) return 0;
+
+ if(utf8_to_enc(string,"UTF-16",length,(char **)&utf16) != NSERROR_OK) return 0;
+ outf16 = utf16;
+ if(!(ofont = ami_open_outline_font(fstyle, 0))) {
+ if(!(ofont = ami_open_outline_font(fstyle, &utf16_a))) return 0;
+ }
+
+ while(*utf16 != 0)
+ {
+ utf16charlen = amiga_nsfont_utf16_char_length(utf16);
+ utf16next = &utf16[utf16charlen];
+
+ if(fstyle->flags & FONTF_SMALLCAPS)
+ {
+ utf16charsc = (uint16 *)ami_font_translate_smallcaps(utf16);
+ utf16nextsc = (uint16 *)ami_font_translate_smallcaps(utf16next);
+
+ tempx = ami_font_width_glyph(ofont, utf16charsc, utf16nextsc, emwidth);
+ }
+ else tempx = 0;
+
+ if(tempx == 0) {
+ tempx = ami_font_width_glyph(ofont, utf16, utf16next, emwidth);
+ }
+
+ if(tempx == 0)
+ {
+ if(ufont == NULL)
+ {
+ ufont = ami_open_outline_font(fstyle, utf16);
+ }
+
+ if(ufont)
+ {
+ tempx = ami_font_width_glyph(ufont, utf16, utf16next, emwidth);
+ }
+ }
+
+ x += tempx;
+
+ utf16 += utf16charlen;
+ }
+
+ free(outf16);
+ return x;
+}
+
+void ami_font_bullet_close(void *nso)
+{
+ struct ami_font_cache_node *node = (struct ami_font_cache_node *)nso;
+ CloseOutlineFont(node->font, &ami_diskfontlib_list);
+}
+
+const struct ami_font_functions ami_font_bullet_table = {
+ amiga_nsfont_width,
+ amiga_nsfont_position_in_string,
+ amiga_nsfont_split,
+ amiga_nsfont_text
+};
+
+void ami_font_bullet_init(void)
+{
+ /* Initialise Unicode font scanner */
+ ami_font_initscanner(false, true);
+
+ /* Initialise font caching etc lists */
+ ami_font_cache_init();
+
+ /* List for diskfont internal cache */
+ NewList(&ami_diskfontlib_list);
+
+ /* Set up table */
+ ami_nsfont = &ami_font_bullet_table;
+}
+
+void ami_font_bullet_fini(void)
+{
+ ami_font_cache_fini();
+ ami_font_finiscanner();
+}
+
+/* Font scanner */
+void ami_font_initscanner(bool force, bool save)
+{
+ ami_font_scan_init(nsoption_charp(font_unicode_file), force, save, glypharray);
+}
+
+void ami_font_finiscanner(void)
+{
+ ami_font_scan_fini(glypharray);
+}
+
+void ami_font_savescanner(void)
+{
+ ami_font_scan_save(nsoption_charp(font_unicode_file), glypharray);
+}
+
diff --git a/frontends/amiga/font_bullet.h b/frontends/amiga/font_bullet.h
new file mode 100644
index 000000000..1ab9582db
--- /dev/null
+++ b/frontends/amiga/font_bullet.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016 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/>.
+ */
+
+#ifndef AMIGA_FONT_BULLET_H
+#define AMIGA_FONT_BULLET_H
+struct ami_font_cache_node;
+
+void ami_font_bullet_init(void);
+void ami_font_bullet_fini(void);
+void ami_font_bullet_close(void *nso);
+
+/* Alternate entry points into font_scan */
+void ami_font_initscanner(bool force, bool save);
+void ami_font_finiscanner(void);
+void ami_font_savescanner(void);
+#endif
+
diff --git a/frontends/amiga/font_cache.c b/frontends/amiga/font_cache.c
new file mode 100644
index 000000000..ea285730a
--- /dev/null
+++ b/frontends/amiga/font_cache.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2015 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 <string.h>
+
+#include <proto/timer.h>
+#include <proto/utility.h>
+
+#include "utils/log.h"
+
+#include "amiga/font.h"
+#include "amiga/font_bullet.h"
+#include "amiga/font_cache.h"
+#include "amiga/schedule.h"
+
+#ifdef __amigaos4__
+#include "amiga/hash/xxhash.h"
+#else
+#include "amiga/object.h"
+#endif
+
+#ifdef __amigaos4__
+static struct SkipList *ami_font_cache_list = NULL;
+static struct Hook ami_font_cache_hook;
+#else
+static struct MinList *ami_font_cache_list = NULL;
+#endif
+
+
+
+#ifdef __amigaos4__
+static LONG ami_font_cache_sort(struct Hook *hook, APTR key1, APTR key2)
+{
+ if(key1 == key2) return 0;
+ if(key1 < key2) return -1;
+ return 1;
+}
+#endif
+
+#ifdef __amigaos4__
+static void ami_font_cache_cleanup(struct SkipList *skiplist)
+{
+ struct ami_font_cache_node *node;
+ struct ami_font_cache_node *nnode;
+ struct TimeVal curtime;
+
+ node = (struct ami_font_cache_node *)GetFirstSkipNode(skiplist);
+ if(node == NULL) return;
+
+ do {
+ nnode = (struct ami_font_cache_node *)GetNextSkipNode(skiplist, (struct SkipNode *)node);
+ GetSysTime(&curtime);
+ SubTime(&curtime, &node->lastused);
+ if(curtime.Seconds > 300)
+ {
+ LOG("Freeing font %p not used for %ld seconds", node->skip_node.sn_Key, curtime.Seconds);
+ ami_font_bullet_close(node);
+ RemoveSkipNode(skiplist, node->skip_node.sn_Key);
+ }
+ } while((node = nnode));
+
+ /* reschedule to run in five minutes */
+ ami_schedule(300000, (void *)ami_font_cache_cleanup, ami_font_cache_list);
+}
+#else
+static void ami_font_cache_cleanup(struct MinList *ami_font_cache_list)
+{
+ struct nsObject *node;
+ struct nsObject *nnode;
+ struct ami_font_cache_node *fnode;
+ struct TimeVal curtime;
+
+ if(IsMinListEmpty(ami_font_cache_list)) return;
+
+ node = (struct nsObject *)GetHead((struct List *)ami_font_cache_list);
+
+ do
+ {
+ nnode=(struct nsObject *)GetSucc((struct Node *)node);
+ fnode = node->objstruct;
+ GetSysTime(&curtime);
+ SubTime(&curtime, &fnode->lastused);
+ if(curtime.Seconds > 300)
+ {
+ LOG("Freeing %s not used for %ld seconds", node->dtz_Node.ln_Name, curtime.Seconds);
+ DelObject(node);
+ }
+ } while((node=nnode));
+
+ /* reschedule to run in five minutes */
+ ami_schedule(300000, (void *)ami_font_cache_cleanup, ami_font_cache_list);
+}
+#endif
+
+#ifdef __amigaos4__
+static void ami_font_cache_del_skiplist(struct SkipList *skiplist)
+{
+ struct SkipNode *node;
+ struct SkipNode *nnode;
+
+ node = GetFirstSkipNode(skiplist);
+ if(node == NULL) return;
+
+ do {
+ nnode = GetNextSkipNode(skiplist, node);
+ ami_font_bullet_close((struct ami_font_cache_node *)node);
+
+ } while((node = nnode));
+
+ DeleteSkipList(skiplist);
+}
+#endif
+
+
+struct ami_font_cache_node *ami_font_cache_locate(const char *font)
+{
+ struct ami_font_cache_node *nodedata;
+ uint32 hash = 0;
+
+#ifdef __amigaos4__
+ hash = XXH32(font, strlen(font), 0);
+ nodedata = (struct ami_font_cache_node *)FindSkipNode(ami_font_cache_list, (APTR)hash);
+#else
+ struct nsObject *node = (struct nsObject *)FindIName((struct List *)ami_font_cache_list, font);
+ if(node) nodedata = node->objstruct;
+#endif
+
+ if(nodedata) {
+ GetSysTime(&nodedata->lastused);
+ return nodedata;
+ }
+
+ LOG("Font cache miss: %s (%lx)", font, hash);
+ return NULL;
+}
+
+struct ami_font_cache_node *ami_font_cache_alloc_entry(const char *font)
+{
+ struct ami_font_cache_node *nodedata;
+
+#ifdef __amigaos4__
+ uint32 hash = XXH32(font, strlen(font), 0);
+ nodedata = (struct ami_font_cache_node *)InsertSkipNode(ami_font_cache_list, (APTR)hash, sizeof(struct ami_font_cache_node));
+#else
+ nodedata = AllocVecTagList(sizeof(struct ami_font_cache_node), NULL);
+#endif
+
+ GetSysTime(&nodedata->lastused);
+
+ return nodedata;
+}
+
+void ami_font_cache_insert(struct ami_font_cache_node *nodedata, const char *font)
+{
+#ifndef __amigaos4__
+ struct nsObject *node = AddObject(ami_font_cache_list, AMINS_FONT);
+ if(node) {
+ ObjectCallback(node, ami_font_bullet_close);
+ node->objstruct = nodedata;
+ node->dtz_Node.ln_Name = strdup(font);
+ }
+#endif
+}
+
+void ami_font_cache_fini(void)
+{
+ LOG("Cleaning up font cache");
+ ami_schedule(-1, (void *)ami_font_cache_cleanup, ami_font_cache_list);
+#ifdef __amigaos4__
+ ami_font_cache_del_skiplist(ami_font_cache_list);
+#else
+ FreeObjList(ami_font_cache_list);
+#endif
+ ami_font_cache_list = NULL;
+}
+
+void ami_font_cache_init(void)
+{
+#ifdef __amigaos4__
+ ami_font_cache_hook.h_Entry = (HOOKFUNC)ami_font_cache_sort;
+ ami_font_cache_hook.h_Data = 0;
+ ami_font_cache_list = CreateSkipList(&ami_font_cache_hook, 8);
+#else
+ ami_font_cache_list = NewObjList();
+#endif
+
+ /* run first cleanup in ten minutes */
+ ami_schedule(600000, (void *)ami_font_cache_cleanup, ami_font_cache_list);
+}
+
diff --git a/frontends/amiga/font_cache.h b/frontends/amiga/font_cache.h
new file mode 100644
index 000000000..7c95ba594
--- /dev/null
+++ b/frontends/amiga/font_cache.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2015 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/>.
+ */
+
+#ifndef AMIGA_FONT_CACHE_H
+#define AMIGA_FONT_CACHE_H
+
+#include <proto/timer.h>
+
+struct ami_font_cache_node
+{
+#ifdef __amigaos4__
+ struct SkipNode skip_node;
+#endif
+ struct OutlineFont *font;
+ char *bold;
+ char *italic;
+ char *bolditalic;
+ struct TimeVal lastused;
+};
+
+
+/* locate an entry in the font cache, NULL if not found */
+struct ami_font_cache_node *ami_font_cache_locate(const char *font);
+
+/* allocate a cache entry */
+struct ami_font_cache_node *ami_font_cache_alloc_entry(const char *font);
+
+/* insert a cache entry into the list (OS3) */
+void ami_font_cache_insert(struct ami_font_cache_node *nodedata, const char *font);
+
+/* initialise the cache */
+void ami_font_cache_init(void);
+
+/* cache clean-up */
+void ami_font_cache_fini(void);
+
+#endif
+
+
diff --git a/frontends/amiga/font_diskfont.c b/frontends/amiga/font_diskfont.c
new file mode 100644
index 000000000..a64674ba2
--- /dev/null
+++ b/frontends/amiga/font_diskfont.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2008 - 2016 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 <stdlib.h>
+#include <string.h>
+#include <proto/diskfont.h>
+#include <proto/exec.h>
+#include <proto/graphics.h>
+#include <proto/utility.h>
+
+#include <graphics/rpattr.h>
+
+#include "utils/log.h"
+#include "utils/utf8.h"
+#include "utils/nsoption.h"
+
+#include "amiga/font.h"
+#include "amiga/font_diskfont.h"
+#include "amiga/gui.h"
+#include "amiga/utf8.h"
+
+#define MAX_FONT_NAME_SIZE 33
+
+static struct TextFont *ami_font_bm_open(struct RastPort *rp, const plot_font_style_t *fstyle)
+{
+ struct TextFont *bmfont = NULL;
+ struct TextAttr tattr;
+ char *fontname;
+ char font[MAX_FONT_NAME_SIZE];
+
+ if(rp == NULL) return NULL;
+
+ tattr.ta_Flags = 0;
+
+ switch(fstyle->family)
+ {
+ case PLOT_FONT_FAMILY_SANS_SERIF:
+ fontname = nsoption_charp(font_sans);
+ break;
+ case PLOT_FONT_FAMILY_SERIF:
+ fontname = nsoption_charp(font_serif);
+ break;
+ case PLOT_FONT_FAMILY_MONOSPACE:
+ fontname = nsoption_charp(font_mono);
+ break;
+ case PLOT_FONT_FAMILY_CURSIVE:
+ fontname = nsoption_charp(font_cursive);
+ break;
+ case PLOT_FONT_FAMILY_FANTASY:
+ fontname = nsoption_charp(font_fantasy);
+ break;
+ default:
+ return NULL;
+ break;
+ }
+
+ tattr.ta_Style = FS_NORMAL;
+
+ if (fstyle->flags & FONTF_OBLIQUE)
+ tattr.ta_Style = FSF_ITALIC;
+
+ if (fstyle->flags & FONTF_ITALIC)
+ tattr.ta_Style = FSF_ITALIC;
+
+ if (fstyle->weight >= 700)
+ tattr.ta_Style |= FSF_BOLD;
+
+ snprintf(font, MAX_FONT_NAME_SIZE, "%s.font", fontname);
+ tattr.ta_Name = font;
+ tattr.ta_YSize = fstyle->size / FONT_SIZE_SCALE;
+ LOG("font: %s/%d", tattr.ta_Name, tattr.ta_YSize);
+ if((bmfont = OpenDiskFont(&tattr))) {
+ SetRPAttrs(rp, RPTAG_Font, bmfont, TAG_DONE);
+ }
+
+ return bmfont;
+}
+
+static void ami_font_bm_close(struct TextFont *bmfont)
+{
+ CloseFont(bmfont);
+}
+
+static size_t ami_font_bm_convert_local_to_utf8_offset(const char *utf8string, size_t length, UWORD offset)
+{
+ size_t chr = 0;
+
+ for(UWORD i = 0; i < offset; i++) {
+ chr = utf8_next(utf8string, length, chr);
+ if(chr > length) return length;
+ }
+
+ return chr;
+}
+
+
+static nserror amiga_bm_nsfont_width(const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int *width)
+{
+ char *localtext = NULL;
+
+ if((glob == NULL) || (glob->rp == NULL)) return NSERROR_INVALID;
+ *width = length;
+
+ struct TextFont *bmfont = ami_font_bm_open(glob->rp, fstyle);
+ if(bmfont == NULL) return NSERROR_INVALID;
+
+ if(utf8_to_local_encoding(string, length, &localtext) != NSERROR_OK) {
+ ami_font_bm_close(bmfont);
+ return NSERROR_INVALID;
+ }
+
+ *width = TextLength(glob->rp, localtext, (UWORD)strlen(localtext));
+ free(localtext);
+
+ ami_font_bm_close(bmfont);
+
+ return NSERROR_OK;
+}
+
+/**
+ * Find the position in a string where an x coordinate falls.
+ *
+ * \param fstyle style for this text
+ * \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
+ * \return true on success, false on error and error reported
+ */
+
+static nserror amiga_bm_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)
+{
+ struct TextExtent extent;
+ struct TextFont *bmfont;
+ char *localtext = NULL;
+ UWORD co = 0;
+
+ if((glob == NULL) || (glob->rp == NULL)) return NSERROR_INVALID;
+
+ bmfont = ami_font_bm_open(glob->rp, fstyle);
+ if(bmfont == NULL) return NSERROR_INVALID;
+
+ if(utf8_to_local_encoding(string, length, &localtext) != NSERROR_OK) {
+ ami_font_bm_close(bmfont);
+ return NSERROR_INVALID;
+ }
+
+ co = TextFit(glob->rp, localtext, (UWORD)strlen(localtext),
+ &extent, NULL, 1, x, 32767);
+ *char_offset = ami_font_bm_convert_local_to_utf8_offset(string, length, co);
+ *actual_x = extent.te_Extent.MaxX;
+
+ free(localtext);
+ ami_font_bm_close(bmfont);
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Find where to split a string to make it fit a width.
+ *
+ * \param fstyle style for this text
+ * \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, [1..length]
+ * \param actual_x updated to x coordinate of character closest to x
+ * \return true on success, false on error and error reported
+ *
+ * On exit, char_offset indicates first character after split point.
+ *
+ * Note: char_offset of 0 should never be returned.
+ *
+ * Returns:
+ * char_offset giving split point closest to x, where actual_x <= x
+ * else
+ * char_offset giving split point closest to x, where actual_x > x
+ *
+ * Returning char_offset == length means no split possible
+ */
+
+static nserror amiga_bm_nsfont_split(const plot_font_style_t *fstyle,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x)
+{
+ struct TextExtent extent;
+ UWORD co, offset;
+ char *charp;
+ char *localtext;
+
+ if((glob == NULL) || (glob->rp == NULL)) return NSERROR_INVALID;
+
+ struct TextFont *bmfont = ami_font_bm_open(glob->rp, fstyle);
+ if(bmfont == NULL) return NSERROR_INVALID;
+
+ if(utf8_to_local_encoding(string, length, &localtext) != NSERROR_OK) {
+ ami_font_bm_close(bmfont);
+ return NSERROR_INVALID;
+ }
+
+ offset = TextFit(glob->rp, localtext, (UWORD)strlen(localtext),
+ &extent, NULL, 1, (UWORD)x, 32767);
+
+ co = offset;
+ charp = localtext + co;
+
+
+ while((*charp != ' ') && (co > 0)) {
+ charp--;
+ co--;
+ }
+
+ if(co == 0) {
+ co = offset;
+ charp = localtext + co;
+ while((*charp != ' ') && (co < strlen(localtext))) {
+ charp++;
+ co++;
+ }
+ }
+
+ if((co > 0) && (co < strlen(localtext))) {
+ *actual_x = TextLength(glob->rp, localtext, co);
+ *char_offset = ami_font_bm_convert_local_to_utf8_offset(string, length, co);
+ } else {
+ *actual_x = x;
+ *char_offset = length;
+ }
+
+ free(localtext);
+ ami_font_bm_close(bmfont);
+
+ return NSERROR_OK;
+}
+
+static ULONG amiga_bm_nsfont_text(struct RastPort *rp, const char *string, ULONG length,
+ const plot_font_style_t *fstyle, ULONG dx, ULONG dy, bool aa)
+{
+ if(!string || string[0]=='\0') return 0;
+ if(!length) return 0;
+ if(rp == NULL) return 0;
+
+ struct TextFont *bmfont = ami_font_bm_open(rp, fstyle);
+ char *localtext = NULL;
+ if(bmfont == NULL) return 0;
+ if(utf8_to_local_encoding(string, length, &localtext) == NSERROR_OK) {
+ Move(rp, dx, dy);
+ Text(rp, localtext, (UWORD)strlen(localtext));
+ free(localtext);
+ }
+
+ ami_font_bm_close(bmfont);
+
+ return 0;
+}
+
+const struct ami_font_functions ami_font_diskfont_table = {
+ amiga_bm_nsfont_width,
+ amiga_bm_nsfont_position_in_string,
+ amiga_bm_nsfont_split,
+ amiga_bm_nsfont_text
+};
+
+void ami_font_diskfont_init(void)
+{
+ /* Set up table */
+ ami_nsfont = &ami_font_diskfont_table;
+}
+
diff --git a/frontends/amiga/font_diskfont.h b/frontends/amiga/font_diskfont.h
new file mode 100644
index 000000000..de19e940e
--- /dev/null
+++ b/frontends/amiga/font_diskfont.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2016 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/>.
+ */
+
+#ifndef AMIGA_FONT_DISKFONT_H
+#define AMIGA_FONT_DISKFONT_H
+void ami_font_diskfont_init(void);
+#endif
+
diff --git a/frontends/amiga/font_scan.c b/frontends/amiga/font_scan.c
new file mode 100644
index 000000000..b65798d6e
--- /dev/null
+++ b/frontends/amiga/font_scan.c
@@ -0,0 +1,522 @@
+/*
+ * Copyright 2012 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
+ * Font glyph scanner for Unicode substitutions.
+*/
+
+#include "amiga/os3support.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef __amigaos4__
+#include <proto/bullet.h>
+#endif
+#include <proto/diskfont.h>
+#include <proto/dos.h>
+#include <proto/exec.h>
+#include <proto/intuition.h>
+#include <diskfont/diskfonttag.h>
+#include <diskfont/oterrors.h>
+
+#include <proto/window.h>
+#include <proto/layout.h>
+#include <proto/fuelgauge.h>
+#include <classes/window.h>
+#include <gadgets/fuelgauge.h>
+#include <gadgets/layout.h>
+
+#include <reaction/reaction_macros.h>
+
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "desktop/mouse.h"
+#include "desktop/gui_window.h"
+
+#include "amiga/font_scan.h"
+#include "amiga/gui.h"
+#include "amiga/libs.h"
+#include "amiga/object.h"
+#include "amiga/utf8.h"
+
+enum {
+ FS_OID_MAIN = 0,
+ FS_GID_MAIN,
+ FS_GID_FONTS,
+ FS_GID_GLYPHS,
+ FS_GID_LAST
+};
+
+struct ami_font_scan_window {
+ struct Window *win;
+ Object *objects[FS_GID_LAST];
+ char *title;
+ char *glyphtext;
+};
+
+/**
+ * Lookup a font that contains a UTF-16 codepoint
+ *
+ * \param code UTF-16 codepoint to lookup
+ * \param glypharray an array of 0xffff lwc_string pointers
+ * \return font name or NULL
+ */
+const char *ami_font_scan_lookup(const uint16 *code, lwc_string **glypharray)
+{
+ if(*code >= 0xd800 && *code <= 0xdbff) {
+ /* This is a multi-byte character, we don't support fallback for these yet. */
+ return NULL;
+ }
+
+ if(glypharray[*code] == NULL) return NULL;
+ else return lwc_string_data(glypharray[*code]);
+}
+
+/**
+ * Open GUI to show font scanning progress
+ *
+ * \param fonts number of fonts that are being scanned
+ * \return pointer to a struct ami_font_scan_window
+ */
+static struct ami_font_scan_window *ami_font_scan_gui_open(int32 fonts)
+{
+ struct ami_font_scan_window *fsw =
+ AllocVecTagList(sizeof(struct ami_font_scan_window), NULL);
+
+ if(fsw == NULL) return NULL;
+
+ fsw->title = ami_utf8_easy(messages_get("FontScanning"));
+ fsw->glyphtext = ami_utf8_easy(messages_get("FontGlyphs"));
+
+ fsw->objects[FS_OID_MAIN] = WindowObj,
+ WA_ScreenTitle, ami_gui_get_screen_title(),
+ WA_Title, fsw->title,
+ WA_Activate, TRUE,
+ WA_DepthGadget, TRUE,
+ WA_DragBar, TRUE,
+ WA_CloseGadget, FALSE,
+ WA_SizeGadget, TRUE,
+ WA_PubScreen, scrn,
+ WA_BusyPointer, TRUE,
+ WA_Width, 400,
+ WINDOW_UserData, fsw,
+ WINDOW_IconifyGadget, FALSE,
+ WINDOW_Position, WPOS_CENTERSCREEN,
+ WINDOW_LockHeight, TRUE,
+ WINDOW_ParentGroup, fsw->objects[FS_GID_MAIN] = LayoutVObj,
+ LAYOUT_AddChild, fsw->objects[FS_GID_FONTS] = FuelGaugeObj,
+ GA_ID, FS_GID_FONTS,
+ GA_Text, fsw->title,
+ FUELGAUGE_Min, 0,
+ FUELGAUGE_Max, fonts,
+ FUELGAUGE_Level, 0,
+ FUELGAUGE_Ticks, 11,
+ FUELGAUGE_ShortTicks, TRUE,
+ FUELGAUGE_Percent, FALSE,
+ FUELGAUGE_Justification, FGJ_CENTER,
+ FuelGaugeEnd,
+ CHILD_NominalSize, TRUE,
+ CHILD_WeightedHeight, 0,
+ LAYOUT_AddChild, fsw->objects[FS_GID_GLYPHS] = FuelGaugeObj,
+ GA_ID, FS_GID_GLYPHS,
+ //GA_Text, "Glyphs",
+ FUELGAUGE_Min, 0x0000,
+ FUELGAUGE_Max, 0xffff,
+ FUELGAUGE_Level, 0,
+ FUELGAUGE_Ticks,11,
+ FUELGAUGE_ShortTicks, TRUE,
+ FUELGAUGE_Percent, FALSE,
+ FUELGAUGE_Justification, FGJ_CENTER,
+ FuelGaugeEnd,
+ CHILD_NominalSize, TRUE,
+ CHILD_WeightedHeight, 0,
+ EndGroup,
+ EndWindow;
+
+ fsw->win = (struct Window *)RA_OpenWindow(fsw->objects[FS_OID_MAIN]);
+
+ return fsw;
+}
+
+/**
+ * Update GUI showing font scanning progress
+ *
+ * \param fsw pointer to a struct ami_font_scan_window
+ * \param font current font being scanned
+ * \param font_num font number being scanned
+ * \param glyphs number of unique glyphs found
+ */
+static void ami_font_scan_gui_update(struct ami_font_scan_window *fsw, const char *font,
+ ULONG font_num, ULONG glyphs)
+{
+ ULONG va[2];
+
+ if(fsw) {
+ RefreshSetGadgetAttrs((struct Gadget *)fsw->objects[FS_GID_FONTS],
+ fsw->win, NULL,
+ FUELGAUGE_Level, font_num,
+ GA_Text, font,
+ TAG_DONE);
+
+ va[0] = glyphs;
+ va[1] = 0;
+
+ RefreshSetGadgetAttrs((struct Gadget *)fsw->objects[FS_GID_GLYPHS],
+ fsw->win, NULL,
+ GA_Text, fsw->glyphtext,
+ FUELGAUGE_VarArgs, va,
+ FUELGAUGE_Level, glyphs,
+ TAG_DONE);
+ } else {
+ printf("Found %ld glyphs\n", glyphs);
+ printf("Scanning font #%ld (%s)...\n", font_num, font);
+ }
+}
+
+/**
+ * Close GUI showing font scanning progress
+ *
+ * \param fsw pointer to a struct ami_font_scan_window
+ */
+static void ami_font_scan_gui_close(struct ami_font_scan_window *fsw)
+{
+ if(fsw) {
+ DisposeObject(fsw->objects[FS_OID_MAIN]);
+ ami_utf8_free(fsw->title);
+ FreeVec(fsw);
+ }
+}
+
+/**
+ * Scan a font for glyphs not present in glypharray.
+ *
+ * \param fontname font to scan
+ * \param glypharray an array of 0xffff lwc_string pointers
+ * \return number of new glyphs found
+ */
+static ULONG ami_font_scan_font(const char *fontname, lwc_string **glypharray)
+{
+ struct OutlineFont *ofont;
+ struct MinList *widthlist = NULL;
+ struct GlyphWidthEntry *gwnode;
+ ULONG foundglyphs = 0;
+ lwc_error lerror;
+ ULONG unicoderanges = 0;
+
+ ofont = OpenOutlineFont(fontname, NULL, OFF_OPEN);
+
+ if(!ofont) return 0;
+
+#ifndef __amigaos4__
+ struct BulletBase *BulletBase = ofont->BulletBase;
+#endif
+
+ if(ESetInfo(AMI_OFONT_ENGINE,
+ OT_PointHeight, 10 * (1 << 16),
+ OT_GlyphCode, 0x0000,
+ OT_GlyphCode2, 0xffff,
+ TAG_END) == OTERR_Success)
+ {
+ if(EObtainInfo(AMI_OFONT_ENGINE,
+ OT_WidthList, &widthlist,
+ TAG_END) == 0)
+ {
+ gwnode = (struct GlyphWidthEntry *)GetHead((struct List *)widthlist);
+ do {
+ if(gwnode && (glypharray[gwnode->gwe_Code] == NULL)) {
+ lerror = lwc_intern_string(fontname, strlen(fontname), &glypharray[gwnode->gwe_Code]);
+ if(lerror != lwc_error_ok) continue;
+ foundglyphs++;
+ }
+ } while((gwnode = (struct GlyphWidthEntry *)GetSucc((struct Node *)gwnode)));
+ EReleaseInfo(AMI_OFONT_ENGINE,
+ OT_WidthList, widthlist,
+ TAG_END);
+ }
+ }
+#ifdef __amigaos4__
+ if(EObtainInfo(AMI_OFONT_ENGINE, OT_UnicodeRanges, &unicoderanges, TAG_END) == 0) {
+ if(unicoderanges & UCR_SURROGATES) {
+ LOG("%s supports UTF-16 surrogates", fontname);
+ if (nsoption_charp(font_surrogate) == NULL) {
+ nsoption_set_charp(font_surrogate, (char *)strdup(fontname));
+ }
+ }
+ EReleaseInfo(AMI_OFONT_ENGINE,
+ OT_UnicodeRanges, unicoderanges,
+ TAG_END);
+ }
+#endif
+ CloseOutlineFont(ofont, NULL);
+
+ return foundglyphs;
+}
+
+/**
+ * Scan all fonts for glyphs.
+ *
+ * \param list min list
+ * \param win scan window
+ * \param glypharray an array of 0xffff lwc_string pointers
+ * \return number of glyphs found
+ */
+static ULONG ami_font_scan_fonts(struct MinList *list,
+ struct ami_font_scan_window *win, lwc_string **glypharray)
+{
+ ULONG found, total = 0, font_num = 0;
+ struct nsObject *node;
+ struct nsObject *nnode;
+
+ if(IsMinListEmpty(list)) return 0;
+
+ node = (struct nsObject *)GetHead((struct List *)list);
+
+ do {
+ nnode = (struct nsObject *)GetSucc((struct Node *)node);
+ ami_font_scan_gui_update(win, node->dtz_Node.ln_Name, font_num, total);
+ LOG("Scanning %s", node->dtz_Node.ln_Name);
+ found = ami_font_scan_font(node->dtz_Node.ln_Name, glypharray);
+ total += found;
+ LOG("Found %ld new glyphs (total = %ld)", found, total);
+ font_num++;
+ } while((node = nnode));
+
+ return total;
+}
+
+/**
+ * Add OS fonts to a list.
+ *
+ * \param list list to add font names to
+ * \return number of fonts found
+ */
+static ULONG ami_font_scan_list(struct MinList *list)
+{
+ int afShortage, afSize = 100;
+ struct AvailFontsHeader *afh;
+ struct AvailFonts *af;
+ ULONG found = 0;
+ struct nsObject *node;
+
+ do {
+ if((afh = (struct AvailFontsHeader *)AllocVecTagList(afSize, NULL))) {
+ if(((afShortage = AvailFonts((STRPTR)afh, afSize,
+ AFF_DISK | AFF_OTAG | AFF_SCALED)))) {
+ FreeVec(afh);
+ afSize += afShortage;
+ }
+ } else {
+ /* out of memory, bail out */
+ return 0;
+ }
+ } while (afShortage);
+
+ if(afh) {
+ af = (struct AvailFonts *)&(afh[1]);
+
+ for(int i = 0; i < afh->afh_NumEntries; i++) {
+ if(af[i].af_Attr.ta_Style == FS_NORMAL) {
+ if(af[i].af_Attr.ta_Name != NULL) {
+ char *p = 0;
+ if((p = strrchr(af[i].af_Attr.ta_Name, '.'))) *p = '\0';
+ node = (struct nsObject *)FindIName((struct List *)list,
+ af[i].af_Attr.ta_Name);
+ if(node == NULL) {
+ node = AddObject(list, AMINS_UNKNOWN);
+ if(node) {
+ node->dtz_Node.ln_Name = strdup(af[i].af_Attr.ta_Name);
+ found++;
+ LOG("Added %s", af[i].af_Attr.ta_Name);
+ }
+ }
+ }
+ }
+ }
+ FreeVec(afh);
+ } else {
+ return 0;
+ }
+ return found;
+}
+
+/**
+ * Load a font glyph cache
+ *
+ * \param filename name of cache file to load
+ * \param glypharray an array of 0xffff lwc_string pointers
+ * \return number of glyphs loaded
+ */
+static ULONG ami_font_scan_load(const char *filename, lwc_string **glypharray)
+{
+ ULONG found = 0;
+ BPTR fh = 0;
+ lwc_error lerror;
+ char buffer[256];
+ struct RDArgs *rargs = NULL;
+ CONST_STRPTR template = "CODE/A,FONT/A";
+ long rarray[] = {0,0};
+
+ enum {
+ A_CODE = 0,
+ A_FONT
+ };
+
+ rargs = AllocDosObjectTags(DOS_RDARGS, TAG_DONE);
+
+ if((fh = FOpen(filename, MODE_OLDFILE, 0))) {
+ LOG("Loading font glyph cache from %s", filename);
+
+ while(FGets(fh, (STRPTR)&buffer, 256) != 0)
+ {
+ rargs->RDA_Source.CS_Buffer = (char *)&buffer;
+ rargs->RDA_Source.CS_Length = 256;
+ rargs->RDA_Source.CS_CurChr = 0;
+
+ rargs->RDA_DAList = NULL;
+ rargs->RDA_Buffer = NULL;
+ rargs->RDA_BufSiz = 0;
+ rargs->RDA_ExtHelp = NULL;
+ rargs->RDA_Flags = 0;
+
+ if(ReadArgs(template, rarray, rargs))
+ {
+ lerror = lwc_intern_string((const char *)rarray[A_FONT],
+ strlen((const char *)rarray[A_FONT]),
+ &glypharray[strtoul((const char *)rarray[A_CODE], NULL, 0)]);
+ if(lerror != lwc_error_ok) continue;
+ found++;
+ }
+ }
+ FClose(fh);
+ }
+
+ return found;
+}
+
+/**
+ * Save a font glyph cache
+ *
+ * \param filename name of cache file to save
+ * \param glypharray an array of 0xffff lwc_string pointers
+ */
+void ami_font_scan_save(const char *filename, lwc_string **glypharray)
+{
+ ULONG i;
+ BPTR fh = 0;
+
+ if((fh = FOpen(filename, MODE_NEWFILE, 0))) {
+ LOG("Writing font glyph cache to %s", filename);
+ FPrintf(fh, "; This file is auto-generated. To re-create the cache, delete this file.\n");
+ FPrintf(fh, "; This file is parsed using ReadArgs() with the following template:\n");
+ FPrintf(fh, "; CODE/A,FONT/A\n;\n");
+
+ for(i=0x0000; i<=0xffff; i++)
+ {
+ if(glypharray[i]) {
+ FPrintf(fh, "0x%04lx \"%s\"\n", i, lwc_string_data(glypharray[i]));
+ }
+ }
+ FClose(fh);
+ }
+}
+
+/**
+ * Finalise the font glyph cache.
+ *
+ * \param glypharray an array of 0xffff lwc_string pointers to free
+ */
+void ami_font_scan_fini(lwc_string **glypharray)
+{
+ ULONG i;
+
+ for(i=0x0000; i<=0xffff; i++)
+ {
+ if(glypharray[i]) {
+ lwc_string_unref(glypharray[i]);
+ glypharray[i] = NULL;
+ }
+ }
+}
+
+/**
+ * Initialise the font glyph cache.
+ * Reads an existing file or, if not present, generates a new cache.
+ *
+ * \param filename cache file to attempt to read
+ * \param force_scan force re-creation of cache
+ * \param save save the cache
+ * \param glypharray an array of 0xffff lwc_string pointers
+ */
+void ami_font_scan_init(const char *filename, bool force_scan, bool save,
+ lwc_string **glypharray)
+{
+ ULONG i, found = 0, entries = 0;
+ struct MinList *list;
+ struct nsObject *node;
+ char *csv;
+ struct ami_font_scan_window *win = NULL;
+
+ /* Ensure array zeroed */
+ for(i=0x0000; i<=0xffff; i++)
+ glypharray[i] = NULL;
+
+ if(force_scan == false)
+ found = ami_font_scan_load(filename, glypharray);
+
+ if(found == 0) {
+ LOG("Creating new font glyph cache");
+ if((list = NewObjList())) {
+
+ /* add preferred fonts list */
+ if(nsoption_charp(font_unicode) &&
+ (csv = strdup(nsoption_charp(font_unicode))))
+ {
+ char *p;
+
+ while((p = strsep(&csv, ","))) {
+ if(p != NULL) {
+ node = AddObject(list, AMINS_UNKNOWN);
+ if(node) node->dtz_Node.ln_Name = strdup(p);
+ entries++;
+ }
+ }
+ free(csv);
+ }
+
+ if(nsoption_bool(font_unicode_only) == false)
+ entries += ami_font_scan_list(list);
+
+ LOG("Found %ld fonts", entries);
+
+ win = ami_font_scan_gui_open(entries);
+ found = ami_font_scan_fonts(list, win, glypharray);
+ ami_font_scan_gui_close(win);
+
+ FreeObjList(list);
+
+ if(save == true)
+ ami_font_scan_save(filename, glypharray);
+ }
+ }
+
+ LOG("Initialised with %ld glyphs", found);
+}
+
diff --git a/frontends/amiga/font_scan.h b/frontends/amiga/font_scan.h
new file mode 100755
index 000000000..7d61e2daa
--- /dev/null
+++ b/frontends/amiga/font_scan.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012 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/>.
+ */
+
+#ifndef AMIGA_FONT_SCAN_H
+#define AMIGA_FONT_SCAN_H
+#include "amiga/os3support.h"
+#include <libwapcaplet/libwapcaplet.h>
+
+/* Compatibliity define used by font.c and font_scan.c
+ * It's here because this file is included by both. */
+#ifdef __amigaos4__
+#define AMI_OFONT_ENGINE &ofont->olf_EEngine
+#else
+#define AMI_OFONT_ENGINE ofont->GEngine
+#endif
+
+void ami_font_scan_init(const char *filename, bool force_scan, bool save,
+ lwc_string **glypharray);
+void ami_font_scan_fini(lwc_string **glypharray);
+void ami_font_scan_save(const char *filename, lwc_string **glypharray);
+const char *ami_font_scan_lookup(const uint16 *code, lwc_string **glypharray);
+
+#endif
+
diff --git a/frontends/amiga/gui.c b/frontends/amiga/gui.c
new file mode 100644
index 000000000..c6c963312
--- /dev/null
+++ b/frontends/amiga/gui.c
@@ -0,0 +1,5740 @@
+/*
+ * Copyright 2008-2015 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/>.
+ */
+
+
+
+/* Custom StringView class */
+#include "amiga/stringview/stringview.h"
+#include "amiga/stringview/urlhistory.h"
+
+/* AmigaOS libraries */
+#ifdef __amigaos4__
+#include <proto/application.h>
+#endif
+#include <proto/asl.h>
+#include <proto/datatypes.h>
+#include <proto/dos.h>
+#include <proto/exec.h>
+#include <proto/graphics.h>
+#include <proto/icon.h>
+#include <proto/intuition.h>
+#include <proto/keymap.h>
+#include <proto/locale.h>
+#include <proto/utility.h>
+#include <proto/wb.h>
+
+/* Other OS includes */
+#include <datatypes/textclass.h>
+#include <devices/inputevent.h>
+#include <graphics/gfxbase.h>
+#include <graphics/rpattr.h>
+#ifdef __amigaos4__
+#include <graphics/blitattr.h>
+#include <intuition/gui.h>
+#include <libraries/application.h>
+#include <libraries/keymap.h>
+#endif
+#include <intuition/icclass.h>
+#include <intuition/screens.h>
+#include <libraries/gadtools.h>
+#include <workbench/workbench.h>
+
+/* ReAction libraries */
+#include <proto/bevel.h>
+#include <proto/bitmap.h>
+#include <proto/button.h>
+#include <proto/chooser.h>
+#include <proto/clicktab.h>
+#include <proto/label.h>
+#include <proto/layout.h>
+#include <proto/scroller.h>
+#include <proto/space.h>
+#include <proto/speedbar.h>
+#include <proto/string.h>
+#include <proto/window.h>
+
+#include <classes/window.h>
+#include <gadgets/button.h>
+#include <gadgets/chooser.h>
+#include <gadgets/clicktab.h>
+#include <gadgets/layout.h>
+#include <gadgets/scroller.h>
+#include <gadgets/space.h>
+#include <gadgets/speedbar.h>
+#include <gadgets/string.h>
+#include <images/bevel.h>
+#include <images/bitmap.h>
+#include <images/label.h>
+
+#include <reaction/reaction_macros.h>
+
+/* newlib includes */
+#include <math.h>
+#include <string.h>
+
+/* NetSurf core includes */
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/nsoption.h"
+#include "utils/utf8.h"
+#include "utils/utils.h"
+#include "utils/nsurl.h"
+#include "utils/file.h"
+#include "content/hlcache.h"
+#include "content/backing_store.h"
+#include "content/fetchers.h"
+#include "content/fetchers/resource.h"
+#include "content/urldb.h"
+#include "image/ico.h"
+#include "desktop/browser_history.h"
+#include "desktop/browser.h"
+#include "desktop/hotlist.h"
+#include "desktop/mouse.h"
+#include "desktop/netsurf.h"
+#include "desktop/version.h"
+#include "desktop/save_complete.h"
+#include "desktop/scrollbar.h"
+#include "desktop/searchweb.h"
+#include "desktop/textinput.h"
+#include "desktop/tree.h"
+#include "desktop/gui_window.h"
+#include "desktop/gui_fetch.h"
+#include "desktop/gui_misc.h"
+
+/* NetSurf Amiga platform includes */
+#include "amiga/gui.h"
+#include "amiga/arexx.h"
+#include "amiga/bitmap.h"
+#include "amiga/clipboard.h"
+#include "amiga/cookies.h"
+#include "amiga/ctxmenu.h"
+#include "amiga/datatypes.h"
+#include "amiga/download.h"
+#include "amiga/drag.h"
+#include "amiga/file.h"
+#include "amiga/filetype.h"
+#include "amiga/font.h"
+#include "amiga/gui_options.h"
+#include "amiga/help.h"
+#include "amiga/history.h"
+#include "amiga/history_local.h"
+#include "amiga/hotlist.h"
+#include "amiga/icon.h"
+#include "amiga/launch.h"
+#include "amiga/libs.h"
+#include "amiga/login.h"
+#include "amiga/menu.h"
+#include "amiga/misc.h"
+#include "amiga/plotters.h"
+#include "amiga/plugin_hack.h"
+#include "amiga/print.h"
+#include "amiga/schedule.h"
+#include "amiga/search.h"
+#include "amiga/selectmenu.h"
+#include "amiga/theme.h"
+#include "amiga/tree.h"
+#include "amiga/utf8.h"
+#include "amiga/sslcert.h"
+
+#define AMINS_SCROLLERPEN NUMDRIPENS
+#define NSA_KBD_SCROLL_PX 10
+#define NSA_MAX_HOTLIST_BUTTON_LEN 20
+
+/* Extra mouse button defines to match those in intuition/intuition.h */
+#define SIDEDOWN (IECODE_4TH_BUTTON)
+#define SIDEUP (IECODE_4TH_BUTTON | IECODE_UP_PREFIX)
+#define EXTRADOWN (IECODE_5TH_BUTTON)
+#define EXTRAUP (IECODE_5TH_BUTTON | IECODE_UP_PREFIX)
+
+#ifdef __amigaos4__
+#define NSA_STATUS_TEXT GA_Text
+#else
+#define NSA_STATUS_TEXT STRINGA_TextVal
+#endif
+
+#ifdef __amigaos4__
+#define BOOL_MISMATCH(a,b) ((a == FALSE) && (b != FALSE)) || ((a != FALSE) && (b == FALSE))
+#else
+#define BOOL_MISMATCH(a,b) (1)
+#endif
+
+static bool ami_quit = false;
+
+extern struct gui_utf8_table *amiga_utf8_table;
+
+struct ami_gui_tb_userdata {
+ struct List *sblist;
+ struct gui_window_2 *gw;
+ int items;
+};
+
+static struct MsgPort *schedulermsgport = NULL;
+static struct MsgPort *appport;
+static Class *urlStringClass;
+
+static BOOL locked_screen = FALSE;
+static int screen_signal = -1;
+static bool win_destroyed;
+static STRPTR nsscreentitle;
+
+static struct MsgPort *applibport = NULL;
+static ULONG applibsig = 0;
+static uint32 ami_appid = 0;
+static struct Hook newprefs_hook;
+
+static STRPTR temp_homepage_url = NULL;
+static bool cli_force = false;
+
+#define USERS_DIR "PROGDIR:Users"
+static char *users_dir = NULL;
+static char *current_user = NULL;
+static char *current_user_dir;
+static char *current_user_faviconcache;
+
+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 *path, const char *file,
+ const char *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);
+
+static bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy);
+static void gui_window_set_scroll(struct gui_window *g, int sx, int sy);
+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);
+
+
+
+/* accessors for default options - user option is updated if it is set as per default */
+#define nsoption_default_set_int(OPTION, VALUE) \
+ if (nsoptions_default[NSOPTION_##OPTION].value.i == nsoptions[NSOPTION_##OPTION].value.i) \
+ nsoptions[NSOPTION_##OPTION].value.i = VALUE; \
+ nsoptions_default[NSOPTION_##OPTION].value.i = VALUE
+
+
+
+STRPTR ami_locale_langs(void)
+{
+ struct Locale *locale;
+ STRPTR acceptlangs = NULL;
+ char *remapped;
+
+ if((locale = OpenLocale(NULL)))
+ {
+ for(int i = 0; i < 10; i++)
+ {
+ if(locale->loc_PrefLanguages[i])
+ {
+ if(ami_gui_map_filename(&remapped, "PROGDIR:Resources",
+ locale->loc_PrefLanguages[i], "LangNames"))
+ {
+ if(acceptlangs)
+ {
+ STRPTR acceptlangs2 = acceptlangs;
+ acceptlangs = ASPrintf("%s, %s",acceptlangs2, remapped);
+ FreeVec(acceptlangs2);
+ acceptlangs2 = NULL;
+ }
+ else
+ {
+ acceptlangs = ASPrintf("%s", remapped);
+ }
+ }
+ }
+ else
+ {
+ continue;
+ }
+ }
+ CloseLocale(locale);
+ }
+ return acceptlangs;
+}
+
+bool ami_gui_map_filename(char **remapped, const char *path, const char *file, const char *map)
+{
+ BPTR fh = 0;
+ char *mapfile = NULL;
+ size_t mapfile_size = 0;
+ char buffer[1024];
+ char *realfname;
+ bool found = false;
+
+ netsurf_mkpath(&mapfile, &mapfile_size, 2, path, map);
+
+ if(mapfile == NULL) return false;
+
+ fh = FOpen(mapfile, MODE_OLDFILE, 0);
+ if(fh)
+ {
+ while(FGets(fh, buffer, 1024) != 0)
+ {
+ if((buffer[0] == '#') ||
+ (buffer[0] == '\n') ||
+ (buffer[0] == '\0')) continue;
+
+ realfname = strchr(buffer, ':');
+ if(realfname)
+ {
+ if(strncmp(buffer, file, strlen(file)) == 0)
+ {
+ if(realfname[strlen(realfname)-1] == '\n')
+ realfname[strlen(realfname)-1] = '\0';
+ *remapped = strdup(realfname + 1);
+ found = true;
+ break;
+ }
+ }
+ }
+ FClose(fh);
+ }
+
+ if(found == false) *remapped = strdup(file);
+ else LOG("Remapped %s to %s in path %s using %s", file, *remapped, path, map);
+
+ free(mapfile);
+
+ return found;
+}
+
+static bool ami_gui_check_resource(char *fullpath, const char *file)
+{
+ bool found = false;
+ char *remapped;
+ BPTR lock = 0;
+ size_t fullpath_len = 1024;
+
+ ami_gui_map_filename(&remapped, fullpath, file, "Resource.map");
+ netsurf_mkpath(&fullpath, &fullpath_len, 2, fullpath, remapped);
+
+ lock = Lock(fullpath, ACCESS_READ);
+ if(lock)
+ {
+ UnLock(lock);
+ found = true;
+ }
+
+ if(found) LOG("Found %s", fullpath);
+ free(remapped);
+
+ return found;
+}
+
+bool ami_locate_resource(char *fullpath, const char *file)
+{
+ struct Locale *locale;
+ int i;
+ bool found = false;
+ char *remapped;
+ size_t fullpath_len = 1024;
+
+ /* Check NetSurf user data area first */
+
+ if(current_user_dir != NULL) {
+ strcpy(fullpath, current_user_dir);
+ found = ami_gui_check_resource(fullpath, file);
+ if(found) return true;
+ }
+
+ /* Check current theme directory */
+ if(nsoption_charp(theme)) {
+ strcpy(fullpath, nsoption_charp(theme));
+ found = ami_gui_check_resource(fullpath, file);
+ if(found) return true;
+ }
+
+ /* If not found, start on the user's preferred languages */
+
+ locale = OpenLocale(NULL);
+
+ for(i=0;i<10;i++) {
+ strcpy(fullpath,"PROGDIR:Resources/");
+
+ if(locale->loc_PrefLanguages[i]) {
+ ami_gui_map_filename(&remapped, "PROGDIR:Resources",
+ locale->loc_PrefLanguages[i], "LangNames");
+ netsurf_mkpath(&fullpath, &fullpath_len, 2, fullpath, remapped);
+
+ found = ami_gui_check_resource(fullpath, file);
+ } else {
+ continue;
+ }
+
+ if(found) break;
+ }
+
+ if(!found) {
+ /* If not found yet, check in PROGDIR:Resources/en,
+ * might not be in user's preferred languages */
+
+ strcpy(fullpath, "PROGDIR:Resources/en/");
+ found = ami_gui_check_resource(fullpath, file);
+ }
+
+ CloseLocale(locale);
+
+ if(!found) {
+ /* Lastly check directly in PROGDIR:Resources */
+
+ strcpy(fullpath, "PROGDIR:Resources/");
+ found = ami_gui_check_resource(fullpath, file);
+ }
+
+ return found;
+}
+
+static bool ami_open_resources(void)
+{
+ urlStringClass = MakeStringClass();
+
+ if(!(appport = AllocSysObjectTags(ASOT_PORT,
+ ASO_NoTrack, FALSE,
+ TAG_DONE))) return false;
+
+ if(!(sport = AllocSysObjectTags(ASOT_PORT,
+ ASO_NoTrack, FALSE,
+ TAG_DONE))) return false;
+
+ if(!(schedulermsgport = AllocSysObjectTags(ASOT_PORT,
+ ASO_NoTrack, FALSE,
+ TAG_DONE))) return false;
+
+ return true;
+}
+
+static UWORD ami_system_colour_scrollbar_fgpen(struct DrawInfo *drinfo)
+{
+ LONG scrollerfillpen = FALSE;
+#ifdef __amigaos4__
+ GetGUIAttrs(NULL, drinfo, GUIA_PropKnobColor, &scrollerfillpen, TAG_DONE);
+
+ if(scrollerfillpen) return FILLPEN;
+ else return FOREGROUNDPEN;
+#else
+ return FILLPEN;
+#endif
+
+}
+
+/**
+ * set option from pen
+ */
+static nserror
+colour_option_from_pen(UWORD pen,
+ enum nsoption_e option,
+ struct Screen *screen,
+ colour def_colour)
+{
+ ULONG colr[3];
+ struct DrawInfo *drinfo;
+
+ if((option < NSOPTION_SYS_COLOUR_START) ||
+ (option > NSOPTION_SYS_COLOUR_END) ||
+ (nsoptions[option].type != OPTION_COLOUR)) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if(screen != NULL) {
+ drinfo = GetScreenDrawInfo(screen);
+ if(drinfo != NULL) {
+
+ if(pen == AMINS_SCROLLERPEN) pen = ami_system_colour_scrollbar_fgpen(drinfo);
+
+ /* Get the colour of the pen being used for "pen" */
+ GetRGB32(screen->ViewPort.ColorMap, drinfo->dri_Pens[pen], 1, (ULONG *)&colr);
+
+ /* convert it to a color */
+ def_colour = ((colr[0] & 0xff000000) >> 24) |
+ ((colr[1] & 0xff000000) >> 16) |
+ ((colr[2] & 0xff000000) >> 8);
+
+ FreeScreenDrawInfo(screen, drinfo);
+ }
+ }
+
+ if (nsoptions_default[option].value.c == nsoptions[option].value.c)
+ nsoptions[option].value.c = def_colour;
+ nsoptions_default[option].value.c = def_colour;
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in amiga/gui.h */
+STRPTR ami_gui_get_screen_title(void)
+{
+ if(nsscreentitle == NULL) {
+ nsscreentitle = ASPrintf("NetSurf %s", netsurf_version);
+ /* If this fails it will be NULL, which means we'll get the screen's
+ * default titlebar text instead - so no need to check for error. */
+ }
+
+ return nsscreentitle;
+}
+
+static void ami_set_screen_defaults(struct Screen *screen)
+{
+ nsoption_default_set_int(window_x, 0);
+ nsoption_default_set_int(window_y, screen->BarHeight + 1);
+ nsoption_default_set_int(window_width, screen->Width);
+ nsoption_default_set_int(window_height, screen->Height - screen->BarHeight - 1);
+
+#ifdef __amigaos4__
+ nsoption_default_set_int(redraw_tile_size_x, screen->Width);
+ nsoption_default_set_int(redraw_tile_size_y, screen->Height);
+
+ /* set system colours for amiga ui */
+ colour_option_from_pen(FILLPEN, NSOPTION_sys_colour_ActiveBorder, screen, 0x00000000);
+ colour_option_from_pen(FILLPEN, NSOPTION_sys_colour_ActiveCaption, screen, 0x00dddddd);
+ colour_option_from_pen(BACKGROUNDPEN, NSOPTION_sys_colour_AppWorkspace, screen, 0x00eeeeee);
+ colour_option_from_pen(BACKGROUNDPEN, NSOPTION_sys_colour_Background, screen, 0x00aa0000);
+ colour_option_from_pen(FOREGROUNDPEN, NSOPTION_sys_colour_ButtonFace, screen, 0x00aaaaaa);
+ colour_option_from_pen(FORESHINEPEN, NSOPTION_sys_colour_ButtonHighlight, screen, 0x00cccccc);
+ colour_option_from_pen(FORESHADOWPEN, NSOPTION_sys_colour_ButtonShadow, screen, 0x00bbbbbb);
+ colour_option_from_pen(TEXTPEN, NSOPTION_sys_colour_ButtonText, screen, 0x00000000);
+ colour_option_from_pen(FILLTEXTPEN, NSOPTION_sys_colour_CaptionText, screen, 0x00000000);
+ colour_option_from_pen(DISABLEDTEXTPEN, NSOPTION_sys_colour_GrayText, screen, 0x00777777);
+ colour_option_from_pen(SELECTPEN, NSOPTION_sys_colour_Highlight, screen, 0x00ee0000);
+ colour_option_from_pen(SELECTTEXTPEN, NSOPTION_sys_colour_HighlightText, screen, 0x00000000);
+ colour_option_from_pen(INACTIVEFILLPEN, NSOPTION_sys_colour_InactiveBorder, screen, 0x00000000);
+ colour_option_from_pen(INACTIVEFILLPEN, NSOPTION_sys_colour_InactiveCaption, screen, 0x00ffffff);
+ colour_option_from_pen(INACTIVEFILLTEXTPEN, NSOPTION_sys_colour_InactiveCaptionText, screen, 0x00cccccc);
+ colour_option_from_pen(BACKGROUNDPEN, NSOPTION_sys_colour_InfoBackground, screen, 0x00aaaaaa);/* This is wrong, HelpHint backgrounds are pale yellow but doesn't seem to be a DrawInfo pen defined for it. */
+ colour_option_from_pen(TEXTPEN, NSOPTION_sys_colour_InfoText, screen, 0x00000000);
+ colour_option_from_pen(MENUBACKGROUNDPEN, NSOPTION_sys_colour_Menu, screen, 0x00aaaaaa);
+ colour_option_from_pen(MENUTEXTPEN, NSOPTION_sys_colour_MenuText, screen, 0x00000000);
+ colour_option_from_pen(AMINS_SCROLLERPEN, NSOPTION_sys_colour_Scrollbar, screen, 0x00aaaaaa);
+ colour_option_from_pen(FORESHADOWPEN, NSOPTION_sys_colour_ThreeDDarkShadow, screen, 0x00555555);
+ colour_option_from_pen(FOREGROUNDPEN, NSOPTION_sys_colour_ThreeDFace, screen, 0x00dddddd);
+ colour_option_from_pen(FORESHINEPEN, NSOPTION_sys_colour_ThreeDHighlight, screen, 0x00aaaaaa);
+ colour_option_from_pen(HALFSHINEPEN, NSOPTION_sys_colour_ThreeDLightShadow, screen, 0x00999999);
+ colour_option_from_pen(HALFSHADOWPEN, NSOPTION_sys_colour_ThreeDShadow, screen, 0x00777777);
+ colour_option_from_pen(BACKGROUNDPEN, NSOPTION_sys_colour_Window, screen, 0x00aaaaaa);
+ colour_option_from_pen(INACTIVEFILLPEN, NSOPTION_sys_colour_WindowFrame, screen, 0x00000000);
+ colour_option_from_pen(TEXTPEN, NSOPTION_sys_colour_WindowText, screen, 0x00000000);
+#else
+ nsoption_default_set_int(redraw_tile_size_x, 100);
+ nsoption_default_set_int(redraw_tile_size_y, 100);
+#endif
+}
+
+
+/**
+ * Set option defaults for amiga frontend
+ *
+ * @param defaults The option table to update.
+ * @return error status.
+ */
+static nserror ami_set_options(struct nsoption_s *defaults)
+{
+ STRPTR tempacceptlangs;
+ char temp[1024];
+
+ /* The following line disables the popupmenu.class select menu.
+ ** It's not recommended to use it!
+ */
+ nsoption_set_bool(core_select_menu, true);
+
+ /* ClickTab < 53 doesn't work with the auto show/hide tab-bar (for reasons forgotten) */
+ if(ClickTabBase->lib_Version < 53)
+ nsoption_set_bool(tab_always_show, true);
+
+ /* Some AmigaOS3 overrides */
+#ifndef __amigaos4__
+ nsoption_set_bool(download_notify, false);
+ nsoption_set_bool(font_antialiasing, false);
+ nsoption_set_bool(truecolour_mouse_pointers, false);
+ nsoption_set_bool(use_openurl_lib, true);
+ nsoption_set_bool(bitmap_fonts, true);
+#endif
+
+ if((!nsoption_charp(accept_language)) ||
+ (nsoption_charp(accept_language)[0] == '\0') ||
+ (nsoption_bool(accept_lang_locale) == true))
+ {
+ if((tempacceptlangs = ami_locale_langs()))
+ {
+ nsoption_set_charp(accept_language,
+ (char *)strdup(tempacceptlangs));
+ FreeVec(tempacceptlangs);
+ }
+ }
+
+ sprintf(temp, "%s/Cookies", current_user_dir);
+ nsoption_setnull_charp(cookie_file,
+ (char *)strdup(temp));
+
+ sprintf(temp, "%s/Hotlist", current_user_dir);
+ nsoption_setnull_charp(hotlist_file,
+ (char *)strdup(temp));
+
+ sprintf(temp, "%s/URLdb", current_user_dir);
+ nsoption_setnull_charp(url_file,
+ (char *)strdup(temp));
+
+ sprintf(temp, "%s/FontGlyphCache", current_user_dir);
+ nsoption_setnull_charp(font_unicode_file,
+ (char *)strdup(temp));
+
+ nsoption_setnull_charp(ca_bundle,
+ (char *)strdup("PROGDIR:Resources/ca-bundle"));
+
+ /* font defaults */
+#ifdef __amigaos4__
+ nsoption_setnull_charp(font_sans, (char *)strdup("DejaVu Sans"));
+ nsoption_setnull_charp(font_serif, (char *)strdup("DejaVu Serif"));
+ nsoption_setnull_charp(font_mono, (char *)strdup("DejaVu Sans Mono"));
+ nsoption_setnull_charp(font_cursive, (char *)strdup("DejaVu Sans"));
+ nsoption_setnull_charp(font_fantasy, (char *)strdup("DejaVu Serif"));
+#else
+ nsoption_setnull_charp(font_sans, (char *)strdup("helvetica"));
+ nsoption_setnull_charp(font_serif, (char *)strdup("times"));
+ nsoption_setnull_charp(font_mono, (char *)strdup("topaz"));
+ nsoption_setnull_charp(font_cursive, (char *)strdup("garnet"));
+ nsoption_setnull_charp(font_fantasy, (char *)strdup("emerald"));
+/* Default CG fonts for OS3 - these work with use_diskfont both on and off,
+ however they are slow in both cases. The bitmap fonts don't work when
+ use_diskfont is off. The bitmap fonts performance on 68k is far superior,
+ so default to those for now whilst testing.
+ \todo maybe add some buttons to the prefs GUI to toggle?
+ nsoption_setnull_charp(font_sans, (char *)strdup("CGTriumvirate"));
+ nsoption_setnull_charp(font_serif, (char *)strdup("CGTimes"));
+ nsoption_setnull_charp(font_mono, (char *)strdup("LetterGothic"));
+ nsoption_setnull_charp(font_cursive, (char *)strdup("CGTriumvirate"));
+ nsoption_setnull_charp(font_fantasy, (char *)strdup("CGTimes"));
+*/
+#endif
+
+ if (nsoption_charp(font_unicode) == NULL)
+ {
+ BPTR lock = 0;
+ /* Search for some likely candidates */
+
+ if((lock = Lock("FONTS:Code2000.otag", ACCESS_READ)))
+ {
+ UnLock(lock);
+ nsoption_set_charp(font_unicode,
+ (char *)strdup("Code2000"));
+ }
+ else if((lock = Lock("FONTS:Bitstream Cyberbit.otag", ACCESS_READ)))
+ {
+ UnLock(lock);
+ nsoption_set_charp(font_unicode,
+ (char *)strdup("Bitstream Cyberbit"));
+ }
+ }
+
+ if (nsoption_charp(font_surrogate) == NULL) {
+ BPTR lock = 0;
+ /* Search for some likely candidates -
+ * Ideally we should pick a font during the scan process which announces it
+ * contains UCR_SURROGATES, but nothing appears to have the tag.
+ */
+ if((lock = Lock("FONTS:Symbola.otag", ACCESS_READ))) {
+ UnLock(lock);
+ nsoption_set_charp(font_surrogate,
+ (char *)strdup("Symbola"));
+ }
+ }
+
+ return NSERROR_OK;
+}
+
+static void ami_amiupdate(void)
+{
+ /* Create AppPath location for AmiUpdate use */
+
+ BPTR lock = 0;
+
+ if(((lock = Lock("ENVARC:AppPaths",SHARED_LOCK)) == 0))
+ {
+ lock = CreateDir("ENVARC:AppPaths");
+ }
+
+ UnLock(lock);
+
+ if((lock = Lock("PROGDIR:", ACCESS_READ)))
+ {
+ char filename[1024];
+ BPTR amiupdatefh;
+
+ DevNameFromLock(lock, (STRPTR)&filename, 1024L, DN_FULLPATH);
+
+ if((amiupdatefh = FOpen("ENVARC:AppPaths/NetSurf", MODE_NEWFILE, 0))) {
+ FPuts(amiupdatefh, (CONST_STRPTR)&filename);
+ FClose(amiupdatefh);
+ }
+
+ UnLock(lock);
+ }
+}
+
+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;
+ }
+
+ netsurf_path_to_nsurl(buf, &url);
+
+ return url;
+}
+
+HOOKF(void, ami_gui_newprefs_hook, APTR, window, APTR)
+{
+ ami_set_screen_defaults(scrn);
+}
+
+static void ami_openscreen(void)
+{
+ ULONG id = 0;
+ ULONG compositing;
+
+ if (nsoption_int(screen_compositing) == -1)
+ compositing = ~0UL;
+ else compositing = nsoption_int(screen_compositing);
+
+ if (nsoption_charp(pubscreen_name) == NULL)
+ {
+ if((nsoption_charp(screen_modeid)) &&
+ (strncmp(nsoption_charp(screen_modeid), "0x", 2) == 0))
+ {
+ id = strtoul(nsoption_charp(screen_modeid), NULL, 0);
+ }
+ else
+ {
+ struct ScreenModeRequester *screenmodereq = NULL;
+
+ if((screenmodereq = AllocAslRequest(ASL_ScreenModeRequest,NULL))) {
+ if(AslRequestTags(screenmodereq,
+ ASLSM_MinDepth, 0,
+ ASLSM_MaxDepth, 32,
+ TAG_DONE))
+ {
+ char *modeid = malloc(20);
+ id = screenmodereq->sm_DisplayID;
+ sprintf(modeid, "0x%lx", id);
+ nsoption_set_charp(screen_modeid, modeid);
+ nsoption_write(current_user_options, NULL, NULL);
+ }
+ FreeAslRequest(screenmodereq);
+ }
+ }
+
+ if(screen_signal == -1) screen_signal = AllocSignal(-1);
+ LOG("Screen signal %d", screen_signal);
+ scrn = OpenScreenTags(NULL,
+ /**\todo specify screen depth */
+ SA_DisplayID, id,
+ SA_Title, ami_gui_get_screen_title(),
+ SA_Type, PUBLICSCREEN,
+ SA_PubName, "NetSurf",
+ SA_PubSig, screen_signal,
+ SA_PubTask, FindTask(0),
+ SA_LikeWorkbench, TRUE,
+ SA_Compositing, compositing,
+ TAG_DONE);
+
+ if(scrn)
+ {
+ PubScreenStatus(scrn,0);
+ }
+ else
+ {
+ FreeSignal(screen_signal);
+ screen_signal = -1;
+
+ if((scrn = LockPubScreen("NetSurf")))
+ {
+ locked_screen = TRUE;
+ }
+ else
+ {
+ nsoption_set_charp(pubscreen_name,
+ strdup("Workbench"));
+ }
+ }
+ }
+
+ if (nsoption_charp(pubscreen_name) != NULL)
+ {
+ scrn = LockPubScreen(nsoption_charp(pubscreen_name));
+
+ if(scrn == NULL)
+ {
+ scrn = LockPubScreen("Workbench");
+ }
+ locked_screen = TRUE;
+ }
+
+ ami_font_setdevicedpi(id);
+ ami_set_screen_defaults(scrn);
+ ami_help_new_screen(scrn);
+}
+
+static void ami_openscreenfirst(void)
+{
+ ami_openscreen();
+ if(!browserglob.bm) ami_init_layers(&browserglob, 0, 0, false);
+ ami_theme_throbber_setup();
+}
+
+static struct RDArgs *ami_gui_commandline(int *argc, char **argv, int *nargc, char **nargv)
+{
+ int new_argc = 1;
+ struct RDArgs *args;
+ CONST_STRPTR template = "-v/S,NSOPTS/M,URL/K,USERSDIR/K,FORCE/S";
+ long rarray[] = {0,0,0,0,0};
+ enum
+ {
+ A_VERBOSE, /* ignored */
+ A_NSOPTS, /* ignored */
+ A_URL,
+ A_USERSDIR,
+ A_FORCE
+ };
+
+ if(*argc == 0) return NULL; // argc==0 is started from wb
+
+ if((args = ReadArgs(template, rarray, NULL))) {
+ if(rarray[A_URL]) {
+ LOG("URL %s specified on command line", rarray[A_URL]);
+ temp_homepage_url = ami_to_utf8_easy((char *)rarray[A_URL]);
+ }
+
+ if(rarray[A_USERSDIR]) {
+ LOG("USERSDIR %s specified on command line", rarray[A_USERSDIR]);
+ users_dir = ASPrintf("%s", rarray[A_USERSDIR]);
+ }
+
+ if(rarray[A_FORCE]) {
+ LOG("FORCE specified on command line");
+ cli_force = true;
+ }
+
+ if(rarray[A_NSOPTS]) {
+ /* The NSOPTS/M parameter specified in the ReadArgs template is
+ * special. The /M means it collects all arguments that can't
+ * be assigned to any other parameter, and stores them in an
+ * array. We collect these and pass them as a fake argc/argv
+ * to nsoption_commandline().
+ * This trickery is necessary because if ReadArgs() is called
+ * first, nsoption_commandline() can no longer parse (fetch?)
+ * the arguments. If nsoption_commandline() is called first,
+ * then ReadArgs cannot fetch the arguments.
+ */
+ char **p = (char **)rarray[A_NSOPTS];
+
+ do {
+ LOG("Arg [%d] assigned to NSOPTS/M by ReadArgs: %s", new_argc, *p);
+ new_argc++;
+ p++;
+ } while(*p != NULL);
+
+ const char *new_argv = malloc(sizeof(char *) * new_argc);
+ const char **new_argvp = &new_argv;
+ p = (char **)rarray[A_NSOPTS];
+
+ do {
+ *new_argvp = *p;
+ new_argvp++;
+ p++;
+ } while(*p != NULL);
+
+ *nargc = new_argc;
+ *nargv = new_argv;
+ }
+ } else {
+ LOG("ReadArgs failed to parse command line");
+ }
+ return args;
+}
+
+static void ami_gui_read_tooltypes(struct WBArg *wbarg)
+{
+ struct DiskObject *dobj;
+ STRPTR *toolarray;
+ char *s;
+
+ if((*wbarg->wa_Name) && (dobj = GetDiskObject(wbarg->wa_Name))) {
+ toolarray = (STRPTR *)dobj->do_ToolTypes;
+
+ if((s = (char *)FindToolType(toolarray,"USERSDIR"))) users_dir = ASPrintf("%s", s);
+ if((s = (char *)FindToolType(toolarray,"USER"))) current_user = ASPrintf("%s", s);
+
+ FreeDiskObject(dobj);
+ }
+}
+
+static void ami_gui_read_all_tooltypes(int argc, char **argv)
+{
+ struct WBStartup *WBenchMsg;
+ struct WBArg *wbarg;
+ char i;
+ LONG olddir = -1;
+
+ if(argc == 0) { /* Started from WB */
+ WBenchMsg = (struct WBStartup *)argv;
+ for(i = 0, wbarg = WBenchMsg->sm_ArgList; i < WBenchMsg->sm_NumArgs; i++,wbarg++) {
+ olddir =-1;
+ if((wbarg->wa_Lock) && (*wbarg->wa_Name))
+ olddir = SetCurrentDir(wbarg->wa_Lock);
+
+ ami_gui_read_tooltypes(wbarg);
+
+ if(olddir !=-1) SetCurrentDir(olddir);
+ }
+ }
+}
+
+static void gui_init2(int argc, char** argv)
+{
+ struct Screen *screen;
+ BOOL notalreadyrunning;
+ nsurl *url;
+ nserror error;
+ struct browser_window *bw = NULL;
+
+ notalreadyrunning = ami_arexx_init();
+
+ /* Treeview init code ends up calling a font function which needs this */
+ glob = &browserglob;
+
+ /* ...and this ensures the treeview at least gets the WB colour palette to work with */
+ if(scrn == NULL) {
+ if((screen = LockPubScreen("Workbench"))) {
+ ami_set_screen_defaults(screen);
+ UnlockPubScreen(NULL, screen);
+ }
+ } else {
+ ami_set_screen_defaults(scrn);
+ }
+ /**/
+
+ ami_hotlist_initialise(nsoption_charp(hotlist_file));
+ ami_cookies_initialise();
+ ami_global_history_initialise();
+ search_web_select_provider(nsoption_int(search_provider));
+
+ if (notalreadyrunning &&
+ (nsoption_bool(startup_no_window) == false))
+ ami_openscreenfirst();
+
+ if(temp_homepage_url && notalreadyrunning) {
+ error = nsurl_create(temp_homepage_url, &url);
+ if (error == NSERROR_OK) {
+ error = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ &bw);
+ nsurl_unref(url);
+ }
+ if (error != NSERROR_OK) {
+ amiga_warn_user(messages_get_errorcode(error), 0);
+ }
+ free(temp_homepage_url);
+ }
+
+ if(cli_force == true) {
+ notalreadyrunning = TRUE;
+ }
+
+ if(argc == 0) { // WB
+ struct WBStartup *WBenchMsg = (struct WBStartup *)argv;
+ struct WBArg *wbarg;
+ int first=0,i=0;
+ char fullpath[1024];
+
+ for(i=0,wbarg=WBenchMsg->sm_ArgList;i<WBenchMsg->sm_NumArgs;i++,wbarg++)
+ {
+ if(i==0) continue;
+ if((wbarg->wa_Lock)&&(*wbarg->wa_Name))
+ {
+ DevNameFromLock(wbarg->wa_Lock,fullpath,1024,DN_FULLPATH);
+ AddPart(fullpath,wbarg->wa_Name,1024);
+
+ if(!temp_homepage_url) {
+ nsurl *temp_url;
+ if (netsurf_path_to_nsurl(fullpath, &temp_url) == NSERROR_OK) {
+ temp_homepage_url = strdup(nsurl_access(temp_url));
+ nsurl_unref(temp_url);
+ }
+ }
+
+ if(notalreadyrunning)
+ {
+ error = nsurl_create(temp_homepage_url, &url);
+
+ if (error == NSERROR_OK) {
+ if(!first)
+ {
+ error = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ &bw);
+
+ first=1;
+ }
+ else
+ {
+ error = browser_window_create(BW_CREATE_CLONE | BW_CREATE_HISTORY,
+ url,
+ NULL,
+ bw,
+ &bw);
+
+ }
+ nsurl_unref(url);
+
+ }
+ if (error != NSERROR_OK) {
+ amiga_warn_user(messages_get_errorcode(error), 0);
+ }
+ free(temp_homepage_url);
+ temp_homepage_url = NULL;
+ }
+ }
+ /* this should be where we read tooltypes, but it's too late for that now */
+ }
+ }
+
+ nsoption_setnull_charp(homepage_url, (char *)strdup(NETSURF_HOMEPAGE));
+
+ if(!notalreadyrunning)
+ {
+ STRPTR sendcmd = NULL;
+
+ if(temp_homepage_url)
+ {
+ sendcmd = ASPrintf("OPEN \"%s\" NEW",temp_homepage_url);
+ free(temp_homepage_url);
+ }
+ else
+ {
+ sendcmd = ASPrintf("OPEN \"%s\" NEW",nsoption_charp(homepage_url));
+ }
+ IDoMethod(arexx_obj,AM_EXECUTE,sendcmd,"NETSURF",NULL,NULL,NULL,NULL);
+ FreeVec(sendcmd);
+
+ ami_quit=true;
+ return;
+ }
+#ifdef __amigaos4__
+ if(IApplication)
+ {
+ if(argc == 0)
+ {
+ ULONG noicon = TAG_IGNORE;
+
+ if (nsoption_bool(hide_docky_icon))
+ noicon = REGAPP_NoIcon;
+
+ ami_appid = RegisterApplication(messages_get("NetSurf"),
+ REGAPP_URLIdentifier, "netsurf-browser.org",
+ REGAPP_WBStartup, (struct WBStartup *)argv,
+ noicon, TRUE,
+ REGAPP_HasPrefsWindow, TRUE,
+ REGAPP_CanCreateNewDocs, TRUE,
+ REGAPP_UniqueApplication, TRUE,
+ REGAPP_Description, messages_get("NetSurfDesc"),
+ TAG_DONE);
+ }
+ else
+ {
+/* TODO: Specify icon when run from Shell */
+ ami_appid = RegisterApplication(messages_get("NetSurf"),
+ REGAPP_URLIdentifier, "netsurf-browser.org",
+ REGAPP_FileName, argv[0],
+ REGAPP_NoIcon, TRUE,
+ REGAPP_HasPrefsWindow, TRUE,
+ REGAPP_CanCreateNewDocs, TRUE,
+ REGAPP_UniqueApplication, TRUE,
+ REGAPP_Description, messages_get("NetSurfDesc"),
+ TAG_DONE);
+ }
+
+ GetApplicationAttrs(ami_appid, APPATTR_Port, (ULONG)&applibport, TAG_DONE);
+ if(applibport) applibsig = (1L << applibport->mp_SigBit);
+ }
+#endif
+ if(!bw && (nsoption_bool(startup_no_window) == false)) {
+ error = nsurl_create(nsoption_charp(homepage_url), &url);
+ if (error == NSERROR_OK) {
+ error = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ if (error != NSERROR_OK) {
+ amiga_warn_user(messages_get_errorcode(error), 0);
+ }
+ }
+}
+
+static void ami_update_buttons(struct gui_window_2 *gwin)
+{
+ long back=FALSE, forward=FALSE, tabclose=FALSE, stop=FALSE, reload=FALSE;
+ long s_back, s_forward, s_tabclose, s_stop, s_reload;
+
+ if(!browser_window_back_available(gwin->gw->bw))
+ back=TRUE;
+
+ if(!browser_window_forward_available(gwin->gw->bw))
+ forward=TRUE;
+
+ if(!browser_window_stop_available(gwin->gw->bw))
+ stop=TRUE;
+
+ if(!browser_window_reload_available(gwin->gw->bw))
+ reload=TRUE;
+
+ if(nsoption_bool(kiosk_mode) == false)
+ {
+ if(gwin->tabs <= 1)
+ {
+ tabclose=TRUE;
+ OffMenu(gwin->win,AMI_MENU_CLOSETAB);
+ }
+ else
+ {
+ OnMenu(gwin->win,AMI_MENU_CLOSETAB);
+ }
+ }
+
+#ifdef __amigaos4__
+ GetAttr(GA_Disabled, gwin->objects[GID_BACK], (uint32 *)&s_back);
+ GetAttr(GA_Disabled, gwin->objects[GID_FORWARD], (uint32 *)&s_forward);
+ GetAttr(GA_Disabled, gwin->objects[GID_RELOAD], (uint32 *)&s_reload);
+ GetAttr(GA_Disabled, gwin->objects[GID_STOP], (uint32 *)&s_stop);
+#endif
+
+ if(BOOL_MISMATCH(s_back, back))
+ SetGadgetAttrs((struct Gadget *)gwin->objects[GID_BACK],
+ gwin->win, NULL, GA_Disabled, back, TAG_DONE);
+
+ if(BOOL_MISMATCH(s_forward, forward))
+ SetGadgetAttrs((struct Gadget *)gwin->objects[GID_FORWARD],
+ gwin->win, NULL, GA_Disabled, forward, TAG_DONE);
+
+ if(BOOL_MISMATCH(s_reload, reload))
+ SetGadgetAttrs((struct Gadget *)gwin->objects[GID_RELOAD],
+ gwin->win, NULL, GA_Disabled, reload, TAG_DONE);
+
+ if(BOOL_MISMATCH(s_stop, stop))
+ SetGadgetAttrs((struct Gadget *)gwin->objects[GID_STOP],
+ gwin->win, NULL, GA_Disabled, stop, TAG_DONE);
+
+ if(ClickTabBase->lib_Version < 53) {
+ if(gwin->tabs <= 1) tabclose = TRUE;
+#ifdef __amigaos4__
+ GetAttr(GA_Disabled, gwin->objects[GID_CLOSETAB], (uint32 *)&s_tabclose);
+#endif
+ if(BOOL_MISMATCH(s_tabclose, tabclose))
+ SetGadgetAttrs((struct Gadget *)gwin->objects[GID_CLOSETAB],
+ gwin->win, NULL, GA_Disabled, tabclose, TAG_DONE);
+ }
+
+ /* Update the back/forward buttons history context menu */
+ ami_ctxmenu_history_create(AMI_CTXMENU_HISTORY_BACK, gwin);
+ ami_ctxmenu_history_create(AMI_CTXMENU_HISTORY_FORWARD, gwin);
+}
+
+void ami_gui_history(struct gui_window_2 *gwin, bool back)
+{
+ if(back == true)
+ {
+ if(browser_window_back_available(gwin->gw->bw))
+ browser_window_history_back(gwin->gw->bw, false);
+ }
+ else
+ {
+ if(browser_window_forward_available(gwin->gw->bw))
+ browser_window_history_forward(gwin->gw->bw, false);
+ }
+
+ ami_update_buttons(gwin);
+}
+
+int ami_key_to_nskey(ULONG keycode, struct InputEvent *ie)
+{
+ int nskey = 0, chars;
+ char buffer[20];
+ char *utf8 = NULL;
+
+ if(keycode >= IECODE_UP_PREFIX) return 0;
+
+ switch(keycode)
+ {
+ case RAWKEY_CRSRUP:
+ if(ie->ie_Qualifier & IEQUALIFIER_RSHIFT)
+ {
+ nskey = NS_KEY_PAGE_UP;
+ }
+ else if(ie->ie_Qualifier & IEQUALIFIER_RALT)
+ {
+ nskey = NS_KEY_TEXT_START;
+ }
+ else nskey = NS_KEY_UP;
+ break;
+ case RAWKEY_CRSRDOWN:
+ if(ie->ie_Qualifier & IEQUALIFIER_RSHIFT)
+ {
+ nskey = NS_KEY_PAGE_DOWN;
+ }
+ else if(ie->ie_Qualifier & IEQUALIFIER_RALT)
+ {
+ nskey = NS_KEY_TEXT_END;
+ }
+ else nskey = NS_KEY_DOWN;
+ break;
+ case RAWKEY_CRSRLEFT:
+ if(ie->ie_Qualifier & IEQUALIFIER_RSHIFT)
+ {
+ nskey = NS_KEY_LINE_START;
+ }
+ else if(ie->ie_Qualifier & IEQUALIFIER_RALT)
+ {
+ nskey = NS_KEY_WORD_LEFT;
+ }
+ else nskey = NS_KEY_LEFT;
+ break;
+ case RAWKEY_CRSRRIGHT:
+ if(ie->ie_Qualifier & IEQUALIFIER_RSHIFT)
+ {
+ nskey = NS_KEY_LINE_END;
+ }
+ else if(ie->ie_Qualifier & IEQUALIFIER_RALT)
+ {
+ nskey = NS_KEY_WORD_RIGHT;
+ }
+ else nskey = NS_KEY_RIGHT;
+ break;
+ case RAWKEY_ESC:
+ nskey = NS_KEY_ESCAPE;
+ break;
+ case RAWKEY_PAGEUP:
+ nskey = NS_KEY_PAGE_UP;
+ break;
+ case RAWKEY_PAGEDOWN:
+ nskey = NS_KEY_PAGE_DOWN;
+ break;
+ case RAWKEY_HOME:
+ nskey = NS_KEY_TEXT_START;
+ break;
+ case RAWKEY_END:
+ nskey = NS_KEY_TEXT_END;
+ break;
+ case RAWKEY_BACKSPACE:
+ if(ie->ie_Qualifier & IEQUALIFIER_RSHIFT)
+ {
+ nskey = NS_KEY_DELETE_LINE_START;
+ }
+ else nskey = NS_KEY_DELETE_LEFT;
+ break;
+ case RAWKEY_DEL:
+ if(ie->ie_Qualifier & IEQUALIFIER_RSHIFT)
+ {
+ nskey = NS_KEY_DELETE_LINE_END;
+ }
+ else nskey = NS_KEY_DELETE_RIGHT;
+ break;
+ case RAWKEY_TAB:
+ if(ie->ie_Qualifier & IEQUALIFIER_RSHIFT)
+ {
+ nskey = NS_KEY_SHIFT_TAB;
+ }
+ else nskey = NS_KEY_TAB;
+ break;
+ case RAWKEY_F5:
+ case RAWKEY_F8:
+ case RAWKEY_F9:
+ case RAWKEY_F10:
+ case RAWKEY_HELP:
+ // don't translate
+ nskey = keycode;
+ break;
+ default:
+ if((chars = MapRawKey(ie,buffer,20,NULL)) > 0) {
+ utf8_from_local_encoding(buffer, chars, &utf8);
+ nskey = utf8_to_ucs4(utf8, utf8_char_byte_length(utf8));
+
+ if(ie->ie_Qualifier & IEQUALIFIER_RCOMMAND) {
+ switch(nskey) {
+ case 'a':
+ nskey = NS_KEY_SELECT_ALL;
+ break;
+ case 'c':
+ nskey = NS_KEY_COPY_SELECTION;
+ break;
+ case 'v':
+ nskey = NS_KEY_PASTE;
+ break;
+ case 'x':
+ nskey = NS_KEY_CUT_SELECTION;
+ break;
+ case 'y':
+ nskey = NS_KEY_REDO;
+ break;
+ case 'z':
+ nskey = NS_KEY_UNDO;
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ return nskey;
+}
+
+static void ami_update_quals(struct gui_window_2 *gwin)
+{
+ uint32 quals = 0;
+#ifdef __amigaos4__
+ GetAttr(WINDOW_Qualifier,gwin->objects[OID_MAIN],(uint32 *)&quals);
+#else
+#warning qualifier needs fixing for OS3
+#endif
+ gwin->key_state = 0;
+
+ if((quals & IEQUALIFIER_LSHIFT) || (quals & IEQUALIFIER_RSHIFT))
+ {
+ gwin->key_state |= BROWSER_MOUSE_MOD_1;
+ }
+
+ if(quals & IEQUALIFIER_CONTROL)
+ {
+ gwin->key_state |= BROWSER_MOUSE_MOD_2;
+ }
+
+ if((quals & IEQUALIFIER_LALT) || (quals & IEQUALIFIER_RALT))
+ {
+ gwin->key_state |= BROWSER_MOUSE_MOD_3;
+ }
+}
+
+/* exported interface documented in amiga/gui.h */
+nserror ami_gui_get_space_box(Object *obj, struct IBox **bbox)
+{
+#ifdef __amigaos4__
+ if(LIB_IS_AT_LEAST((struct Library *)SpaceBase, 53, 6)) {
+ *bbox = AllocVecTagList(sizeof(struct IBox), NULL);
+ if(*bbox == NULL) return NSERROR_NOMEM;
+ GetAttr(SPACE_RenderBox, obj, (ULONG *)*bbox);
+ } else
+#endif
+ {
+ GetAttr(SPACE_AreaBox, obj, (ULONG *)bbox);
+ }
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in amiga/gui.h */
+void ami_gui_free_space_box(struct IBox *bbox)
+{
+#ifdef __amigaos4__
+ if(LIB_IS_AT_LEAST((struct Library *)SpaceBase, 53, 6)) {
+ FreeVec(bbox);
+ }
+#endif
+}
+
+static bool ami_spacebox_to_ns_coords(struct gui_window_2 *gwin, int *x, int *y,
+ int space_x, int space_y)
+{
+ 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;
+
+ *x = ns_x;
+ *y = ns_y;
+
+ return true;
+}
+
+bool ami_mouse_to_ns_coords(struct gui_window_2 *gwin, int *x, int *y,
+ int mouse_x, int mouse_y)
+{
+ int ns_x, ns_y;
+ struct IBox *bbox;
+
+ if(mouse_x == -1) mouse_x = gwin->win->MouseX;
+ if(mouse_y == -1) mouse_y = gwin->win->MouseY;
+
+ if(ami_gui_get_space_box((Object *)gwin->objects[GID_BROWSER], &bbox) == NSERROR_OK) {
+ ns_x = (ULONG)(mouse_x - bbox->Left);
+ ns_y = (ULONG)(mouse_y - bbox->Top);
+
+ if((ns_x < 0) || (ns_x > bbox->Width) || (ns_y < 0) || (ns_y > bbox->Height))
+ return false;
+
+ ami_gui_free_space_box(bbox);
+ } else {
+ amiga_warn_user("NoMemory", "");
+ return false;
+ }
+
+ return ami_spacebox_to_ns_coords(gwin, x, y, ns_x, ns_y);
+}
+
+static void ami_gui_scroll_internal(struct gui_window_2 *gwin, int xs, int ys)
+{
+ struct IBox *bbox;
+ int x, y;
+
+ 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)
+ {
+ int width, height;
+
+ gui_window_get_scroll(gwin->gw,
+ &gwin->gw->scrollx,
+ &gwin->gw->scrolly);
+
+ if(ami_gui_get_space_box((Object *)gwin->objects[GID_BROWSER], &bbox) != NSERROR_OK) {
+ amiga_warn_user("NoMemory", "");
+ return;
+ }
+
+ browser_window_get_extents(gwin->gw->bw, false, &width, &height);
+
+ switch(xs)
+ {
+ case SCROLL_PAGE_UP:
+ xs = gwin->gw->scrollx - bbox->Width;
+ break;
+
+ case SCROLL_PAGE_DOWN:
+ xs = gwin->gw->scrollx + bbox->Width;
+ break;
+
+ case SCROLL_TOP:
+ xs = 0;
+ break;
+
+ case SCROLL_BOTTOM:
+ xs = width;
+ break;
+
+ default:
+ xs += gwin->gw->scrollx;
+ break;
+ }
+
+ switch(ys)
+ {
+ case SCROLL_PAGE_UP:
+ ys = gwin->gw->scrolly - bbox->Height;
+ break;
+
+ case SCROLL_PAGE_DOWN:
+ ys = gwin->gw->scrolly + bbox->Height;
+ break;
+
+ case SCROLL_TOP:
+ ys = 0;
+ break;
+
+ case SCROLL_BOTTOM:
+ ys = height;
+ break;
+
+ default:
+ ys += gwin->gw->scrolly;
+ break;
+ }
+
+ ami_gui_free_space_box(bbox);
+
+ gui_window_set_scroll(gwin->gw, xs, ys);
+ }
+ }
+}
+
+static struct IBox *ami_ns_rect_to_ibox(struct gui_window_2 *gwin, const struct rect *rect)
+{
+ struct IBox *bbox, *ibox;
+
+ ibox = AllocVecTagList(sizeof(struct IBox), NULL);
+ if(ibox == NULL) return NULL;
+
+ if(ami_gui_get_space_box((Object *)gwin->objects[GID_BROWSER], &bbox) != NSERROR_OK) {
+ amiga_warn_user("NoMemory", "");
+ return NULL;
+ }
+
+ ibox->Left = gwin->win->MouseX + (rect->x0 * gwin->gw->scale);
+ ibox->Top = gwin->win->MouseY + (rect->y0 * gwin->gw->scale);
+
+ ibox->Width = (rect->x1 - rect->x0) * gwin->gw->scale;
+ ibox->Height = (rect->y1 - rect->y0) * gwin->gw->scale;
+
+ if(ibox->Left < bbox->Left) ibox->Left = bbox->Left;
+ if(ibox->Top < bbox->Top) ibox->Top = bbox->Top;
+
+ if((ibox->Left > (bbox->Left + bbox->Width)) ||
+ (ibox->Top > (bbox->Top + bbox->Height)) ||
+ (ibox->Width < 0) || (ibox->Height < 0))
+ {
+ FreeVec(ibox);
+ ami_gui_free_space_box(bbox);
+ return NULL;
+ }
+
+ ami_gui_free_space_box(bbox);
+ return ibox;
+}
+
+static void ami_gui_trap_mouse(struct gui_window_2 *gwin)
+{
+#ifdef __amigaos4__
+ switch(gwin->drag_op)
+ {
+ case GDRAGGING_NONE:
+ case GDRAGGING_SCROLLBAR:
+ case GDRAGGING_OTHER:
+ break;
+
+ default:
+ if(gwin->ptr_lock)
+ {
+ SetWindowAttrs(gwin->win, WA_GrabFocus, 10,
+ WA_MouseLimits, gwin->ptr_lock, TAG_DONE);
+ }
+ break;
+ }
+#endif
+}
+
+static void ami_gui_menu_update_all(void)
+{
+ struct nsObject *node;
+ struct nsObject *nnode;
+ struct gui_window_2 *gwin;
+
+ if(IsMinListEmpty(window_list)) return;
+
+ node = (struct nsObject *)GetHead((struct List *)window_list);
+
+ do {
+ nnode=(struct nsObject *)GetSucc((struct Node *)node);
+ gwin = node->objstruct;
+
+ if(node->Type == AMINS_WINDOW)
+ {
+ ami_menu_update_checked(gwin);
+ }
+ } while((node = nnode));
+}
+
+static void gui_window_get_dimensions(struct gui_window *g, int *width, int *height,
+ bool scaled)
+{
+ struct IBox *bbox;
+ if(!g) return;
+
+ if(ami_gui_get_space_box((Object *)g->shared->objects[GID_BROWSER], &bbox) != NSERROR_OK) {
+ amiga_warn_user("NoMemory", "");
+ return;
+ }
+
+ *width = bbox->Width;
+ *height = bbox->Height;
+
+ ami_gui_free_space_box(bbox);
+
+ if(scaled)
+ {
+ *width /= g->scale;
+ *height /= g->scale;
+ }
+}
+
+/* Add a horizontal scroller, if not already present
+ * Returns true if changed, false otherwise */
+static bool ami_gui_hscroll_add(struct gui_window_2 *gwin)
+{
+ struct TagItem attrs[2];
+
+ if(gwin->objects[GID_HSCROLL] != NULL) return false;
+
+ attrs[0].ti_Tag = CHILD_MinWidth;
+ attrs[0].ti_Data = 0;
+ attrs[1].ti_Tag = TAG_DONE;
+ attrs[1].ti_Data = 0;
+
+ gwin->objects[GID_HSCROLL] = ScrollerObj,
+ GA_ID, GID_HSCROLL,
+ GA_RelVerify, TRUE,
+ SCROLLER_Orientation, SORIENT_HORIZ,
+ ICA_TARGET, ICTARGET_IDCMP,
+ ScrollerEnd;
+#ifdef __amigaos4__
+ IDoMethod(gwin->objects[GID_HSCROLLLAYOUT], LM_ADDCHILD,
+ gwin->win, gwin->objects[GID_HSCROLL], attrs);
+#else
+ SetAttrs(gwin->objects[GID_HSCROLLLAYOUT],
+ LAYOUT_AddChild, gwin->objects[GID_HSCROLL], TAG_MORE, &attrs);
+#endif
+ return true;
+}
+
+/* Remove the horizontal scroller, if present */
+static bool ami_gui_hscroll_remove(struct gui_window_2 *gwin)
+{
+ if(gwin->objects[GID_HSCROLL] == NULL) return false;
+
+#ifdef __amigaos4__
+ IDoMethod(gwin->objects[GID_HSCROLLLAYOUT], LM_REMOVECHILD,
+ gwin->win, gwin->objects[GID_HSCROLL]);
+#else
+ SetAttrs(gwin->objects[GID_HSCROLLLAYOUT], LAYOUT_RemoveChild, gwin->objects[GID_HSCROLL]);
+#endif
+
+ gwin->objects[GID_HSCROLL] = NULL;
+
+ return true;
+}
+
+/* Add a vertical scroller, if not already present
+ * Returns true if changed, false otherwise */
+static bool ami_gui_vscroll_add(struct gui_window_2 *gwin)
+{
+ struct TagItem attrs[2];
+
+ if(gwin->objects[GID_VSCROLL] != NULL) return false;
+
+ attrs[0].ti_Tag = CHILD_MinWidth;
+ attrs[0].ti_Data = 0;
+ attrs[1].ti_Tag = TAG_DONE;
+ attrs[1].ti_Data = 0;
+
+ gwin->objects[GID_VSCROLL] = ScrollerObj,
+ GA_ID, GID_VSCROLL,
+ GA_RelVerify, TRUE,
+ ICA_TARGET, ICTARGET_IDCMP,
+ ScrollerEnd;
+#ifdef __amigaos4__
+ IDoMethod(gwin->objects[GID_VSCROLLLAYOUT], LM_ADDCHILD,
+ gwin->win, gwin->objects[GID_VSCROLL], attrs);
+#else
+ SetAttrs(gwin->objects[GID_VSCROLLLAYOUT],
+ LAYOUT_AddChild, gwin->objects[GID_VSCROLL], TAG_MORE, &attrs);
+#endif
+ return true;
+}
+
+/* Remove the vertical scroller, if present */
+static bool ami_gui_vscroll_remove(struct gui_window_2 *gwin)
+{
+ if(gwin->objects[GID_VSCROLL] == NULL) return false;
+
+#ifdef __amigaos4__
+ IDoMethod(gwin->objects[GID_VSCROLLLAYOUT], LM_REMOVECHILD,
+ gwin->win, gwin->objects[GID_VSCROLL]);
+#else
+ SetAttrs(gwin->objects[GID_VSCROLLLAYOUT], LAYOUT_RemoveChild, gwin->objects[GID_VSCROLL]);
+#endif
+
+ gwin->objects[GID_VSCROLL] = NULL;
+
+ return true;
+}
+
+/**
+ * Check the scroll bar requirements for a browser window, and add/remove
+ * the vertical scroller as appropriate. This should be the main entry
+ * point used to perform this task.
+ *
+ * \param gwin "Shared" GUI window to check the state of
+ */
+static void ami_gui_scroller_update(struct gui_window_2 *gwin)
+{
+ int h = 1, w = 1, wh = 0, ww = 0;
+ bool rethinkv = false;
+ bool rethinkh = false;
+ browser_scrolling hscroll = BW_SCROLLING_YES;
+ browser_scrolling vscroll = BW_SCROLLING_YES;
+
+ browser_window_get_scrollbar_type(gwin->gw->bw, &hscroll, &vscroll);
+
+ if(browser_window_is_frameset(gwin->gw->bw) == true) {
+ rethinkv = ami_gui_vscroll_remove(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);
+ }
+
+ if(vscroll == BW_SCROLLING_NO) {
+ rethinkv = ami_gui_vscroll_remove(gwin);
+ } else {
+ if (h > wh) rethinkv = ami_gui_vscroll_add(gwin);
+ else rethinkv = ami_gui_vscroll_remove(gwin);
+ }
+
+ if(hscroll == BW_SCROLLING_NO) {
+ rethinkh = ami_gui_hscroll_remove(gwin);
+ } else {
+ if (w > ww) rethinkh = ami_gui_hscroll_add(gwin);
+ else rethinkh = ami_gui_hscroll_remove(gwin);
+ }
+ }
+
+ if(rethinkv || rethinkh) {
+ FlushLayoutDomainCache((struct Gadget *)gwin->objects[GID_MAIN]);
+ RethinkLayout((struct Gadget *)gwin->objects[GID_MAIN],
+ gwin->win, NULL, TRUE);
+ browser_window_schedule_reformat(gwin->gw->bw);
+ }
+}
+
+/**
+ * function to add retrieved favicon to gui
+ */
+static void gui_window_set_icon(struct gui_window *g, hlcache_handle *icon)
+{
+ struct BitMap *bm = NULL;
+ struct IBox *bbox;
+ struct bitmap *icon_bitmap = NULL;
+
+ if(nsoption_bool(kiosk_mode) == true) return;
+ if(!g) return;
+
+ if ((icon != NULL) && ((icon_bitmap = content_get_bitmap(icon)) != NULL))
+ {
+ bm = ami_bitmap_get_native(icon_bitmap, 16, 16,
+ g->shared->win->RPort->BitMap);
+ }
+
+ if(g == g->shared->gw) {
+ RefreshGList((struct Gadget *)g->shared->objects[GID_ICON],
+ g->shared->win, NULL, 1);
+
+ if(bm)
+ {
+ ULONG tag, tag_data, minterm;
+
+ if(ami_plot_screen_is_palettemapped() == false) {
+ tag = BLITA_UseSrcAlpha;
+ tag_data = !amiga_bitmap_get_opaque(icon_bitmap);
+ minterm = 0xc0;
+ } else {
+ tag = BLITA_MaskPlane;
+ tag_data = (ULONG)ami_bitmap_get_mask(icon_bitmap, 16, 16, bm);
+ minterm = MINTERM_SRCMASK;
+ }
+
+ if(ami_gui_get_space_box((Object *)g->shared->objects[GID_ICON], &bbox) != NSERROR_OK) {
+ amiga_warn_user("NoMemory", "");
+ return;
+ }
+
+ EraseRect(g->shared->win->RPort, bbox->Left, bbox->Top,
+ bbox->Left + 16, bbox->Top + 16);
+
+#ifdef __amigaos4__
+ BltBitMapTags(BLITA_SrcX, 0,
+ BLITA_SrcY, 0,
+ BLITA_DestX, bbox->Left,
+ BLITA_DestY, bbox->Top,
+ BLITA_Width, 16,
+ BLITA_Height, 16,
+ BLITA_Source, bm,
+ BLITA_Dest, g->shared->win->RPort,
+ BLITA_SrcType, BLITT_BITMAP,
+ BLITA_DestType, BLITT_RASTPORT,
+ BLITA_Minterm, minterm,
+ tag, tag_data,
+ TAG_DONE);
+#else
+ if(tag_data) {
+ BltMaskBitMapRastPort(bm, 0, 0, g->shared->win->RPort,
+ bbox->Left, bbox->Top, 16, 16, minterm, tag_data);
+ } else {
+ BltBitMapRastPort(bm, 0, 0, g->shared->win->RPort,
+ bbox->Left, bbox->Top, 16, 16, 0xc0);
+ }
+#endif
+ ami_gui_free_space_box(bbox);
+ }
+ }
+
+ g->favicon = icon;
+}
+
+static void ami_gui_refresh_favicon(void *p)
+{
+ struct gui_window_2 *gwin = (struct gui_window_2 *)p;
+ gui_window_set_icon(gwin->gw, gwin->gw->favicon);
+}
+
+/* Gets the size that border gadget 1 (status) needs to be.
+ * Returns the width of the size gadget as a convenience.
+ */
+#ifdef __amigaos4__
+static ULONG ami_get_border_gadget_size(struct gui_window_2 *gwin, ULONG *width, ULONG *height)
+{
+ static ULONG sz_gad_width = 0;
+ static ULONG sz_gad_height = 0;
+ ULONG available_width;
+
+ if((sz_gad_width == 0) || (sz_gad_height == 0)) {
+ struct DrawInfo *dri = GetScreenDrawInfo(scrn);
+ GetGUIAttrs(NULL, dri,
+ GUIA_SizeGadgetWidth, &sz_gad_width,
+ GUIA_SizeGadgetHeight, &sz_gad_height,
+ TAG_DONE);
+ FreeScreenDrawInfo(scrn, dri);
+ }
+ available_width = gwin->win->Width - scrn->WBorLeft - sz_gad_width;
+
+ *width = available_width;
+ *height = sz_gad_height;
+
+ return sz_gad_width;
+}
+#endif
+
+static void ami_set_border_gadget_size(struct gui_window_2 *gwin)
+{
+#ifdef __amigaos4__
+ /* Reset gadget widths according to new calculation */
+ ULONG size1, size2;
+
+ ami_get_border_gadget_size(gwin, &size1, &size2);
+
+ RefreshSetGadgetAttrs((struct Gadget *)(APTR)gwin->objects[GID_STATUS],
+ gwin->win, NULL,
+ GA_Width, size1,
+ TAG_DONE);
+
+ RefreshWindowFrame(gwin->win);
+#endif
+}
+
+static void ami_handle_msg(void)
+{
+ ULONG result,storage = 0,x,y,xs,ys,width=800,height=600;
+ uint16 code;
+ struct IBox *bbox;
+ struct nsObject *node;
+ struct nsObject *nnode;
+ struct gui_window_2 *gwin = NULL;
+ struct InputEvent *ie;
+ struct Node *tabnode;
+ int nskey;
+ struct timeval curtime;
+ static int drag_x_move = 0, drag_y_move = 0;
+ char *utf8 = NULL;
+ nsurl *url;
+
+ if(IsMinListEmpty(window_list))
+ {
+ /* no windows in list, so NetSurf should not be running */
+ ami_try_quit();
+ return;
+ }
+
+ node = (struct nsObject *)GetHead((struct List *)window_list);
+
+ do
+ {
+ nnode=(struct nsObject *)GetSucc((struct Node *)node);
+
+ gwin = node->objstruct;
+
+ if(node->Type == AMINS_TVWINDOW) {
+ if(ami_tree_event((struct treeview_window *)gwin)) {
+ ami_try_quit();
+ break;
+ } else {
+ node = nnode;
+ continue;
+ }
+ } else if(node->Type == AMINS_FINDWINDOW) {
+ if(ami_search_event()) {
+ ami_try_quit();
+ break;
+ } else {
+ node = nnode;
+ continue;
+ }
+ } else if(node->Type == AMINS_HISTORYWINDOW) {
+ if(ami_history_event((struct history_window *)gwin)) {
+ ami_try_quit();
+ break;
+ } else {
+ node = nnode;
+ continue;
+ }
+ } else if(node->Type == AMINS_PRINTWINDOW) {
+ if(ami_print_event((struct ami_print_window *)gwin)) {
+ ami_try_quit();
+ break;
+ } else {
+ node = nnode;
+ continue;
+ }
+ } else if(node->Type == AMINS_GUIOPTSWINDOW) {
+ if(ami_gui_opts_event()) {
+ /* last window possibly closed, so exit with conditions ;) */
+ if(scrn) ami_try_quit();
+ break;
+ } else {
+ node = nnode;
+ continue;
+ }
+ } else if(node->Type == AMINS_DLWINDOW)