summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Docs/BUILDING-Windows228
-rw-r--r--Makefile56
-rw-r--r--Makefile.defaults28
-rw-r--r--Makefile.resources13
-rw-r--r--Makefile.sources11
-rw-r--r--desktop/gui.h1
-rw-r--r--desktop/netsurf.c26
-rw-r--r--utils/config.h26
-rw-r--r--utils/filename.c10
-rw-r--r--utils/useragent.c3
-rw-r--r--utils/utils.c14
-rw-r--r--utils/utils.h5
-rw-r--r--utils/utsname.h39
-rw-r--r--windows/NetSurfInstaller.nsi95
-rw-r--r--windows/about.c174
-rw-r--r--windows/about.h24
-rw-r--r--windows/bitmap.c333
-rw-r--r--windows/bitmap.h36
-rw-r--r--windows/download.c294
-rw-r--r--windows/download.h64
-rw-r--r--windows/filetype.c57
-rw-r--r--windows/findfile.c118
-rw-r--r--windows/findfile.h29
-rw-r--r--windows/font.c208
-rw-r--r--windows/font.h40
-rw-r--r--windows/gui.c2402
-rw-r--r--windows/gui.h89
-rw-r--r--windows/history.c41
-rw-r--r--windows/hotlist.c23
-rw-r--r--windows/localhistory.c422
-rw-r--r--windows/localhistory.h30
-rw-r--r--windows/login.c24
-rw-r--r--windows/misc.c52
-rw-r--r--windows/plot.c837
-rw-r--r--windows/plot.h30
-rw-r--r--windows/prefs.c635
-rw-r--r--windows/prefs.h26
l---------windows/res/Aliases1
-rw-r--r--windows/res/NetSurf16.icobin0 -> 1406 bytes
-rw-r--r--windows/res/NetSurf32.icobin0 -> 4286 bytes
-rw-r--r--windows/res/back.bmpbin0 -> 406 bytes
l---------windows/res/default.css1
-rw-r--r--windows/res/forward.bmpbin0 -> 406 bytes
-rw-r--r--windows/res/home.bmpbin0 -> 406 bytes
l---------windows/res/messages1
l---------windows/res/quirks.css1
-rw-r--r--windows/res/reload.bmpbin0 -> 406 bytes
-rw-r--r--windows/res/resource.rc217
-rw-r--r--windows/res/stop.bmpbin0 -> 406 bytes
-rw-r--r--windows/res/throbber.avibin0 -> 23980 bytes
-rwxr-xr-xwindows/res/throbber/throbber0.pngbin0 -> 730 bytes
-rwxr-xr-xwindows/res/throbber/throbber1.pngbin0 -> 928 bytes
-rwxr-xr-xwindows/res/throbber/throbber2.pngbin0 -> 906 bytes
-rwxr-xr-xwindows/res/throbber/throbber3.pngbin0 -> 917 bytes
-rwxr-xr-xwindows/res/throbber/throbber4.pngbin0 -> 927 bytes
-rwxr-xr-xwindows/res/throbber/throbber5.pngbin0 -> 923 bytes
-rwxr-xr-xwindows/res/throbber/throbber6.pngbin0 -> 904 bytes
-rwxr-xr-xwindows/res/throbber/throbber7.pngbin0 -> 940 bytes
-rwxr-xr-xwindows/res/throbber/throbber8.pngbin0 -> 921 bytes
-rw-r--r--windows/resourceid.h103
-rw-r--r--windows/schedule.c208
-rw-r--r--windows/schedule.h25
-rw-r--r--windows/thumbnail.c149
-rw-r--r--windows/tree.c62
64 files changed, 7287 insertions, 24 deletions
diff --git a/Docs/BUILDING-Windows b/Docs/BUILDING-Windows
new file mode 100644
index 000000000..df7589522
--- /dev/null
+++ b/Docs/BUILDING-Windows
@@ -0,0 +1,228 @@
+--------------------------------------------------------------------------------
+ Build Instructions for Windows NetSurf 17 January 2010
+--------------------------------------------------------------------------------
+
+ This document provides instructions for building the Windows version
+ of NetSurf and provides guidance on obtaining NetSurf's build
+ dependencies.
+
+ Windows NetSurf has been tested on Wine and Vista.
+
+ Building and executing NetSurf
+================================
+
+ The windows netsurf port uses the MinGW (Minimal GNU on Windows)
+ system as its build infrastructure. This allows the normal netsurf
+ build process to be used.
+
+ The method outlined here to create executables cross compiles
+ windows executable from a Linux OS host.
+
+ First of all, you should examine the contents of Makefile.defaults
+ and enable and disable relevant features as you see fit by creating
+ a Makefile.config file. Some of these options can be automatically
+ detected and used, and where this is the case they are set to such.
+ Others cannot be automatically detected from the Makefile, so you
+ will either need to install the dependencies, or set them to NO.
+
+ You should then obtain NetSurf's dependencies, keeping in mind which
+ options you have enabled in the configuration file. See the next
+ section for specifics.
+
+ Once done, to build windows NetSurf on a UNIX-like platform, simply run:
+
+ $ export MINGW_PREFIX=i586-mingw32msvc-
+ $ export MINGW_INSTALL_ENV=/usr/i586-mingw32msvc/
+ $ make TARGET=windows
+
+ If that produces errors, you probably don't have some of NetSurf's
+ build dependencies installed. See "Obtaining NetSurf's dependencies"
+ below. Or turn off the complaining features in a Makefile.config
+ file. You may need to "make clean" before attempting to build after
+ installing the dependencies.
+
+ You will need the libgnurx-0.dll from /usr/i586-mingw32msvc/bin/
+ copied next to the exe and the windows/res directory available, also
+ next to the executable.
+
+ Run NetSurf by executing it:
+
+ $ wine NetSurf.exe
+
+ The staticaly linked binary which is generated may be several
+ megabytes in size, this can be reduced by stripping the binary.
+
+ $ i586-mingw32msvc-strip NetSurf.exe
+
+
+
+ Obtaining NetSurf's build dependencies
+========================================
+
+ Package installation
+----------------------
+
+ Debian-based OS:
+
+ The mingw cross compilation tools are required. These can be
+ installed as pakages on Debian/Ubuntu systems:
+
+ $ sudo apt-get install mingw32 mingw32-binutils mingw32-runtime
+
+ These provide a suitable set of compilers and headers including the win32 API.
+
+ The includes and associated libraries are installed in
+ /usr/i586-mingw32msvc/ Which is where the build system will include
+ files from by default. The packages at time of writing only target
+ 32bit windows builds.
+
+ Other:
+
+ For other OS the apropriate packages and environment must be installed.
+
+ Base libraries
+----------------
+
+ Unlike other OS the base libraries and their dependancies need to be
+ built and installed.
+
+ The instructions given here assume you will be installing on a
+ Debian derived OS using the mingw32 packages. The libraries should
+ be unpacked and built from a suitable temporary directory.
+
+ zlib:
+
+ $ apt-get source zlib1g
+ $ cd zlib-1.2.3.3.dfsg
+ $ CC=i586-mingw32msvc-gcc AR=i586-mingw32msvc-ar RANLIB=i586-mingw32msvc-ranlib CFLAGS="-DNO_FSEEKO" ./configure --prefix=/usr/i586-mingw32msvc/
+ $ make
+ $ sudo make install
+
+
+ libiconv:
+
+ $ wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.13.1.tar.gz
+ $ tar -zxf libiconv-1.13.1.tar.gz
+ $ cd libiconv-1.13.1
+ $ ./configure --prefix=/usr/i586-mingw32msvc/ --host=i586-mingw32msvc --disable-shared
+ $ make
+ $ sudo make install
+
+
+ regex:
+
+ $ wget http://downloads.sourceforge.net/project/mingw/User%20Contributed/regex/mingw-regex-2.5.1/mingw-libgnurx-2.5.1-src.tar.gz?use_mirror=ignum
+ $ tar -zxf mingw-libgnurx-2.5.1-src.tar.gz
+ $ ./configure --prefix=/usr/i586-mingw32msvc/ --host=i586-mingw32msvc
+ $ make
+ $ sudo make install
+
+
+ openssl:
+
+ $ wget http://www.openssl.org/source/openssl-0.9.8l.tar.gz
+ $ tar -zxf openssl-0.9.8l.tar.gz
+ $ cd openssl-0.9.8l
+
+--- openssl-0.9.8l/Configure 2009-11-05 12:07:06.000000000 +0000
++++ openssl-0.9.8l-work/Configure 2010-01-25 12:35:13.000000000 +0000
+@@ -1059,7 +1059,7 @@
+
+ my $IsMK1MF=scalar grep /^$target$/,@MK1MF_Builds;
+
+-$IsMK1MF=1 if ($target eq "mingw" && $^O ne "cygwin" && !is_msys());
++#$IsMK1MF=1 if ($target eq "mingw" && $^O ne "cygwin" && !is_msys());
+
+ $no_shared = 0 if ($fipsdso && !$IsMK1MF);
+
+--- openssl-0.9.8l/e_os2.h 2005-12-18 18:57:07.000000000 +0000
++++ openssl-0.9.8l-work/e_os2.h 2010-01-25 12:42:48.000000000 +0000
+@@ -264,7 +264,7 @@
+ # define OPENSSL_IMPLEMENT_GLOBAL(type,name) \
+ extern type _hide_##name; \
+ type *_shadow_##name(void) { return &_hide_##name; } \
+- static type _hide_##name
++ type _hide_##name
+ # define OPENSSL_DECLARE_GLOBAL(type,name) type *_shadow_##name(void)
+ # define OPENSSL_GLOBAL_REF(name) (*(_shadow_##name()))
+ #else
+
+ $ ./Configure no-shared --prefix=/usr/i586-mingw32msvc/ mingw
+ $ make CC=i586-mingw32msvc-gcc RANLIB=i586-mingw32msvc-ranlib
+
+
+ libxml:
+
+ $ apt-get source libxml2
+ $ cd libxml2-2.6.32.dfsg/
+ $ ./configure --prefix=/usr/i586-mingw32msvc/ --disable-shared --host=i586-mingw32msvc
+ $ make
+ $ sudo make install
+
+
+ libcurl:
+
+ $ LDFLAGS=-mwindows ./configure --prefix=/usr/i586-mingw32msvc/ --host=i586-mingw32msvc --disable-shared --disable-ldap
+ $ make
+ $ sudo make install
+
+
+ libpng:
+ $ wget "http://downloads.sourceforge.net/project/libpng/01-libpng-master/1.4.0/libpng-1.4.0.tar.gz?use_mirror=garr"
+ $ tar -zxf libpng-1.4.0.tar.gz
+ $ cd libpng-1.4.0
+ $ make
+ $ sudo make install
+
+
+ libjpeg:
+
+wget http://www.ijg.org/files/jpegsrc.v8.tar.gz
+tar -zxf jpegsrc.v8.tar.gz
+cd jpeg-8
+./configure --prefix=/usr/i586-mingw32msvc/ --host=i586-mingw32msvc --disable-shared
+make
+sudo make install
+
+ The NetSurf project's libraries
+---------------------------------
+
+ The NetSurf project has developed several libraries which are required by
+ the browser. These are:
+
+ LibParserUtils -- Parser building utility functions
+ LibWapcaplet -- String internment
+ Hubbub -- HTML5 compliant HTML parser
+ LibCSS -- CSS parser and selection engine
+ LibNSGIF -- GIF format image decoder
+ LibNSBMP -- BMP and ICO format image decoder
+
+ To fetch each of these libraries, run the following commands:
+
+ $ svn co svn://svn.netsurf-browser.org/trunk/libparserutils
+ $ svn co svn://svn.netsurf-browser.org/trunk/libwapcaplet
+ $ svn co svn://svn.netsurf-browser.org/trunk/hubbub
+ $ svn co svn://svn.netsurf-browser.org/trunk/libcss
+ $ svn co svn://svn.netsurf-browser.org/trunk/libnsgif
+ $ svn co svn://svn.netsurf-browser.org/trunk/libnsbmp
+
+ To build and install these libraries.
+
+ Ensure the MINGW_INSTALL_ENV variable is correctly set.
+
+ $ export MINGW_INSTALL_ENV=/usr/i586-mingw32msvc/
+
+ Then simply enter each of their directories and run:
+
+ $ make TARGET=windows PREFIX=/usr/i586-mingw32msvc/
+ $ sudo make TARGET=windows PREFIX=/usr/i586-mingw32msvc/ install
+
+ Resources
+-----------
+
+ The windows resources may be rebuilt. Currently there is 1 object
+ file included in the svn distribution of NetSurf that could be
+ manually compiled
+
+ $ cd windows/res
+ $ i586-mingw32msvc-windres resource.rc -O coff -o resource.o
diff --git a/Makefile b/Makefile
index faedb5127..605ea28ff 100644
--- a/Makefile
+++ b/Makefile
@@ -93,7 +93,9 @@ ifneq ($(TARGET),riscos)
ifneq ($(TARGET),beos)
ifneq ($(TARGET),amiga)
ifneq ($(TARGET),framebuffer)
- $(error Unknown TARGET "$(TARGET)", should either be "riscos", "gtk", "beos", "amiga", or "framebuffer")
+ ifneq ($(TARGET),windows)
+ $(error Unknown TARGET "$(TARGET)", should either be "riscos", "gtk", "beos", "amiga", "framebuffer" or "windows")
+ endif
endif
endif
endif
@@ -162,8 +164,20 @@ else
PKG_CONFIG :=
#endif
else
- # Building for GTK, Amiga, or Framebuffer
- PKG_CONFIG := pkg-config
+ ifeq ($(TARGET),windows)
+ ifneq ($(HOST),windows)
+ # Set Mingw defaults
+ MINGW_PREFIX ?= i586-mingw32msvc-
+ MINGW_INSTALL_ENV ?= /usr/i586-mingw32msvc/
+
+ # mingw cross-compile
+ CC := $(MINGW_PREFIX)gcc
+ PKG_CONFIG := $(MINGW_INSTALL_ENV)/bin/pkg-config
+ endif
+ else
+ # Building for GTK, Amiga, Framebuffer
+ PKG_CONFIG := pkg-config
+ endif
endif
endif
@@ -435,9 +449,9 @@ ifeq ($(TARGET),gtk)
CFLAGS += $(GTKCFLAGS)
LDFLAGS += $(GTKLDFLAGS)
- # ----------------------------------------------------------------------------
+ # ---------------------------------------------------------------------------
# Windows flag setup
- # ----------------------------------------------------------------------------
+ # ---------------------------------------------------------------------------
ifeq ($(HOST),Windows_NT)
CFLAGS += -U__STRICT_ANSI__
@@ -445,6 +459,35 @@ ifeq ($(TARGET),gtk)
endif
# ----------------------------------------------------------------------------
+# Windows target setup
+# ----------------------------------------------------------------------------
+ifeq ($(TARGET),windows)
+ NETSURF_FEATURE_NSSVG_CFLAGS := -DWITH_NSSVG
+ NETSURF_FEATURE_ROSPRITE_CFLAGS := -DWITH_NSSPRITE
+ NETSURF_FEATURE_BMP_CFLAGS := -DWITH_BMP
+ NETSURF_FEATURE_GIF_CFLAGS := -DWITH_GIF
+ NETSURF_FEATURE_PNG_CFLAGS := -DWITH_PNG
+ $(eval $(call feature_enabled,BMP,-DWITH_BMP,-lnsbmp,NetSurf BMP decoder))
+ $(eval $(call feature_enabled,GIF,-DWITH_GIF,-lnsgif,NetSurf GIF decoder))
+ $(eval $(call feature_enabled,PNG,-DWITH_PNG,-lpng,PNG support))
+ $(eval $(call feature_enabled,NSSVG,-DWITH_NS_SVG,-lsvgtiny,SVG rendering))
+ $(eval $(call feature_enabled,MNG,,-llcms -ljpeg,MNG additional support))
+
+ LDFLAGS += -L${MINGW_INSTALL_ENV}/lib $(shell $(PKG_CONFIG) --libs zlib \
+ libxml-2.0 libcurl libhubbub libparserutils libcss libwapcaplet) \
+ -lparserutils -lssl -lcrypto -lregex -liconv -lcss -lwapcaplet \
+ -lgdi32 -lcomctl32 -lws2_32 -lmsimg32 -mwindows
+ CFLAGS += -U__STRICT_ANSI__ -mwin32
+ WSCFLAGS := -std=c99 \
+ $(WARNFLAGS) -I. -I/${MINGW_INSTALL_ENV}/include \
+ -DCURL_STATICLIB \
+ $(shell $(PKG_CONFIG) --cflags libcurl libhubbub zlib libparserutils \
+ libxml-2.0) -g
+ CFLAGS += $(WSCFLAGS)
+ LDFLAGS += $(WSCFLAGS)
+endif
+
+# ----------------------------------------------------------------------------
# Amiga target setup
# ----------------------------------------------------------------------------
@@ -555,6 +598,9 @@ else
$(Q)$(ELF2AIF) $(EXETARGET:,ff8=,e1f) $(EXETARGET)
$(Q)$(RM) $(EXETARGET:,ff8=,e1f)
endif
+ifeq ($(TARGET),windows)
+ $(Q)$(TOUCH) windows/res/preferences
+endif
ifeq ($(TARGET),gtk)
$(Q)$(TOUCH) gtk/res/toolbarIndices
endif
diff --git a/Makefile.defaults b/Makefile.defaults
index 9862916c5..ecb97d78e 100644
--- a/Makefile.defaults
+++ b/Makefile.defaults
@@ -229,6 +229,34 @@ ifeq ($(TARGET),framebuffer)
endif
+# ----------------------------------------------------------------------------
+# windows-specific options
+# ----------------------------------------------------------------------------
+ifeq ($(TARGET),windows)
+
+ # Enable NetSurf's use of librosprite for displaying RISC OS Sprites
+ # Valid options: YES, NO, AUTO
+ NETSURF_USE_ROSPRITE := NO
+
+ # Enable NetSurf's use of libsvgtiny for displaying SVGs
+ # Valid options: YES, NO
+ NETSURF_USE_NSSVG := NO
+
+ # Force using glibc internal iconv implementation instead of external libiconv
+ # Valid options: YES, NO
+ NETSURF_USE_LIBICONV_PLUG := NO
+
+ # mng support does not currently build on windows
+ NETSURF_USE_MNG := NO
+
+ # no pdf support
+ NETSURF_USE_HARU_PDF := NO
+
+ # Optimisation levels
+ CFLAGS += -O2 -Wuninitialized
+
+endif
+
# Include any local configuration
-include Makefile.config
diff --git a/Makefile.resources b/Makefile.resources
index d44697fad..2a5493226 100644
--- a/Makefile.resources
+++ b/Makefile.resources
@@ -62,7 +62,16 @@ S_IMAGES :=
$(eval $(foreach V,$(filter FB_IMAGE_%,$(.VARIABLES)),$(call convert_image,$($(V)),$(OBJROOT)/$(patsubst FB_IMAGE_%,%,$(V)).c,$(patsubst FB_IMAGE_%,%,$(V)))))
+# End of framebuffer resource definitions
+endif
+ifeq ($(TARGET),windows)
-# End of framebuffer resource definitions
-endif \ No newline at end of file
+$(OBJROOT)/windows_resource.o: windows/res/resource.rc
+ $(VQ)echo " WINDRES: compiling windows resources"
+ ${Q}$(MINGW_PREFIX)windres $< -O coff -o $@
+
+S_RESOURCES := windows_resource.o
+
+# End of windows resource definitions
+endif
diff --git a/Makefile.sources b/Makefile.sources
index a1a11cd8d..84ed16197 100644
--- a/Makefile.sources
+++ b/Makefile.sources
@@ -66,6 +66,12 @@ S_GTK := font_pango.c gtk_bitmap.c gtk_gui.c gtk_schedule.c \
S_GTK := $(addprefix gtk/,$(S_GTK)) $(addprefix utils/,container.c)
# code in utils/container.ch is non-universal it seems
+# S_WINDOWS are sources purely for the windows build
+S_WINDOWS := about.c bitmap.c download.c filetype.c findfile.c font.c \
+ gui.c history.c hotlist.c localhistory.c login.c misc.c plot.c \
+ prefs.c schedule.c thumbnail.c tree.c
+S_WINDOWS := $(addprefix windows/,$(S_WINDOWS))
+
# S_BEOS are sources purely for the BeOS build
S_BEOS := beos_about.cpp beos_bitmap.cpp beos_fetch_rsrc.cpp \
beos_filetype.cpp beos_font.cpp beos_gui.cpp beos_history.cpp \
@@ -162,6 +168,11 @@ SOURCES := $(S_COMMON) $(S_IMAGE) $(S_BROWSER) $(S_FRAMEBUFFER) $(S_IMAGES)
EXETARGET := nsfb$(SUBTARGET)
endif
+ifeq ($(TARGET),windows)
+SOURCES := $(S_COMMON) $(S_IMAGE) $(S_BROWSER) $(S_WINDOWS) $(S_RESOURCES)
+EXETARGET := NetSurf.exe
+endif
+
ifeq ($(SOURCES),)
$(error Unable to build NetSurf, could not determine set of sources to build)
endif
diff --git a/desktop/gui.h b/desktop/gui.h
index ca557ef8a..f09e5f20f 100644
--- a/desktop/gui.h
+++ b/desktop/gui.h
@@ -58,6 +58,7 @@ typedef enum { GUI_POINTER_DEFAULT, GUI_POINTER_POINT, GUI_POINTER_CARET,
#include "desktop/browser.h"
#include "desktop/search.h"
+void gui_stdout(void);
void gui_init(int argc, char** argv);
void gui_init2(int argc, char** argv);
void gui_multitask(void);
diff --git a/desktop/netsurf.c b/desktop/netsurf.c
index a1b7dabae..9acddaf87 100644
--- a/desktop/netsurf.c
+++ b/desktop/netsurf.c
@@ -23,11 +23,13 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
-#include <sys/utsname.h>
+
#include <libxml/encoding.h>
#include <libxml/globals.h>
#include <libxml/xmlversion.h>
+
#include "utils/config.h"
+#include "utils/utsname.h"
#include "content/fetch.h"
#include "content/fetchcache.h"
#include "content/urldb.h"
@@ -83,32 +85,38 @@ void netsurf_init(int argc, char** argv)
{
struct utsname utsname;
+#ifdef HAVE_SIGPIPE
/* Ignore SIGPIPE - this is necessary as OpenSSL can generate these
* and the default action is to terminate the app. There's no easy
* way of determining the cause of the SIGPIPE (other than using
* sigaction() and some mechanism for getting the file descriptor
* out of libcurl). However, we expect nothing else to generate a
* SIGPIPE, anyway, so may as well just ignore them all. */
+
signal(SIGPIPE, SIG_IGN);
+#endif
#if !((defined(__SVR4) && defined(__sun)) || defined(__NetBSD__) || \
- defined(__OpenBSD__))
+ defined(__OpenBSD__) || defined(_WIN32))
stdout = stderr;
#endif
if ((argc > 1) && (argv[1][0] == '-') && (argv[1][1] == 'v') && (argv[1][2] == 0)) {
- int argcmv;
- verbose_log = true;
- for (argcmv = 2; argcmv < argc; argcmv++) {
- argv[argcmv - 1] = argv[argcmv];
- }
- argc--;
+ int argcmv;
+ verbose_log = true;
+ for (argcmv = 2; argcmv < argc; argcmv++) {
+ argv[argcmv - 1] = argv[argcmv];
+ }
+ argc--;
+
+#ifndef HAVE_STDOUT
+ gui_stdout();
+#endif
}
#ifdef _MEMDEBUG_H_
memdebug_memdebug("memdump");
#endif
-
LOG(("version '%s'", netsurf_version));
if (uname(&utsname) < 0)
LOG(("Failed to extract machine information"));
diff --git a/utils/config.h b/utils/config.h
index c86770b6e..ba8d8227b 100644
--- a/utils/config.h
+++ b/utils/config.h
@@ -26,7 +26,7 @@
#define HAVE_STRNDUP
#if defined(__FreeBSD__) || (defined(__SRV4) && defined(__sun)) || \
defined(__APPLE__) || defined(__HAIKU__) || defined(__BEOS__) \
- || defined(__OpenBSD__)
+ || defined(__OpenBSD__) || defined(_WIN32)
/* FreeBSD and Solaris do not have this function, so
* we implement it ourselves in util.c
*/
@@ -35,12 +35,32 @@ char *strndup(const char *s, size_t n);
#endif
#define HAVE_STRCASESTR
-#if !(defined(_GNU_SOURCE) || defined(__NetBSD__) || defined(__OpenBSD__)) \
- || defined(riscos) || defined(__APPLE__)
+#if (!(defined(_GNU_SOURCE) || defined(__NetBSD__) || defined(__OpenBSD__)) \
+ || defined(riscos) || defined(__APPLE__) || defined(_WIN32))
#undef HAVE_STRCASESTR
char *strcasestr(const char *haystack, const char *needle);
#endif
+#define HAVE_UTSNAME
+#if (defined(_WIN32))
+#undef HAVE_UTSNAME
+#endif
+
+#define HAVE_MKDIR
+#if (defined(_WIN32))
+#undef HAVE_MKDIR
+#endif
+
+#define HAVE_SIGPIPE
+#if (defined(_WIN32))
+#undef HAVE_SIGPIPE
+#endif
+
+#define HAVE_STDOUT
+#if (defined(_WIN32))
+#undef HAVE_STDOUT
+#endif
+
#define HAVE_STRCHRNUL
/* For some reason, UnixLib defines this unconditionally.
* Assume we're using UnixLib if building for RISC OS. */
diff --git a/utils/filename.c b/utils/filename.c
index 5ec84b9c3..d4cb34521 100644
--- a/utils/filename.c
+++ b/utils/filename.c
@@ -32,6 +32,8 @@
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
+
+#include "utils/config.h"
#include "utils/filename.h"
#include "utils/log.h"
#include "utils/url.h"
@@ -181,13 +183,13 @@ bool filename_initialise(void)
for (start = directory; *start != '\0'; start++) {
if (*start == '/') {
*start = '\0';
- mkdir(directory, S_IRWXU);
+ nsmkdir(directory, S_IRWXU);
*start = '/';
}
}
LOG(("Temporary directory location: %s", directory));
- mkdir(directory, S_IRWXU);
+ nsmkdir(directory, S_IRWXU);
free(directory);
@@ -481,7 +483,7 @@ static struct directory *filename_create_directory(const char *prefix)
new_dir->prefix[8] = '/';
if (!is_dir(filename_directory)) {
- if (!mkdir(filename_directory, S_IRWXU))
+ if (!nsmkdir(filename_directory, S_IRWXU))
return new_dir;
/* the user has probably deleted the parent directory
@@ -508,7 +510,7 @@ static struct directory *filename_create_directory(const char *prefix)
last_1[0] = '\0';
if (!is_dir(filename_directory)) {
- if (mkdir(filename_directory, S_IRWXU)) {
+ if (nsmkdir(filename_directory, S_IRWXU)) {
LOG(("Failed to create directory '%s'",
filename_directory));
return NULL;
diff --git a/utils/useragent.c b/utils/useragent.c
index 48aa010b1..5b8c9e10f 100644
--- a/utils/useragent.c
+++ b/utils/useragent.c
@@ -17,10 +17,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <sys/utsname.h>
#include <stdio.h>
#include <stdlib.h>
+#include "utils/config.h"
+#include "utils/utsname.h"
#include "desktop/netsurf.h"
#include "utils/log.h"
#include "utils/useragent.h"
diff --git a/utils/utils.c b/utils/utils.c
index c8cfcb410..175b33073 100644
--- a/utils/utils.c
+++ b/utils/utils.c
@@ -463,3 +463,17 @@ char *strchrnul (const char *s, int c_in)
}
#endif
+
+#ifndef HAVE_UTSNAME
+#include "utils/utsname.h"
+
+int uname(struct utsname *buf) {
+ strcpy(buf->sysname,"windows");
+ strcpy(buf->nodename,"nodename");
+ strcpy(buf->release,"release");
+ strcpy(buf->version,"version");
+ strcpy(buf->machine,"pc");
+
+ return 0;
+}
+#endif
diff --git a/utils/utils.h b/utils/utils.h
index 74c01ec25..c6b07c6b6 100644
--- a/utils/utils.h
+++ b/utils/utils.h
@@ -72,6 +72,11 @@ typedef struct
void (*cancel)(query_id, enum query_response res, void *pw);
} query_callback;
+#ifdef HAVE_MKDIR
+#define nsmkdir(dir, mode) mkdir((dir), (mode))
+#else
+#define nsmkdir(dir, mode) mkdir((dir))
+#endif
char * strip(char * const s);
int whitespace(const char * str);
diff --git a/utils/utsname.h b/utils/utsname.h
new file mode 100644
index 000000000..cc267c6d3
--- /dev/null
+++ b/utils/utsname.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2010 Vincent Sanders <vince@kyllikki.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_UTILS_UTSNAME_H_
+#define _NETSURF_UTILS_UTSNAME_H_
+
+#ifdef HAVE_UTSNAME
+#include <sys/utsname.h>
+#else
+/* from posix spec */
+struct utsname {
+ char sysname[65]; /* Operating system name (e.g., "Linux") */
+ char nodename[65]; /* Name within "some implementation-defined
+ network" */
+ char release[65]; /* OS release (e.g., "2.6.28") */
+ char version[65]; /* OS version */
+ char machine[65]; /* Hardware identifier */
+};
+
+int uname(struct utsname *buf);
+
+#endif
+
+#endif
diff --git a/windows/NetSurfInstaller.nsi b/windows/NetSurfInstaller.nsi
new file mode 100644
index 000000000..65e58baa1
--- /dev/null
+++ b/windows/NetSurfInstaller.nsi
@@ -0,0 +1,95 @@
+; install script for nullsoft msi installer creation
+; debian package name nsis
+; paths may need adapting according to local settings
+; for release, would really need to compile source tree too
+Page license
+Page directory
+Page instfiles
+; install directory $INSTDIR = $PROGRAMFILES\NetSurf
+; install resources $PROGRAMFILES\NetSurf\res
+; install dlls $SYSDIR=%SystemRoot%\System[32]
+SetCompressor lzma
+InstallDir "$PROGRAMFILES\NetSurf"
+LicenseData ../COPYING ; \n -> \r\n
+Name NetSurf
+OutFile NetSurfInstall.exe
+Icon ../windows/res/NetSurf32.ico
+XPStyle on
+Section
+ SetShellVarContext all
+ SetOutPath $SYSDIR
+ File /usr/local/mingw/bin/libeay32.dll
+ File /usr/local/mingw/bin/libcurl-4.dll
+ File /usr/local/mingw/bin/libiconv-2.dll
+ File /usr/local/mingw/bin/ssleay32.dll
+ File /usr/local/mingw/bin/libgnurx-0.dll
+ File /usr/local/mingw/bin/libxml2-2.dll
+ File /usr/local/mingw/bin/libpng12.dll
+ File /usr/local/mingw/bin/libjpeg.dll
+ IfFileExists "$INSTDIR\*.*" +2
+ CreateDirectory "$INSTDIR"
+ SetOutPath $INSTDIR
+ File ../NetSurf.exe
+ IfFileExists "$INSTDIR\res\*.*" +2
+ CreateDirectory "$INSTDIR\res"
+ SetOutPath $INSTDIR\res
+ File ../windows/res/Aliases
+ File ../windows/res/default.css
+ File ../windows/res/quirks.css
+ File ../windows/res/messages
+ File ../windows/res/preferences
+ File ../windows/res/*.bmp
+ File ../windows/res/*.ico
+ File ../windows/res/throbber.avi
+ IfFileExists $SMPROGRAMS\NetSurf\NetSurf.lnk +2
+ CreateDirectory "$SMPROGRAMS\NetSurf"
+ CreateShortCut "$SMPROGRAMS\NetSurf\NetSurf.lnk" "$INSTDIR\NetSurf.exe" "" "$INSTDIR\res\NetSurf32.ico"
+ IfFileExists "$INSTDIR\src\*.*" +2
+ CreateDirectory "$INSTDIR\src"
+ SetOutPath "$INSTDIR\src"
+ File ../Makefile
+ File ../Makefile.config
+ File ../Makefile.config.example
+ File ../Makefile.defaults
+ File ../Makefile.sources
+ File ../Makefile.resources
+ IfFileExists "$INSTDIR\src\content\*.*" +2
+ CreateDirectory "$INSTDIR\src\content"
+ SetOutPath "$INSTDIR\src\content"
+ File /r /x .svn ../content/*.c
+ File /r /x .svn ../content/*.h
+ IfFileExists "$INSTDIR\src\css\*.*" +2
+ CreateDirectory "$INSTDIR\src\css"
+ SetOutPath "$INSTDIR\src\css"
+ File /r /x .svn ../css/*.c
+ File /r /x .svn ../css/*.h
+ IfFileExists "$INSTDIR\src\desktop\*.*" +2
+ CreateDirectory "$INSTDIR\src\desktop"
+ SetOutPath "$INSTDIR\src\desktop"
+ File /r /x .svn ../desktop/*.c
+ File /r /x .svn ../desktop/*.h
+ IfFileExists "$INSTDIR\src\image\*.*" +2
+ CreateDirectory "$INSTDIR\src\image"
+ SetOutPath "$INSTDIR\src\image"
+ File /r /x .svn ../image/*.c
+ File /r /x .svn ../image/*.h
+ IfFileExists "$INSTDIR\src\render\*.*" +2
+ CreateDirectory "$INSTDIR\src\render"
+ SetOutPath "$INSTDIR\src\render"
+ File /r /x .svn ../render/*.c
+ File /r /x .svn ../render/*.h
+ IfFileExists "$INSTDIR\src\utils\*.*" +2
+ CreateDirectory "$INSTDIR\src\utils"
+ SetOutPath "$INSTDIR\src\utils"
+ File /r /x .svn ../utils/*.c
+ File /r /x .svn ../utils/*.h
+ IfFileExists "$INSTDIR\src\windows\*.*" +2
+ CreateDirectory "$INSTDIR\src\windows"
+ SetOutPath "$INSTDIR\src\windows"
+ File /r /x .svn ../windows/*.c
+ File /r /x .svn ../windows/*.h
+ IfFileExists "$INSTDIR\src\Docs\*.*" +2
+ CreateDirectory "$INSTDIR\src\Docs"
+ SetOutPath "$INSTDIR\src\Docs"
+ File /r /x .svn ../Docs/*.*
+SectionEnd
diff --git a/windows/about.c b/windows/about.c
new file mode 100644
index 000000000..e73b270ce
--- /dev/null
+++ b/windows/about.c
@@ -0,0 +1,174 @@
+/*
+* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+*
+* This file is part of NetSurf, http://www.netsurf-browser.org/
+*
+* NetSurf is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; version 2 of the License.
+*
+* NetSurf is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <windows.h>
+#include <stdio.h>
+
+#include "utils/utils.h"
+#include "utils/messages.h"
+#include "desktop/netsurf.h"
+
+#include "windows/about.h"
+#include "windows/resourceid.h"
+
+const char *netsurf_authors[] = {
+ "John-Mark Bell", "James Bursa", "Michael Drake",
+ "Rob Kendrick", "Adrian Lees", "Vincent Sanders",
+ "Daniel Silverstone", "Richard Wilson",
+ "\nContributors:", "Kevin Bagust", "Stefaan Claes",
+ "Matthew Hambley", "Rob Jackson", "Jeffrey Lee", "Phil Mellor",
+ "Philip Pemberton", "Darren Salt", "Andrew Timmins",
+ "John Tytgat", "Chris Williams",
+ "\nGoogle Summer of Code Contributors:", "Mark Benjamin",
+ "Adam Blokus", "Paul Blokus", "Sean Fox", "Michael Lester",
+ "Andrew Sidwell", "Bo Yang", NULL
+};
+const char * const netsurf_translators = "Sebastian Barthel\n"
+ "Bruno D'Arcangeli\nGerard van Katwijk\nJérôme Mathevet\n"
+ "Simon Voortman.";
+const char *netsurf_artists[] = {
+ "Michael Drake", "\nContributors:", "Andrew Duffell",
+ "John Duffell", "Richard Hallas", "Phil Mellor", NULL
+};
+const char *netsurf_documenters[] = {
+ "John-Mark Bell", "James Bursa", "Michael Drake",
+ "Richard Wilson", "\nContributors:", "James Shaw", NULL
+};
+const char * const netsurf_name = "NetSurf";
+const char * const netsurf_description =
+ "Small as a mouse, fast as a cheetah, and available for free.\n"
+ "NetSurf is a portable web browser for RISC OS, AmigaOS, BeOS, "
+ "Windows and UNIX-like platforms.";
+const char * const netsurf_url = "http://www.netsurf-browser.org/";
+const char * const netsurf_url_label = "NetSurf Website";
+const char * const netsurf_copyright =
+ "Copyright © 2003 - 2009 The NetSurf Developers";
+
+BOOL CALLBACK nsws_about_event_callback(HWND hwnd, UINT msg, WPARAM wparam,
+ LPARAM lparam);
+
+BOOL CALLBACK nsws_about_event_callback(HWND hwnd, UINT msg, WPARAM wparam,
+ LPARAM lparam)
+{
+ switch(msg) {
+ case WM_INITDIALOG: {
+ HWND content = GetDlgItem(hwnd, NSWS_ID_ABOUT_CONTENT);
+ /* modify label NSWS_ID_ABOUT_CONTENT */
+ size_t len;
+ char *newcontent, *authors, *artists, *documenters;
+ int i;
+ for (i = 0, len = 0; netsurf_authors[i] != NULL; i++) {
+ len += strlen(netsurf_authors[i]) + 1;
+ }
+ authors = malloc(len + 1);
+ if (authors == NULL) {
+ warn_user(messages_get("NoMemory"), 0);
+ return FALSE;
+ }
+ authors[0] = '\0';
+ for (i = 0; netsurf_authors[i] != NULL; i++) {
+ strcat(authors, netsurf_authors[i]);
+ strcat(authors, " ");
+ }
+ for (i = 0, len = 0; netsurf_artists[i] != NULL; i++) {
+ len += strlen(netsurf_artists[i]) + 1;
+ }
+ artists = malloc(len + 1);
+ if (artists == NULL) {
+ warn_user(messages_get("NoMemory"), 0);
+ free(authors);
+ return FALSE;
+ }
+ artists[0] = '\0';
+ for (i = 0; netsurf_artists[i] != NULL; i++) {
+ strcat(artists, netsurf_artists[i]);
+ strcat(artists, " ");
+ }
+ for (i = 0, len = 0; netsurf_documenters[i] != NULL; i++) {
+ len += strlen(netsurf_documenters[i]) + 1;
+ }
+ documenters = malloc(len + 1);
+ if (documenters == NULL) {
+ warn_user(messages_get("NoMemory"), 0);
+ free(authors);
+ free(artists);
+ return FALSE;
+ }
+ documenters[0] = '\0';
+ for (i = 0; netsurf_documenters[i] != NULL; i++) {
+ strcat(documenters, netsurf_documenters[i]);
+ strcat(documenters, " ");
+ }
+ len = strlen(netsurf_name) + 1 + strlen(netsurf_version) +
+ 2 + strlen(netsurf_description) + 2 +
+ strlen(netsurf_url) + 2 +
+ strlen(netsurf_copyright) + 2 +
+ strlen(netsurf_translators) + 2 +
+ strlen(authors) + 2 + strlen(artists) + 2 +
+ strlen(documenters) + 2 + SLEN("authors:") + 2 +
+ SLEN("artists:") + 2 + SLEN("documenters:") + 2 +
+ SLEN("translators:") + 2;
+ newcontent = malloc(len + 1);
+ if (newcontent == NULL) {
+ warn_user(messages_get("NoMemory"), 0);
+ free(authors);
+ free(artists);
+ free(documenters);
+ return FALSE;
+ }
+ sprintf(newcontent, "%s %s\n\n%s\n\nauthors:\n\n%s\n\n"
+ "artists:\n\n%s\n\ndocumenters:\n\n%s\n\n"
+ "translators:\n\n%s\n\n%s\n\n%s\n",
+ netsurf_name, netsurf_version,
+ netsurf_description, authors, artists,
+ documenters, netsurf_translators, netsurf_url,
+ netsurf_copyright);
+ SendMessage(content, WM_SETTEXT, 0, (LPARAM)newcontent);
+ free(authors);
+ free(artists);
+ free(documenters);
+ free(newcontent);
+
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch(LOWORD(wparam)) {
+ case IDOK:
+ EndDialog(hwnd, IDOK);
+ break;
+ default:
+ return FALSE;
+ }
+ break;
+ case WM_CREATE:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void nsws_about_dialog_init(HINSTANCE hinst, HWND parent)
+{
+ int ret = DialogBox(hinst, MAKEINTRESOURCE(NSWS_ID_ABOUT_DIALOG), parent,
+ nsws_about_event_callback);
+ if (ret == -1) {
+ warn_user(messages_get("NoMemory"), 0);
+ return;
+ }
+}
diff --git a/windows/about.h b/windows/about.h
new file mode 100644
index 000000000..e0315b507
--- /dev/null
+++ b/windows/about.h
@@ -0,0 +1,24 @@
+/*
+* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+*
+* This file is part of NetSurf, http://www.netsurf-browser.org/
+*
+* NetSurf is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; version 2 of the License.
+*
+* NetSurf is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _NETSURF_WINDOWS_ABOUT_H_
+#define _NETSURF_WINDOWS_ABOUT_H_
+
+void nsws_about_dialog_init(HINSTANCE hinst, HWND parent);
+
+#endif
diff --git a/windows/bitmap.c b/windows/bitmap.c
new file mode 100644
index 000000000..74c104963
--- /dev/null
+++ b/windows/bitmap.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <inttypes.h>
+#include <sys/types.h>
+
+#include "assert.h"
+#include "image/bitmap.h"
+#include "windows/bitmap.h"
+
+#include "utils/log.h"
+
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+/**
+ * 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 *bitmap_create(int width, int height, unsigned int state)
+{
+ struct bitmap *bitmap;
+ LOG(("width %d, height %d, state %u",width,height,state));
+ bitmap = calloc(1 , sizeof(struct bitmap));
+ if (bitmap) {
+ bitmap->pixdata = calloc(width * height, 4);
+ if (bitmap->pixdata != NULL) {
+ bitmap->width = width;
+ bitmap->height = height;
+ bitmap->opaque = false;
+ } else {
+ free(bitmap);
+ bitmap=NULL;
+ }
+ }
+
+ LOG(("bitmap %p", bitmap));
+
+ return bitmap;
+}
+
+
+/**
+ * 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 *bitmap_get_buffer(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+ if (bitmap == NULL) {
+ LOG(("NULL bitmap!"));
+ return NULL;
+ }
+
+ return bm->pixdata;
+}
+
+
+/**
+ * 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 bitmap_get_rowstride(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG(("NULL bitmap!"));
+ return 0;
+ }
+
+ return (bm->width) * 4;
+}
+
+
+/**
+ * Free a bitmap.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+
+void bitmap_destroy(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG(("NULL bitmap!"));
+ return;
+ }
+
+ free(bm->pixdata);
+ free(bm);
+}
+
+
+/**
+ * Save a bitmap in the platform's native format.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \param path pathname for file
+ * \return true on success, false on error and error reported
+ */
+
+bool bitmap_save(void *bitmap, const char *path, unsigned flags)
+{
+ return true;
+}
+
+
+/**
+ * The bitmap image has changed, so flush any persistant cache.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+void bitmap_modified(void *bitmap) {
+}
+
+
+/**
+ * The bitmap image can be suspended.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ * \param private_word a private word to be returned later
+ * \param suspend the function to be called upon suspension
+ * \param resume the function to be called when resuming
+ */
+void bitmap_set_suspendable(void *bitmap, void *private_word,
+ void (*invalidate)(void *bitmap, void *private_word)) {
+}
+
+/**
+ * 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 bitmap_set_opaque(void *bitmap, bool opaque)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG(("NULL bitmap!"));
+ return;
+ }
+
+ LOG(("setting bitmap %p to %s", bm, opaque?"opaque":"transparent"));
+ bm->opaque = 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 bitmap_test_opaque(void *bitmap)
+{
+ int tst;
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG(("NULL bitmap!"));
+ return false;
+ }
+
+ tst = bm->width * bm->height;
+
+ while (tst-- > 0) {
+ if (bm->pixdata[(tst << 2) + 3] != 0xff) {
+ LOG(("bitmap %p has transparency",bm));
+ return false;
+ }
+ }
+ LOG(("bitmap %p is opaque", bm));
+ return true;
+}
+
+
+/**
+ * Gets whether a bitmap should be plotted opaque
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+bool bitmap_get_opaque(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG(("NULL bitmap!"));
+ return false;
+ }
+
+ return bm->opaque;
+}
+
+int bitmap_get_width(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG(("NULL bitmap!"));
+ return 0;
+ }
+
+ return(bm->width);
+}
+
+int bitmap_get_height(void *bitmap)
+{
+ struct bitmap *bm = bitmap;
+
+ if (bitmap == NULL) {
+ LOG(("NULL bitmap!"));
+ return 0;
+ }
+
+ return(bm->height);
+}
+
+size_t bitmap_get_bpp(void *bitmap)
+{
+ return 4;
+}
+
+struct bitmap *bitmap_scale(struct bitmap *prescale, int width, int height)
+{
+ struct bitmap *ret = malloc(sizeof(struct bitmap));
+ int i, ii, v, vv;
+ uint32_t *retpixdata, *inpixdata; /* 4 byte types for quicker
+ * transfer */
+ if (ret == NULL)
+ return NULL;
+ retpixdata = malloc(width * height * 4);
+ if (retpixdata == NULL) {
+ free(ret);
+ return NULL;
+ }
+ inpixdata = (uint32_t *)prescale->pixdata;
+ ret->pixdata = (uint8_t *)retpixdata;
+ ret->height = height;
+ ret->width = width;
+ for (i = 0; i < height; i++) {
+ v = i * width;
+ vv = (int)((i * prescale->height) / height) * prescale->width;
+ for (ii = 0; ii < width; ii++) {
+ retpixdata[v + ii] = inpixdata[vv + (int)
+ ((ii * prescale->width) / width)];
+ }
+ }
+ return ret;
+
+}
+
+struct bitmap *bitmap_pretile(struct bitmap *untiled, int width, int height,
+ bitmap_flags_t flags)
+{
+ struct bitmap *ret = malloc(sizeof(struct bitmap));
+ if (ret == NULL)
+ return NULL;
+ int i, hrepeat, vrepeat, repeat;
+ vrepeat = ((flags & BITMAPF_REPEAT_Y) != 0) ?
+ ((height + untiled->height - 1) / untiled->height) : 1;
+ hrepeat = ((flags & BITMAPF_REPEAT_X) != 0) ?
+ ((width + untiled->width - 1) / untiled->width) : 1;
+ width = untiled->width * hrepeat;
+ height = untiled->height * vrepeat;
+ uint8_t *indata = untiled->pixdata;
+ uint8_t *newdata = malloc(4 * width * height);
+ if (newdata == NULL) {
+ free(ret);
+ return NULL;
+ }
+ ret->pixdata = newdata;
+ size_t stride = untiled->width * 4;
+
+ /* horizontal tiling */
+ for (i = 0; i < untiled->height; i++) {
+ for (repeat = 0; repeat < hrepeat; repeat ++) {
+ memcpy(newdata, indata, stride);
+ newdata += stride;
+ }
+ indata += stride;
+ }
+
+ /* vertical tiling */
+ stride = untiled->height * width * 4;
+ newdata = ret->pixdata + stride;
+ indata = ret->pixdata;
+
+ for (repeat = 1; repeat < vrepeat; repeat++) {
+ memcpy(newdata, indata, stride);
+ newdata += stride;
+ }
+ ret->width = width;
+ ret->height = height;
+ return ret;
+}
diff --git a/windows/bitmap.h b/windows/bitmap.h
new file mode 100644
index 000000000..991ce7210
--- /dev/null
+++ b/windows/bitmap.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_WINDOWS_BITMAP_H_
+#define _NETSURF_WINDOWS_BITMAP_H_
+
+#include "desktop/plotters.h"
+
+struct bitmap {
+ int width;
+ int height;
+ uint8_t *pixdata;
+ bool opaque;
+};
+
+struct bitmap *bitmap_scale(struct bitmap *prescale, int width, int height);
+struct bitmap *bitmap_pretile(struct bitmap *untiled, int width, int height,
+ bitmap_flags_t flags);
+
+#endif
diff --git a/windows/download.c b/windows/download.c
new file mode 100644
index 000000000..8e5b1a2e7
--- /dev/null
+++ b/windows/download.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <limits.h>
+#define _WIN32_IE 0x0500
+#include <windows.h>
+#include <shlobj.h>
+#include <sys/time.h>
+
+#include "content/fetch.h"
+#include "desktop/gui.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/url.h"
+#include "utils/utils.h"
+#include "windows/download.h"
+#include "windows/gui.h"
+#include "windows/resourceid.h"
+
+static bool downloading = false;
+static struct gui_download_window *download1;
+
+static bool nsws_download_window_up(struct gui_download_window *w);
+BOOL CALLBACK nsws_download_event_callback(HWND hwnd, UINT msg, WPARAM wparam,
+ LPARAM lparam);
+static void nsws_download_update_label(void *p);
+static void nsws_download_update_progress(void *p);
+static void nsws_download_clear_data(struct gui_download_window *w);
+
+struct gui_download_window *gui_download_window_create(const char *url,
+ const char *mime_type, struct fetch *fetch,
+ unsigned int total_size, struct gui_window *gui)
+{
+ if (downloading) {
+ /* initial implementation */
+ warn_user("1 download at a time please", 0);
+ return NULL;
+ }
+ downloading = true;
+ struct gui_download_window *w =
+ malloc(sizeof(struct gui_download_window));
+ if (w == NULL) {
+ warn_user(messages_get("NoMemory"), 0);
+ return NULL;
+ }
+ char *domain, *filename, *destination;
+ bool unknown_size = (total_size == 0);
+ const char *size = (unknown_size) ?
+ messages_get("UnknownSize") :
+ human_friendly_bytesize(total_size);
+
+ if (url_nice(url, &filename, false) != URL_FUNC_OK)
+ filename = strdup(messages_get("UnknownFile"));
+ if (filename == NULL) {
+ warn_user(messages_get("NoMemory"), 0);
+ free(w);
+ return NULL;
+ }
+ if (url_host(url, &domain) != URL_FUNC_OK)
+ domain = strdup(messages_get("UnknownHost"));
+ if (domain == NULL) {
+ warn_user(messages_get("NoMemory"), 0);
+ free(filename);
+ free(w);
+ return NULL;
+ }
+ destination = malloc(PATH_MAX);
+ if (destination == NULL) {
+ warn_user(messages_get("NoMemory"), 0);
+ free(domain);
+ free(filename);
+ free(w);
+ return NULL;
+ }
+ SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, SHGFP_TYPE_CURRENT,
+ destination);
+ if (strlen(destination) < PATH_MAX - 2)
+ strcat(destination, "/");
+ if (strlen(destination) + strlen(filename) < PATH_MAX - 1)
+ strcat(destination, filename);
+ LOG(("download %s [%s] from %s to %s", filename, size, domain,
+ destination));
+ w->fetch = fetch;
+ w->title = filename;
+ w->domain = domain;
+ w->size = total_size;
+ w->total_size = strdup(size);
+ if (w->total_size == NULL) {
+ warn_user(messages_get("NoMemory"), 0);
+ free(destination);
+ free(domain);
+ free(filename);
+ free(w);
+ return NULL;
+ }
+ w->downloaded = 0;
+ w->speed = 0;
+ gettimeofday(&(w->start_time), NULL);
+ w->time_remaining = -1;
+ w->time_left = NULL;
+ w->status = DOWNLOAD_NONE;
+ w->filename = destination;
+ w->progress = 0;
+ w->error = 0;
+ w->window = gui;
+ w->file = fopen(destination, "wb");
+ if (w->file == NULL) {
+ warn_user(messages_get("FileOpenWriteError"), destination);
+ free(destination);
+ free(domain);
+ free(filename);
+ free(w->total_size);
+ free(w->time_left);
+ free(w);
+ return NULL;
+ }
+ download1 = w;
+
+ nsws_download_window_up(w);
+ return w;
+}
+
+bool nsws_download_window_up(struct gui_download_window *w)
+{
+ w->hwnd = CreateDialog(hinstance, MAKEINTRESOURCE(
+ NSWS_ID_DOWNLOAD_DIALOG),
+ gui_window_main_window(w->window),
+ nsws_download_event_callback);
+ if (w->hwnd == NULL) {
+ warn_user(messages_get("NoMemory"), 0);
+ return false;
+ }
+ ShowWindow(w->hwnd, SW_SHOW);
+ return true;
+}
+
+BOOL CALLBACK nsws_download_event_callback(HWND hwnd, UINT msg, WPARAM wparam,
+ LPARAM lparam)
+{
+ HWND sub;
+ switch(msg){
+ case WM_INITDIALOG:
+ sub = GetDlgItem(hwnd, NSWS_ID_DOWNLOAD_LABEL);
+ nsws_download_update_label((void *)download1);
+ nsws_download_update_progress((void *)download1);
+ return TRUE;
+ case WM_COMMAND:
+ switch(LOWORD(wparam)) {
+ case IDOK:
+ if (download1->downloaded != download1->size)
+ return TRUE;
+ case IDCANCEL:
+ nsws_download_clear_data(download1);
+ download1 = NULL;
+ downloading = false;
+ EndDialog(hwnd, IDCANCEL);
+ return FALSE;
+ }
+ }
+ return FALSE;
+}
+
+void nsws_download_update_label(void *p)
+{
+ struct gui_download_window *w = p;
+ if (w->hwnd == NULL) {
+ schedule_remove(nsws_download_update_label, p);
+ return;
+ }
+ HWND sub = GetDlgItem(w->hwnd, NSWS_ID_DOWNLOAD_LABEL);
+ char *size = human_friendly_bytesize(w->downloaded);
+ int i = 0, temp = w->time_remaining;
+ if (temp == -1) {
+ w->time_left = strdup(messages_get("UnknownSize"));
+ i = strlen(w->time_left);
+ } else {
+ do {
+ temp = temp / 10;
+ i++;
+ } while (temp > 2);
+ w->time_left = malloc(i + SLEN(" s") + 1);
+ if (w->time_left != NULL) {
+ if (w->time_remaining > 3600)
+ sprintf(w->time_left, "%d h",
+ w->time_remaining / 3600);
+ else if (w->time_remaining > 60)
+ sprintf(w->time_left, "%d m",
+ w->time_remaining / 60);
+ else
+ sprintf(w->time_left, "%d s",
+ w->time_remaining);
+ }
+ }
+ char label[strlen(w->title) + strlen(size) + strlen(w->total_size) +
+ + strlen(w->domain) + strlen(w->filename) +
+ SLEN("download from to \n[\t/\t]\n estimate of time"
+ " remaining ") + i + 1];
+ sprintf(label, "download %s from %s to %s\n[%s\t/\t%s] [%d%%]\n"
+ "estimate of time remaining %s", w->title, w->domain,
+ w->filename, size, w->total_size, w->progress / 100,
+ w->time_left);
+ if (w->time_left != NULL) {
+ free(w->time_left);
+ w->time_left = NULL;
+ }
+ SendMessage(sub, WM_SETTEXT, (WPARAM)0, (LPARAM)label);
+ if (w->progress < 10000)
+ schedule(50, nsws_download_update_label, p);
+}
+
+void nsws_download_update_progress(void *p)
+{
+ struct gui_download_window *w = p;
+ if (w->hwnd == NULL) {
+ schedule_remove(nsws_download_update_progress, p);
+ return;
+ }
+ HWND sub = GetDlgItem(w->hwnd, NSWS_ID_DOWNLOAD_PROGRESS);
+ SendMessage(sub, PBM_SETPOS, (WPARAM)(w->progress / 100), 0);
+ if (w->progress < 10000)
+ schedule(50, nsws_download_update_progress, p);
+}
+
+void nsws_download_clear_data(struct gui_download_window *w)
+{
+ if (w == NULL)
+ return;
+ if (w->title != NULL)
+ free(w->title);
+ if (w->filename != NULL)
+ free(w->filename);
+ if (w->domain != NULL)
+ free(w->domain);
+ if (w->time_left != NULL)
+ free(w->time_left);
+ if (w->total_size != NULL)
+ free(w->total_size);
+ if (w->file != NULL)
+ fclose(w->file);
+ schedule_remove(nsws_download_update_progress, (void *)w);
+ schedule_remove(nsws_download_update_label, (void *)w);
+}
+
+
+void gui_download_window_data(struct gui_download_window *w, const char *data,
+ unsigned int size)
+{
+ if ((w == NULL) || (w->file == NULL))
+ return;
+ size_t res;
+ struct timeval val;
+ res = fwrite((void *)data, 1, size, w->file);
+ if (res != size)
+ LOG(("file write error %d of %d", size - res, size));
+ w->downloaded += res;
+ w->progress = (unsigned int)(((long long)(w->downloaded) * 10000)
+ / w->size);
+ gettimeofday(&val, NULL);
+ w->time_remaining = (w->progress == 0) ? -1 :
+ (int)((val.tv_sec - w->start_time.tv_sec) *
+ (10000 - w->progress) / w->progress);
+}
+
+void gui_download_window_error(struct gui_download_window *w,
+ const char *error_msg)
+{
+ LOG(("error %s", error_msg));
+}
+
+void gui_download_window_done(struct gui_download_window *w)
+{
+ if (w == NULL)
+ return;
+ downloading = false;
+ if (w->hwnd != NULL)
+ EndDialog(w->hwnd, IDOK);
+ nsws_download_clear_data(w);
+}
+
diff --git a/windows/download.h b/windows/download.h
new file mode 100644
index 000000000..c259aac2e
--- /dev/null
+++ b/windows/download.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_WINDOWS_DOWNLOAD_H_
+#define _NETSURF_WINDOWS_DOWNLOAD_H_
+
+#include <time.h>
+#include <windows.h>
+#include "desktop/gui.h"
+
+typedef enum {
+ DOWNLOAD_NONE,
+ DOWNLOAD_WORKING,
+ DOWNLOAD_ERROR,
+ DOWNLOAD_COMPLETE,
+ DOWNLOAD_CANCELED
+} download_status;
+
+typedef enum {
+ DOWNLOAD_PAUSE = 1 << 0,
+ DOWNLOAD_RESUME = 1 << 1,
+ DOWNLOAD_CANCEL = 1 << 2,
+ DOWNLOAD_CLEAR = 1 << 3
+} download_actions;
+
+struct gui_download_window {
+ HWND hwnd;
+ char *title;
+ char *filename;
+ char *domain;
+ char *time_left;
+ char *total_size;
+ char *original_total_size;
+ int size;
+ int downloaded;
+ unsigned int progress;
+ int time_remaining;
+ struct timeval start_time;
+ int speed;
+ int error;
+ struct fetch *fetch;
+ struct gui_window *window;
+ FILE *file;
+ download_status status;
+};
+
+void nsws_download_window_init(struct gui_window *);
+
+#endif
diff --git a/windows/filetype.c b/windows/filetype.c
new file mode 100644
index 000000000..7ad862b8b
--- /dev/null
+++ b/windows/filetype.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2003 James Bursa <bursa@users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "content/fetch.h"
+#include "utils/log.h"
+#include "utils/utils.h"
+
+/**
+ * filetype -- determine the MIME type of a local file
+ */
+
+const char *fetch_filetype(const char *unix_path)
+{
+ int l;
+ LOG(("unix path %s", unix_path));
+ l = strlen(unix_path);
+ if (2 < l && strcasecmp(unix_path + l - 3, "css") == 0)
+ return "text/css";
+ if (2 < l && strcasecmp(unix_path + l - 3, "jpg") == 0)
+ return "image/jpeg";
+ if (3 < l && strcasecmp(unix_path + l - 4, "jpeg") == 0)
+ return "image/jpeg";
+ if (2 < l && strcasecmp(unix_path + l - 3, "gif") == 0)
+ return "image/gif";
+ if (2 < l && strcasecmp(unix_path + l - 3, "png") == 0)
+ return "image/png";
+ if (2 < l && strcasecmp(unix_path + l - 3, "jng") == 0)
+ return "image/jng";
+ if (2 < l && strcasecmp(unix_path + l - 3, "svg") == 0)
+ return "image/svg";
+ if (2 < l && strcasecmp(unix_path + l - 3, "bmp") == 0)
+ return "image/x-ms-bmp";
+ return "text/html";
+}
+
+
+char *fetch_mimetype(const char *ro_path)
+{
+ return strdup("text/plain");
+}
diff --git a/windows/findfile.c b/windows/findfile.c
new file mode 100644
index 000000000..f47e49d03
--- /dev/null
+++ b/windows/findfile.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2008 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <limits.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils/log.h"
+#include "utils/utils.h"
+
+#include "windows/findfile.h"
+
+static char *realpath(const char *path, char *resolved_path)
+{
+ /* useless, but there we go */
+ return strncpy(resolved_path, path, PATH_MAX);
+}
+
+char *path_to_url(const char *path)
+{
+ char *r = malloc(strlen(path) + 7 + 1);
+
+ strcpy(r, "file://");
+ strcat(r, path);
+
+ return r;
+}
+
+/**
+ * Locate a shared resource file by searching known places in order.
+ *
+ * \param buf buffer to write to. must be at least PATH_MAX chars
+ * \param filename file to look for
+ * \param def default to return if file not found
+ * \return buf
+ *
+ * Search order is: ~/.netsurf/, $NETSURFRES/ (where NETSURFRES is an
+ * environment variable), then the path specified in
+ NETSURF_WINDOWS_RESPATH in the Makefile then .\res\ [windows paths]
+ */
+
+char *nsws_find_resource(char *buf, const char *filename, const char *def)
+{
+ char *cdir = getenv("HOME");
+ char t[PATH_MAX];
+
+ if (cdir != NULL) {
+ LOG(("Found Home %s", cdir));
+ strcpy(t, cdir);
+ strcat(t, "/.netsurf/");
+ strcat(t, filename);
+ if ((realpath(t, buf) != NULL) && (access(buf, R_OK) == 0))
+ return buf;
+ }
+
+ cdir = getenv("NETSURFRES");
+
+ if (cdir != NULL) {
+ if (realpath(cdir , buf) != NULL) {
+ strcat(buf, "/");
+ strcat(buf, filename);
+ if (access(buf, R_OK) == 0)
+ return buf;
+ }
+ }
+
+ strcpy(t, NETSURF_WINDOWS_RESPATH);
+ strcat(t, filename);
+ if ((realpath(t, buf) != NULL) && (access(buf, R_OK) == 0))
+ return buf;
+
+ getcwd(t, PATH_MAX - SLEN("\\res\\") - strlen(filename));
+ strcat(t, "\\res\\");
+ strcat(t, filename);
+ LOG(("looking in %s", t));
+ if ((realpath(t, buf) != NULL) && (access(buf, R_OK) == 0))
+ return buf;
+
+ if (def[0] == '~') {
+ snprintf(t, PATH_MAX, "%s%s", getenv("HOME"), def + 1);
+ if (realpath(t, buf) == NULL) {
+ strcpy(buf, t);
+ }
+ } else {
+ if (realpath(def, buf) == NULL) {
+ strcpy(buf, def);
+ }
+ }
+
+ return buf;
+}
+
+
+/*
+ * Local Variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
diff --git a/windows/findfile.h b/windows/findfile.h
new file mode 100644
index 000000000..f9b6746da
--- /dev/null
+++ b/windows/findfile.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2008 Daniel Silverstone <dsilvers@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_WINDOWS_FINDFILE_H_
+#define _NETSURF_WINDOWS_FINDFILE_H_
+
+#define NETSURF_WINDOWS_RESPATH "C:"
+
+char *path_to_url(const char *path);
+
+extern char *nsws_find_resource(char *buf, const char *filename,
+ const char *def);
+
+#endif /* _NETSURF_WINDOWS_FINDFILE_H_ */
diff --git a/windows/font.c b/windows/font.c
new file mode 100644
index 000000000..1857652e9
--- /dev/null
+++ b/windows/font.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <inttypes.h>
+
+#include <assert.h>
+#include <windows.h>
+#include "css/css.h"
+#include "render/font.h"
+#include "desktop/options.h"
+#include "utils/utf8.h"
+
+#include "windows/font.h"
+#include "windows/gui.h"
+#include "windows/plot.h"
+
+#define NSWS_FONT_SCALE_HEIGHT 1.3
+#define NSWS_FONT_SCALE_WIDTH 0.45
+
+utf8_convert_ret utf8_to_font_encoding(const struct font_desc* font,
+ const char *string,
+ size_t len,
+ char **result)
+{
+ return utf8_to_enc(string, font->encoding, len, result);
+}
+
+utf8_convert_ret utf8_to_local_encoding(const char *string,
+ size_t len,
+ char **result)
+{
+ return utf8_to_enc(string, "UCS-2", len, result);
+}
+
+HFONT get_font(const plot_font_style_t *style)
+{
+ char *face = NULL;
+ DWORD family;
+ switch(style->family) {
+ case PLOT_FONT_FAMILY_SERIF:
+ face = strdup(option_font_serif);
+ family = FF_ROMAN | DEFAULT_PITCH;
+ break;
+ case PLOT_FONT_FAMILY_MONOSPACE:
+ face = strdup(option_font_mono);
+ family = FF_MODERN | DEFAULT_PITCH;
+ break;
+ case PLOT_FONT_FAMILY_CURSIVE:
+ face = strdup(option_font_cursive);
+ family = FF_SCRIPT | DEFAULT_PITCH;
+ break;
+ case PLOT_FONT_FAMILY_FANTASY:
+ face = strdup(option_font_fantasy);
+ family = FF_DECORATIVE | DEFAULT_PITCH;
+ break;
+ case PLOT_FONT_FAMILY_SANS_SERIF:
+ default:
+ face = strdup(option_font_sans);
+ family = FF_SWISS | DEFAULT_PITCH;
+ break;
+ }
+
+ HFONT font = CreateFont((int)((((float)style->size) *
+ NSWS_FONT_SCALE_HEIGHT * nsws_plot_get_scale())
+ / FONT_SIZE_SCALE), /* height */
+ (int)((((float)style->size) *
+ NSWS_FONT_SCALE_WIDTH * nsws_plot_get_scale())
+ / FONT_SIZE_SCALE), /* width */
+ 0, /* escapement*/
+ 0, /* orientation */
+ style->weight,
+ (style->flags & FONTF_ITALIC) ? TRUE : FALSE,
+ FALSE, /* underline */
+ FALSE, /* strike */
+ DEFAULT_CHARSET, /* for locale */
+ OUT_DEFAULT_PRECIS, /* general 'best match' */
+ CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,
+ family,
+ face /* name of font face */
+ );
+ if (face != NULL)
+ free(face);
+ if (font == NULL) {
+ if (style->family == PLOT_FONT_FAMILY_MONOSPACE)
+ font = (HFONT) GetStockObject(ANSI_FIXED_FONT);
+ else
+ font = (HFONT) GetStockObject(ANSI_VAR_FONT);
+ }
+ if (font == NULL)
+ font = (HFONT) GetStockObject(SYSTEM_FONT);
+ return font;
+}
+
+static bool nsfont_width(const plot_font_style_t *style,
+ const char *string, size_t length,
+ int *width)
+{
+ HDC hdc = GetDC(NULL);
+ HFONT font = get_font(style);
+ HFONT fontbak = SelectObject(hdc, font);
+ SIZE s;
+ if (length < 8192) { /* win 95/98/ME */
+ /* may well need to convert utf-8 to lpctstr */
+ GetTextExtentPoint32(hdc, string,
+ utf8_bounded_length(string, length), &s);
+ *width = s.cx;
+ font = SelectObject(hdc, fontbak);
+ DeleteObject(font);
+ ReleaseDC(NULL, hdc);
+ return true;
+ }
+ font = SelectObject(hdc, fontbak);
+ DeleteObject(font);
+ ReleaseDC(NULL, hdc);
+ return false;
+}
+
+/**
+ * Find the position in a string where an x coordinate falls.
+ *
+ * \param style css_style for this text, with style->font_size.size ==
+ * CSS_FONT_SIZE_LENGTH
+ * \param string UTF-8 string to measure
+ * \param length length of string
+ * \param x x coordinate to search for
+ * \param char_offset updated to offset in string of actual_x, [0..length]
+ * \param actual_x updated to x coordinate of character closest to x
+ * \return true on success, false on error and error reported
+ */
+
+static bool nsfont_position_in_string(const plot_font_style_t *style,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x)
+{
+ HDC hdc = GetDC(NULL);
+ HFONT font = get_font(style);
+ HFONT fontbak = SelectObject(hdc, font);
+ SIZE s;
+ int offset;
+ GetTextExtentExPoint(hdc, string, length, x, &offset, NULL, &s);
+ *char_offset = (size_t)offset;
+ nsfont_width(style, string, *char_offset, actual_x);
+
+ font = SelectObject(hdc, fontbak);
+ DeleteObject(font);
+ ReleaseDC(NULL, hdc);
+
+ return true;
+}
+
+
+/**
+ * Find where to split a string to make it fit a width.
+ *
+ * \param style css_style for this text, with style->font_size.size ==
+ * CSS_FONT_SIZE_LENGTH
+ * \param string UTF-8 string to measure
+ * \param length length of string
+ * \param x width available
+ * \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
+ *
+ * On exit, [char_offset == 0 ||
+ * string[char_offset] == ' ' ||
+ * char_offset == length]
+ */
+
+static bool nsfont_split(const plot_font_style_t *style,
+ const char *string, size_t length,
+ int x, size_t *char_offset, int *actual_x)
+{
+ nsfont_position_in_string(style, string, length, x, char_offset,
+ actual_x);
+ if (*char_offset == length) {
+ printf("%s %d\n",string, (int)(*char_offset));
+ return true;
+ }
+ while ((string[*char_offset] != ' ') && (*char_offset > 0))
+ (*char_offset)--;
+ nsfont_position_in_string(style, string, *char_offset, x, char_offset,
+ actual_x);
+ return true;
+}
+
+const struct font_functions nsfont = {
+ nsfont_width,
+ nsfont_position_in_string,
+ nsfont_split
+};
diff --git a/windows/font.h b/windows/font.h
new file mode 100644
index 000000000..4bd100f6a
--- /dev/null
+++ b/windows/font.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_WINDOWS_FONT_H_
+#define _NETSURF_WINDOWS_FONT_H_
+
+#include <windows.h>
+#include "utils/utf8.h"
+
+struct font_desc {
+ const char *name;
+ int width, height;
+ const char *encoding;
+};
+
+extern utf8_convert_ret utf8_to_font_encoding(const struct font_desc* font,
+ const char *string,
+ size_t len,
+ char **result);
+
+HFONT get_font(const plot_font_style_t *style);
+
+#endif /* NETSURF_WINDOWS_FONT_H */
+
diff --git a/windows/gui.c b/windows/gui.c
new file mode 100644
index 000000000..3eeb9fbfa
--- /dev/null
+++ b/windows/gui.c
@@ -0,0 +1,2402 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <windows.h>
+#include <windowsx.h>
+#define _WIN32_IE (0x0501)
+#include <commctrl.h>
+
+#include <hubbub/hubbub.h>
+
+#include "content/urldb.h"
+#include "content/fetch.h"
+#include "css/utils.h"
+#include "desktop/gui.h"
+#include "desktop/history_core.h"
+#include "desktop/plotters.h"
+#include "desktop/netsurf.h"
+#include "desktop/options.h"
+#include "desktop/save_complete.h"
+#include "desktop/selection.h"
+#include "desktop/textinput.h"
+#include "render/html.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+
+#include "windows/about.h"
+#include "windows/gui.h"
+#include "windows/findfile.h"
+#include "windows/font.h"
+#include "windows/localhistory.h"
+#include "windows/plot.h"
+#include "windows/prefs.h"
+#include "windows/resourceid.h"
+
+char *default_stylesheet_url;
+char *adblock_stylesheet_url;
+char *quirks_stylesheet_url;
+char *options_file_location;
+
+struct gui_window *input_window = NULL;
+struct gui_window *search_current_window;
+struct gui_window *window_list = NULL;
+
+FARPROC urlproc;
+FARPROC toolproc;
+
+static char default_page[] = "http://www.netsurf-browser.org/welcome/";
+static HICON hIcon, hIconS;
+static int open_windows = 0;
+
+#define NTOOLBUTTONS 5
+#define NSWS_THROBBER_WIDTH 24
+#define NSWS_URL_ENTER (WM_USER)
+
+struct gui_window {
+ /* The front's private data connected to a browser window */
+ /* currently 1<->1 gui_window<->windows window [non-tabbed] */
+ struct browser_window *bw; /** the browser_window */
+ HWND main; /**< handle to the actual window */
+ HWND toolbar; /**< toolbar handle */
+ HWND urlbar; /**< url bar handle */
+ HWND throbber; /** throbber handle */
+ HWND drawingarea; /**< drawing area handle */
+ HWND statusbar; /**< status bar handle */
+ HWND vscroll; /**< vertical scrollbar handle */
+ HWND hscroll; /**< horizontal scrollbar handle */
+ HMENU mainmenu; /**< the main menu */
+ HMENU rclick; /**< the right-click menu */
+ HDC bufferdc; /**< the screen buffer */
+ HBITMAP bufferbm; /**< the buffer bitmap */
+ struct nsws_localhistory *localhistory; /**< handle to local history window */
+ int width; /**< width of window */
+ int height; /**< height of drawing area */
+ int urlbarwidth; /**< width of url bar */
+ int ntoolbuttons; /**< number of toolbar buttons */
+ int toolbuttondimension; /**< width, height of buttons */
+ int voffset; /**< height of toolbar */
+ bool throbbing; /**< whether currently throbbing */
+ TBBUTTON buttons[NTOOLBUTTONS + 1]; /* 1 = url bar */
+ HBITMAP hbmp[NTOOLBUTTONS]; /**< tool button images */
+
+ struct browser_mouse *mouse; /**< mouse state */
+
+ HACCEL acceltable; /**< accelerators */
+
+ float scale; /**< scale of content */
+
+ int scrollx; /**< current scroll location */
+ int scrolly; /**< current scroll location */
+
+ RECT *fullscreen; /**< memorize non-fullscreen area */
+ RECT redraw; /**< Area needing redraw. */
+ RECT clip; /**< current clip rectangle */
+ int requestscrollx, requestscrolly; /**< scolling requested. */
+ struct gui_window *next, *prev; /**< global linked list */
+};
+
+static struct nsws_pointers nsws_pointer;
+
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+typedef enum {
+ NSWS_ID_TOOLBAR = 1111,
+ NSWS_ID_URLBAR,
+ NSWS_ID_THROBBER,
+ NSWS_ID_DRAWINGAREA,
+ NSWS_ID_STATUSBAR,
+ NSWS_ID_LAUNCH_URL,
+} nsws_constants ;
+
+LRESULT CALLBACK nsws_window_url_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
+LRESULT CALLBACK nsws_window_toolbar_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
+LRESULT CALLBACK nsws_window_event_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
+
+HINSTANCE hinstance;
+
+void gui_multitask(void)
+{
+/* LOG(("gui_multitask")); */
+}
+
+/**
+ * called synchronously to handle all redraw events
+ */
+static void redraw(void)
+{
+ struct gui_window *w = window_list;
+ struct browser_window *bw;
+ struct content *c;
+ HDC hdc;
+
+ while (w != NULL) {
+ if ((w->redraw.right - w->redraw.left <= 0) ||
+ (w->redraw.bottom - w->redraw.top <= 0)) {
+ w = w->next;
+ continue;
+ }
+
+ bw = w->bw;
+ if (bw == NULL) {
+ w = w->next;
+ continue;
+ }
+
+ c = bw->current_content;
+
+ if ((c == NULL) || (c->locked)) {
+ w = w->next;
+ continue;
+ }
+ current_hwnd = w->main;
+ PostMessage(w->toolbar, WM_PAINT, 0, 0);
+ PostMessage(w->urlbar, WM_PAINT, 0, 0);
+ w->scrolly += w->requestscrolly;
+ w->scrollx += w->requestscrollx;
+ w->scrolly = MAX(w->scrolly, 0);
+ w->scrolly = MIN(w->scrolly, c->height * w->bw->scale
+ - w->height);
+ w->scrollx = MAX(w->scrollx, 0);
+ w->scrollx = MIN(w->scrollx, c->width * w->bw->scale
+ - w->width);
+ /* redraw */
+/* w->redraw.left = MIN(w->redraw.left, w->scrollx);
+ w->redraw.top = MIN(w->redraw.top, w->scrolly + w->voffset );
+ w->redraw.right = MAX(w->redraw.right, w->scrollx + w->width);
+ w->redraw.bottom = MAX(w->redraw.bottom, w->scrolly +
+ w->height + w->voffset );
+*/
+ current_redraw_browser = bw;
+ nsws_plot_set_scale(bw->scale);
+
+/* doublebuffering = true; */
+ hdc = GetDC(w->main);
+ if (w->bufferbm == NULL) {
+ w->bufferbm = CreateCompatibleBitmap(hdc, w->width,
+ w->height + w->voffset);
+ SelectObject(w->bufferdc, w->bufferbm);
+ }
+
+
+ if ((w->bufferbm == NULL) || (w->bufferdc == NULL) ||
+ (hdc == NULL))
+ doublebuffering = false;
+ if (doublebuffering)
+ bufferdc = w->bufferdc;
+ content_redraw(c, -w->scrollx / w->bw->scale,
+ -w->scrolly / w->bw->scale,
+ w->width, w->height,
+ w->redraw.left - w->scrollx / w->bw->scale,
+ w->redraw.top - w->scrolly / w->bw->scale,
+ w->redraw.right - w->scrollx / w->bw->scale,
+ w->redraw.bottom - w->scrolly / w->bw->scale,
+ bw->scale, 0xFFFFFF);
+ if (doublebuffering)
+ /* blit buffer to screen */
+ BitBlt(hdc, 0, w->voffset, w->width, w->height,
+ w->bufferdc, 0, w->voffset,
+ SRCCOPY);
+ ReleaseDC(w->main, hdc);
+ doublebuffering = false;
+
+ w->requestscrolly = 0;
+ w->requestscrollx = 0;
+ w->redraw.left = w->redraw.top = INT_MAX;
+ w->redraw.right = w->redraw.bottom = -(INT_MAX);
+ w = w->next;
+ }
+}
+
+void gui_poll(bool active)
+{
+ MSG Msg;
+ if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE) != 0) {
+ if (!((current_gui == NULL) ||
+ (TranslateAccelerator(current_gui->main,
+ current_gui->acceltable, &Msg))))
+ TranslateMessage(&Msg);
+ DispatchMessage(&Msg);
+ }
+
+ schedule_run();
+
+}
+
+
+
+/**
+ * callback for url bar events
+ */
+LRESULT CALLBACK nsws_window_url_callback(HWND hwnd, UINT msg, WPARAM wparam,
+ LPARAM lparam)
+{
+ DWORD i, ii;
+ SendMessage(hwnd, EM_GETSEL, (WPARAM)&i, (LPARAM)&ii);
+ int x,y;
+ x = GET_X_LPARAM(lparam);
+ y = GET_Y_LPARAM(lparam);
+
+ if (msg == WM_PAINT) {
+ SendMessage(hwnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
+ SendMessage(hwnd, EM_SETSEL, (WPARAM)i, (LPARAM)ii);
+ }
+ return CallWindowProc((WNDPROC) urlproc, hwnd, msg, wparam, lparam);
+}
+
+/**
+ * callback for toolbar events
+ */
+LRESULT CALLBACK nsws_window_toolbar_callback(HWND hwnd, UINT msg,
+ WPARAM wparam, LPARAM lparam)
+{
+ bool match = false;
+ struct gui_window *w = window_list;
+ while (w != NULL) {
+ if (w->toolbar == hwnd) {
+ match = true;
+ break;
+ }
+ w = w->next;
+ }
+
+ if (match == false) { /* during initial window creation */
+ w = window_list;
+ while (w != NULL) {
+ if (w->toolbar == NULL) {
+ w->toolbar = hwnd;
+ break;
+ }
+ w = w->next;
+ }
+ }
+
+ if ((msg == WM_LBUTTONUP) ||
+ (msg == WM_LBUTTONDOWN) ||
+ (msg == WM_MOUSEMOVE)) {
+ int x,y;
+ x = GET_X_LPARAM(lparam);
+ y = GET_Y_LPARAM(lparam);
+ if ((w != NULL) &&
+ (x > w->ntoolbuttons * w->toolbuttondimension)
+ && (y < w->voffset)) {
+ if (msg == WM_LBUTTONDOWN)
+ SetFocus(w->urlbar);
+ return CallWindowProc((WNDPROC)
+ nsws_window_url_callback,
+ w->urlbar, msg, wparam,
+ MAKELONG(x - w->ntoolbuttons *
+ w->toolbuttondimension, y));
+ }
+ }
+ return CallWindowProc((WNDPROC) toolproc, hwnd, msg, wparam, lparam);
+}
+
+/**
+ * update state of forward/back buttons/menu items when page changes
+ */
+static void nsws_window_update_forward_back(struct gui_window *w)
+{
+ if (w->bw == NULL)
+ return;
+ bool forward = history_forward_available(w->bw->history);
+ bool back = history_back_available(w->bw->history);
+ if (w->mainmenu != NULL) {
+ EnableMenuItem(w->mainmenu, NSWS_ID_NAV_FORWARD,
+ (forward ? MF_ENABLED : MF_GRAYED));
+ EnableMenuItem(w->mainmenu, NSWS_ID_NAV_BACK,
+ (back ? MF_ENABLED : MF_GRAYED));
+ EnableMenuItem(w->rclick, NSWS_ID_NAV_FORWARD,
+ (forward ? MF_ENABLED : MF_GRAYED));
+ EnableMenuItem(w->rclick, NSWS_ID_NAV_BACK,
+ (back ? MF_ENABLED : MF_GRAYED));
+ }
+ if (w->toolbar != NULL) {
+ SendMessage(w->toolbar, TB_SETSTATE,
+ (WPARAM) NSWS_ID_NAV_FORWARD,
+ MAKELONG((forward ? TBSTATE_ENABLED :
+ TBSTATE_INDETERMINATE), 0));
+ SendMessage(w->toolbar, TB_SETSTATE,
+ (WPARAM) NSWS_ID_NAV_BACK,
+ MAKELONG((back ? TBSTATE_ENABLED :
+ TBSTATE_INDETERMINATE), 0));
+ }
+}
+
+static void nsws_update_edit(struct gui_window *w)
+{
+ bool paste, copy, del;
+ if (GetFocus() == w->urlbar) {
+ DWORD i, ii;
+ SendMessage(w->urlbar, EM_GETSEL, (WPARAM)&i,
+ (LPARAM)&ii);
+ paste = true;
+ copy = (i != ii);
+ del = (i != ii);
+
+ } else if ((w->bw != NULL) && (w->bw->sel != NULL)){
+ paste = (w->bw->paste_callback != NULL);
+ copy = w->bw->sel->defined;
+ del = ((w->bw->sel->defined) &&
+ (w->bw->caret_callback != NULL));
+ } else {
+ paste = false;
+ copy = false;
+ del = false;
+ }
+ EnableMenuItem(w->mainmenu,
+ NSWS_ID_EDIT_PASTE,
+ (paste ? MF_ENABLED : MF_GRAYED));
+
+ EnableMenuItem(w->rclick,
+ NSWS_ID_EDIT_PASTE,
+ (paste ? MF_ENABLED : MF_GRAYED));
+
+
+ EnableMenuItem(w->mainmenu,
+ NSWS_ID_EDIT_COPY,
+ (copy ? MF_ENABLED : MF_GRAYED));
+
+
+ EnableMenuItem(w->rclick,
+ NSWS_ID_EDIT_COPY,
+ (copy ? MF_ENABLED : MF_GRAYED));
+
+
+ if (del == true) {
+ EnableMenuItem(w->mainmenu, NSWS_ID_EDIT_CUT, MF_ENABLED);
+ EnableMenuItem(w->mainmenu, NSWS_ID_EDIT_DELETE, MF_ENABLED);
+ EnableMenuItem(w->rclick, NSWS_ID_EDIT_CUT, MF_ENABLED);
+ EnableMenuItem(w->rclick, NSWS_ID_EDIT_DELETE, MF_ENABLED);
+ } else {
+ EnableMenuItem(w->mainmenu, NSWS_ID_EDIT_CUT, MF_GRAYED);
+ EnableMenuItem(w->mainmenu, NSWS_ID_EDIT_DELETE, MF_GRAYED);
+ EnableMenuItem(w->rclick, NSWS_ID_EDIT_CUT, MF_GRAYED);
+ EnableMenuItem(w->rclick, NSWS_ID_EDIT_DELETE, MF_GRAYED);
+ }
+}
+
+static bool
+nsws_ctx_menu(struct gui_window *w, HWND hwnd, int x, int y)
+{
+ RECT rc; /* client area of window */
+ POINT pt = { x, y }; /* location of mouse click */
+
+ /* Get the bounding rectangle of the client area. */
+ GetClientRect(hwnd, &rc);
+
+ /* Convert the mouse position to client coordinates. */
+ ScreenToClient(hwnd, &pt);
+
+ /* If the position is in the client area, display a shortcut menu. */
+ if (PtInRect(&rc, pt)) {
+ ClientToScreen(hwnd, &pt);
+ nsws_update_edit(w);
+ TrackPopupMenu(GetSubMenu(w->rclick, 0),
+ TPM_CENTERALIGN | TPM_TOPALIGN,
+ x,
+ y,
+ 0,
+ hwnd,
+ NULL);
+
+ return true;
+ }
+
+ /* Return false if no menu is displayed. */
+ return false;
+}
+
+/**
+ * set accelerators
+ */
+static void nsws_window_set_accels(struct gui_window *w)
+{
+ int i, nitems = 13;
+ ACCEL accels[nitems];
+ for (i = 0; i < nitems; i++)
+ accels[i].fVirt = FCONTROL | FVIRTKEY;
+ accels[0].key = 0x51; /* Q */
+ accels[0].cmd = NSWS_ID_FILE_QUIT;
+ accels[1].key = 0x4E; /* N */
+ accels[1].cmd = NSWS_ID_FILE_OPEN_WINDOW;
+ accels[2].key = VK_LEFT;
+ accels[2].cmd = NSWS_ID_NAV_BACK;
+ accels[3].key = VK_RIGHT;
+ accels[3].cmd = NSWS_ID_NAV_FORWARD;
+ accels[4].key = VK_UP;
+ accels[4].cmd = NSWS_ID_NAV_HOME;
+ accels[5].key = VK_BACK;
+ accels[5].cmd = NSWS_ID_NAV_STOP;
+ accels[6].key = VK_SPACE;
+ accels[6].cmd = NSWS_ID_NAV_RELOAD;
+ accels[7].key = 0x4C; /* L */
+ accels[7].cmd = NSWS_ID_FILE_OPEN_LOCATION;
+ accels[8].key = 0x57; /* w */
+ accels[8].cmd = NSWS_ID_FILE_CLOSE_WINDOW;
+ accels[9].key = 0x41; /* A */
+ accels[9].cmd = NSWS_ID_EDIT_SELECT_ALL;
+ accels[10].key = VK_F8;
+ accels[10].cmd = NSWS_ID_VIEW_SOURCE;
+ accels[11].key = VK_RETURN;
+ accels[11].fVirt = FVIRTKEY;
+ accels[11].cmd = NSWS_ID_LAUNCH_URL;
+ accels[12].key = VK_F11;
+ accels[12].fVirt = FVIRTKEY;
+ accels[12].cmd = NSWS_ID_VIEW_FULLSCREEN;
+
+ w->acceltable = CreateAcceleratorTable(accels, nitems);
+}
+
+/**
+ * set window icons
+ */
+static void nsws_window_set_ico(struct gui_window *w)
+{
+ char ico[PATH_MAX];
+ nsws_find_resource(ico, "NetSurf32.ico", "windows/res/NetSurf32.ico");
+ LOG(("setting ico as %s", ico));
+ hIcon = LoadImage(NULL, ico, IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
+ if (hIcon != NULL)
+ SendMessage(w->main, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
+ nsws_find_resource(ico, "NetSurf16.ico", "windows/res/NetSurf16.ico");
+ LOG(("setting ico as %s", ico));
+ hIconS = LoadImage(NULL, ico, IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
+ if (hIconS != NULL)
+ SendMessage(w->main, WM_SETICON, ICON_SMALL, (LPARAM)hIconS);
+}
+
+/**
+ * creation of url bar
+ */
+static void nsws_window_urlbar_create(struct gui_window *w)
+{
+ HWND hwnd = CreateWindow("EDIT",
+ "",
+ WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_OEMCONVERT,
+ w->toolbuttondimension * w->ntoolbuttons + 4,
+ 10,
+ w->urlbarwidth - 8,
+ w->toolbuttondimension - 12,
+ w->main,
+ (HMENU) NSWS_ID_URLBAR,
+ hinstance,
+ NULL);
+ /*urlproc = (FARPROC) SetWindowLong(hwnd, GWL_WNDPROC, (DWORD)
+ nsws_window_url_callback);*/
+ w->urlbar = hwnd;
+}
+
+/**
+ * creation of throbber
+ */
+static void nsws_window_throbber_create(struct gui_window *w)
+{
+ HWND hwnd;
+ char avi[PATH_MAX];
+
+ hwnd = CreateWindow(ANIMATE_CLASS,
+ "",
+ WS_CHILD | WS_VISIBLE | ACS_TRANSPARENT,
+ w->width - NSWS_THROBBER_WIDTH - 4, 8,
+ NSWS_THROBBER_WIDTH, NSWS_THROBBER_WIDTH, w->main,
+ (HMENU) NSWS_ID_THROBBER, hinstance, NULL);
+
+ nsws_find_resource(avi, "throbber.avi", "windows/res/throbber.avi");
+ LOG(("setting throbber avi as %s", avi));
+ Animate_Open(hwnd, avi);
+ if (w->throbbing)
+ Animate_Play(hwnd, 0, -1, -1);
+ else
+ Animate_Seek(hwnd, 0);
+ ShowWindow(hwnd, SW_SHOWNORMAL);
+ w->throbber = hwnd;
+}
+
+/**
+ * creation of toolbar
+ */
+static void
+nsws_window_toolbar_create(struct gui_window *w)
+{
+ unsigned int listid = 0;
+ char imagepath[PATH_MAX];
+ /* NB there is currently an immediate window close at
+ * netsurf launch in real/virtual - as distinct from
+ * emulation - windows whose probable cause is the
+ * location of the url bar to the right of the buttons;
+ * really the way forward would quite possibly be to
+ * implement an active bitmap as the button bar, sensitive
+ * to hover / click events; the immediate window close
+ * behaviour was observed during development when testing
+ * the arrangements of url bar / buttons although much has
+ * changed since then */
+
+ HWND hwnd = CreateWindow(TOOLBARCLASSNAME, NULL, WS_CHILD |
+ WS_VISIBLE | WS_BORDER | WS_CLIPSIBLINGS,
+ 0, 0, w->width,
+ w->toolbuttondimension + 12, w->main,
+ (HMENU) NSWS_ID_TOOLBAR, hinstance, NULL);
+ HIMAGELIST hImageList = ImageList_Create(w->toolbuttondimension - 8,
+ w->toolbuttondimension - 8, 0, w->ntoolbuttons, 0);
+ SendMessage(hwnd, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
+
+ ZeroMemory(w->buttons, sizeof(w->buttons));
+
+ w->buttons[5].iBitmap = w->urlbarwidth;
+ w->buttons[5].fsStyle = TBSTYLE_SEP;
+ w->buttons[5].iString = -1;
+/* w->buttons[0].fsState = TBSTATE_ENABLED; */
+
+/* keep bitmaps in cache memory for re-creation of toolbar */
+
+#define MAKE_BUTTON(p, q, r) \
+ if (w->hbmp[p] == NULL) { \
+ nsws_find_resource(imagepath, #r ".bmp", "windows/res/" \
+ #r ".bmp"); \
+ LOG(("loading toolbutton image %s", imagepath)); \
+ w->hbmp[p] = LoadImage(NULL, imagepath, IMAGE_BITMAP, \
+ w->toolbuttondimension - 8, \
+ w->toolbuttondimension - 8, LR_SHARED | \
+ LR_LOADFROMFILE | LR_LOADTRANSPARENT); \
+ } \
+ ImageList_Add(hImageList, w->hbmp[p], NULL); \
+ w->buttons[p].iBitmap = MAKELONG(p, 0); \
+ w->buttons[p].idCommand = NSWS_ID_NAV_##q; \
+ w->buttons[p].fsState = TBSTATE_ENABLED; \
+ w->buttons[p].fsStyle = TBSTYLE_BUTTON
+ MAKE_BUTTON(0, BACK, back);
+ MAKE_BUTTON(1, FORWARD, forward);
+ MAKE_BUTTON(2, HOME, home);
+ MAKE_BUTTON(3, STOP, stop);
+ MAKE_BUTTON(4, RELOAD, reload);
+#undef MAKE_BUTTON
+ SendMessage(hwnd, TB_SETIMAGELIST, (WPARAM) listid, (LPARAM)
+ hImageList);
+ SendMessage(hwnd, TB_ADDBUTTONS, w->ntoolbuttons + 1,
+ (LPARAM) &(w->buttons));
+ w->toolbar = hwnd;
+ DeleteObject(hImageList);
+ nsws_window_urlbar_create(w);
+ nsws_window_throbber_create(w);
+ SendMessage(hwnd, WM_SIZE, 0,
+ MAKELONG(w->width, w->toolbuttondimension + 12));
+ toolproc = (FARPROC) SetWindowLong(hwnd, GWL_WNDPROC, (DWORD)
+ nsws_window_toolbar_callback);
+}
+
+/**
+ * creation of status bar
+ */
+static void nsws_window_statusbar_create(struct gui_window *w)
+{
+ HWND hwnd = CreateWindowEx(0, STATUSCLASSNAME, NULL, WS_CHILD |
+ WS_VISIBLE, 0, 0, 0, 0, w->main,
+ (HMENU) NSWS_ID_STATUSBAR, hinstance, NULL);
+ SendMessage(hwnd, SB_SETTEXT, 0, (LPARAM)"NetSurf");
+ w->statusbar = hwnd;
+}
+
+static void nsws_window_drawingarea_create(struct gui_window *w)
+{
+ /* potentially make drawingarea window from frameless window
+ + scrollbars here */
+}
+
+/**
+ * creation of vertical scrollbar
+ */
+static void nsws_window_vscroll_create(struct gui_window *w)
+{
+ w->vscroll = CreateWindow("SCROLLBAR", NULL, WS_CHILD | SBS_VERT,
+ 0, 0, CW_USEDEFAULT, 300, w->main, NULL, hinstance,
+ NULL);
+}
+
+/**
+ * creation of horizontal scrollbar
+ */
+static void nsws_window_hscroll_create(struct gui_window *w)
+{
+ w->hscroll = CreateWindow("SCROLLBAR", NULL, WS_CHILD | SBS_HORZ,
+ 0, 0, 200, CW_USEDEFAULT, w->main, NULL, hinstance,
+ NULL);
+}
+
+/**
+ * callback for window events generally
+ */
+LRESULT CALLBACK nsws_window_event_callback(HWND hwnd, UINT msg, WPARAM wparam,
+ LPARAM lparam)
+{
+ bool match = false;
+ bool historyactive = false;
+ struct gui_window *w = window_list;
+ while (w != NULL) {
+ if (w->main == hwnd) {
+ match = true;
+ break;
+ }
+ w = w->next;
+ }
+ if (!match) { /* during initial window creation */
+ w = window_list;
+ while (w != NULL) {
+ if (w->main == NULL) {
+ w->main = hwnd;
+ break;
+ }
+ w = w->next;
+ }
+ }
+ if ((match) && (current_gui == NULL)) {
+ /* local history window is active */
+ if ((msg == WM_LBUTTONDOWN) || (msg == WM_PAINT))
+ historyactive = true;
+ else if ((msg == WM_NCHITTEST) || (msg == WM_SETCURSOR))
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+ else
+ return 0;
+ }
+ current_gui = w;
+ switch(msg) {
+ case WM_KEYDOWN: {
+ if (GetFocus() != hwnd)
+ break;
+ uint32_t i;
+ bool shift = ((GetKeyState(VK_SHIFT) & 0x8000) == 0x8000);
+ bool capslock = ((GetKeyState(VK_CAPITAL) & 1) == 1);
+ switch(wparam) {
+ case VK_LEFT:
+ i = KEY_LEFT;
+ if (shift)
+ SendMessage(hwnd, WM_HSCROLL,
+ MAKELONG(SB_LINELEFT, 0), 0);
+ break;
+ case VK_RIGHT:
+ i = KEY_RIGHT;
+ if (shift)
+ SendMessage(hwnd, WM_HSCROLL,
+ MAKELONG(SB_LINERIGHT, 0), 0);
+ break;
+ case VK_UP:
+ i = KEY_UP;
+ if (shift)
+ SendMessage(hwnd, WM_VSCROLL,
+ MAKELONG(SB_LINEUP, 0), 0);
+ break;
+ case VK_DOWN:
+ i = KEY_DOWN;
+ if (shift)
+ SendMessage(hwnd, WM_VSCROLL,
+ MAKELONG(SB_LINEDOWN, 0), 0);
+ break;
+ case VK_HOME:
+ i = KEY_LINE_START;
+ if (shift)
+ SendMessage(hwnd, WM_HSCROLL,
+ MAKELONG(SB_PAGELEFT, 0), 0);
+ break;
+ case VK_END:
+ i = KEY_LINE_END;
+ if (shift)
+ SendMessage(hwnd, WM_HSCROLL,
+ MAKELONG(SB_PAGERIGHT, 0), 0);
+ break;
+ case VK_DELETE:
+ i = KEY_DELETE_RIGHT;
+ break;
+ case VK_NEXT:
+ i = wparam;
+ SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0),
+ 0);
+ break;
+ case VK_PRIOR:
+ i = wparam;
+ SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0),
+ 0);
+ break;
+ default:
+ i = wparam;
+ break;
+ }
+ if ((i >= 'A') && (i <= 'Z') &&
+ (((!capslock) && (!shift)) ||
+ ((capslock) && (shift))))
+ i += 'a' - 'A';
+ if (w != NULL)
+ browser_window_key_press(w->bw, i);
+ break;
+ }
+ case WM_MOUSEMOVE: {
+ int x,y;
+ bool shift = ((GetKeyState(VK_SHIFT) & 0x8000) == 0x8000);
+ bool ctrl = ((GetKeyState(VK_CONTROL) & 0x8000) == 0x8000);
+ bool alt = ((GetKeyState(VK_MENU) & 0x8000) == 0x8000);
+ x = GET_X_LPARAM(lparam);
+ y = GET_Y_LPARAM(lparam);
+ if ((w == NULL) || (w->mouse == NULL) || (w->bw == NULL)
+ || (y < w->voffset))
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+
+ if ((w->mouse->state & BROWSER_MOUSE_PRESS_1) != 0) {
+ browser_window_mouse_click(w->bw, BROWSER_MOUSE_DRAG_1,
+ w->mouse->pressed_x,
+ w->mouse->pressed_y);
+ w->mouse->state &= ~BROWSER_MOUSE_PRESS_1;
+ w->mouse->state |= BROWSER_MOUSE_HOLDING_1 |
+ BROWSER_MOUSE_DRAG_ON;
+ }
+ else if ((w->mouse->state & BROWSER_MOUSE_PRESS_2) != 0) {
+ browser_window_mouse_click(w->bw, BROWSER_MOUSE_DRAG_2,
+ w->mouse->pressed_x,
+ w->mouse->pressed_y);
+ w->mouse->state &= ~BROWSER_MOUSE_PRESS_2;
+ w->mouse->state |= BROWSER_MOUSE_HOLDING_2 |
+ BROWSER_MOUSE_DRAG_ON;
+ }
+ if (((w->mouse->state & BROWSER_MOUSE_MOD_1) != 0) && !shift)
+ w->mouse->state &= ~BROWSER_MOUSE_MOD_1;
+ if (((w->mouse->state & BROWSER_MOUSE_MOD_2) != 0) && !ctrl)
+ w->mouse->state &= ~BROWSER_MOUSE_MOD_2;
+ if (((w->mouse->state & BROWSER_MOUSE_MOD_3) != 0) && !alt)
+ w->mouse->state &= ~BROWSER_MOUSE_MOD_3;
+
+ browser_window_mouse_track(w->bw, w->mouse->state,
+ (x + w->scrollx) / w->bw->scale,
+ (y - w->voffset + w->scrolly) / w->bw->scale);
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+ break;
+ }
+ case WM_LBUTTONDOWN: {
+ int x,y;
+ x = GET_X_LPARAM(lparam);
+ y = GET_Y_LPARAM(lparam);
+ if ((w == NULL) || (w->mouse == NULL) || (w->bw == NULL)
+ || (y < w->voffset)) {
+ nsws_localhistory_close(w);
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+ }
+ w->mouse->state = BROWSER_MOUSE_PRESS_1;
+ if ((GetKeyState(VK_SHIFT) & 0x8000) == 0x8000)
+ w->mouse->state |= BROWSER_MOUSE_MOD_1;
+ if ((GetKeyState(VK_CONTROL) & 0x8000) == 0x8000)
+ w->mouse->state |= BROWSER_MOUSE_MOD_2;
+ if ((GetKeyState(VK_MENU) & 0x8000) == 0x8000)
+ w->mouse->state |= BROWSER_MOUSE_MOD_3;
+ w->mouse->pressed_x = (x + w->scrollx) / w->bw->scale;
+ w->mouse->pressed_y = (y - w->voffset + w->scrolly)
+ / w->bw->scale;
+
+ SetFocus(hwnd);
+ browser_window_mouse_click(w->bw, w->mouse->state,
+ (x + w->scrollx) / w->bw->scale ,
+ (y - w->voffset + w->scrolly) /
+ w->bw->scale);
+ nsws_localhistory_close(w);
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+ break;
+ }
+ case WM_RBUTTONDOWN: {
+ int x,y;
+ x = GET_X_LPARAM(lparam);
+ y = GET_Y_LPARAM(lparam);
+ if ((w == NULL) || (w->mouse == NULL) || (w->bw == NULL) ||
+ (y < w->voffset))
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+
+ w->mouse->state = BROWSER_MOUSE_PRESS_2;
+ if ((GetKeyState(VK_SHIFT) & 0x8000) == 0x8000)
+ w->mouse->state |= BROWSER_MOUSE_MOD_1;
+ if ((GetKeyState(VK_CONTROL) & 0x8000) == 0x8000)
+ w->mouse->state |= BROWSER_MOUSE_MOD_2;
+ if ((GetKeyState(VK_MENU) & 0x8000) == 0x8000)
+ w->mouse->state |= BROWSER_MOUSE_MOD_3;
+ w->mouse->pressed_x = (x + w->scrollx) / w->bw->scale;
+ w->mouse->pressed_y = (y - w->voffset + w->scrolly)
+ / w->bw->scale;
+ SetFocus(hwnd);
+ browser_window_mouse_click(w->bw, w->mouse->state,
+ (x + w->scrollx) / w->bw->scale ,
+ (y - w->voffset + w->scrolly) /
+ w->bw->scale);
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+ break;
+ }
+ case WM_LBUTTONUP: {
+ int x,y;
+ x = GET_X_LPARAM(lparam);
+ y = GET_Y_LPARAM(lparam);
+ if ((w == NULL) || (w->mouse == NULL) || (w->bw == NULL)
+ || (y < w->voffset))
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+
+ bool shift = ((GetKeyState(VK_SHIFT) & 0x8000) == 0x8000);
+ bool ctrl = ((GetKeyState(VK_CONTROL) & 0x8000) == 0x8000);
+ bool alt = ((GetKeyState(VK_MENU) & 0x8000) == 0x8000);
+
+ if ((w->mouse->state & BROWSER_MOUSE_PRESS_1) != 0) {
+ w->mouse->state &= ~BROWSER_MOUSE_PRESS_1;
+ w->mouse->state |= BROWSER_MOUSE_CLICK_1;
+ }
+
+ if (((w->mouse->state & BROWSER_MOUSE_MOD_1) != 0) && !shift)
+ w->mouse->state &= ~BROWSER_MOUSE_MOD_1;
+ if (((w->mouse->state & BROWSER_MOUSE_MOD_2) != 0) && !ctrl)
+ w->mouse->state &= ~BROWSER_MOUSE_MOD_2;
+ if (((w->mouse->state & BROWSER_MOUSE_MOD_3) != 0) && !alt)
+ w->mouse->state &= ~BROWSER_MOUSE_MOD_3;
+
+ if ((w->mouse->state & BROWSER_MOUSE_CLICK_1) != 0)
+ browser_window_mouse_click(w->bw, w->mouse->state,
+ (x + w->scrollx) / w->bw->scale,
+ (y - w->voffset + w->scrolly) /
+ w->bw->scale);
+ else
+ browser_window_mouse_drag_end(w->bw, 0,
+ (x + w->scrollx) / w->bw->scale,
+ (y - w->voffset + w->scrolly) /
+ w->bw->scale);
+
+ w->mouse->state = 0;
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+ break;
+ }
+ case WM_RBUTTONUP: {
+ int x,y;
+ x = GET_X_LPARAM(lparam);
+ y = GET_Y_LPARAM(lparam);
+ if ((w == NULL) || (w->mouse == NULL) || (w->bw == NULL) ||
+ (y < w->voffset))
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+ bool shift = ((GetKeyState(VK_SHIFT) & 0x8000) == 0x8000);
+ bool ctrl = ((GetKeyState(VK_CONTROL) & 0x8000) == 0x8000);
+ bool alt = ((GetKeyState(VK_MENU) & 0x8000) == 0x8000);
+
+ if ((w->mouse->state & BROWSER_MOUSE_PRESS_2) != 0) {
+ w->mouse->state &= ~BROWSER_MOUSE_PRESS_2;
+ w->mouse->state |= BROWSER_MOUSE_CLICK_2;
+ }
+
+ if (((w->mouse->state & BROWSER_MOUSE_MOD_1) != 0) && !shift)
+ w->mouse->state &= ~BROWSER_MOUSE_MOD_1;
+ if (((w->mouse->state & BROWSER_MOUSE_MOD_2) != 0) && !ctrl)
+ w->mouse->state &= ~BROWSER_MOUSE_MOD_2;
+ if (((w->mouse->state & BROWSER_MOUSE_MOD_3) != 0) && !alt)
+ w->mouse->state &= ~BROWSER_MOUSE_MOD_3;
+
+ if ((w->mouse->state & BROWSER_MOUSE_CLICK_2) != 0)
+ browser_window_mouse_click(w->bw, w->mouse->state,
+ (x + w->scrollx) / w->bw->scale,
+ (y - w->voffset + w->scrolly) /
+ w->bw->scale);
+ else
+ browser_window_mouse_drag_end(w->bw, 0,
+ (x + w->scrollx) / w->bw->scale,
+ (y - w->voffset + w->scrolly) /
+ w->bw->scale);
+
+ w->mouse->state = 0;
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+ break;
+ }
+ case WM_LBUTTONDBLCLK: {
+ int x,y;
+ x = GET_X_LPARAM(lparam);
+ y = GET_Y_LPARAM(lparam);
+ if ((w != NULL) && (w->bw != NULL) && (y > w->voffset))
+ browser_window_mouse_click(w->bw,
+ BROWSER_MOUSE_DOUBLE_CLICK,
+ (x + w->scrollx) / w->bw->scale,
+ (y - w->voffset + w->scrolly) /
+ w->bw->scale);
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+ break;
+ }
+ case WM_NCLBUTTONDOWN: {
+ int x,y;
+ x = GET_X_LPARAM(lparam);
+ y = GET_Y_LPARAM(lparam);
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+ break;
+ }
+ case WM_ENTERMENULOOP:
+ nsws_update_edit(w);
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+
+ case WM_CONTEXTMENU:
+ if (!nsws_ctx_menu(w, hwnd, GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)))
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+
+
+ break;
+
+ case WM_COMMAND:
+ {
+ switch(LOWORD(wparam)) {
+ case NSWS_ID_FILE_QUIT:
+ w = window_list;
+ while (w != NULL) {
+ PostMessage(w->main, WM_CLOSE, 0, 0);
+ w = w->next;
+ }
+ netsurf_quit = true;
+ break;
+ case NSWS_ID_FILE_OPEN_LOCATION:
+ SetFocus(w->urlbar);
+ break;
+ case NSWS_ID_FILE_OPEN_WINDOW:
+ break;
+ case NSWS_ID_FILE_CLOSE_WINDOW:
+ PostMessage(hwnd, WM_CLOSE, 0, 0);
+ break;
+ case NSWS_ID_FILE_SAVE_PAGE:
+ break;
+ case NSWS_ID_FILE_SAVEAS_TEXT:
+ break;
+ case NSWS_ID_FILE_SAVEAS_PDF:
+ break;
+ case NSWS_ID_FILE_SAVEAS_DRAWFILE:
+ break;
+ case NSWS_ID_FILE_SAVEAS_POSTSCRIPT:
+ break;
+ case NSWS_ID_FILE_PRINT_PREVIEW:
+ break;
+ case NSWS_ID_FILE_PRINT:
+ break;
+ case NSWS_ID_EDIT_CUT:
+ OpenClipboard(hwnd);
+ EmptyClipboard();
+ CloseClipboard();
+ if (GetFocus() == w->urlbar)
+ SendMessage(w->urlbar, WM_CUT, 0, 0);
+ else if (w->bw != NULL)
+ browser_window_key_press(w->bw,
+ KEY_CUT_SELECTION);
+ break;
+ case NSWS_ID_EDIT_COPY:
+ OpenClipboard(hwnd);
+ EmptyClipboard();
+ CloseClipboard();
+ if (GetFocus() == w->urlbar)
+ SendMessage(w->urlbar, WM_COPY, 0, 0);
+ else if (w->bw != NULL)
+ gui_copy_to_clipboard(w->bw->sel);
+ break;
+ case NSWS_ID_EDIT_PASTE: {
+ OpenClipboard(hwnd);
+ HANDLE h = GetClipboardData(CF_TEXT);
+ if (h != NULL) {
+ char *content = GlobalLock(h);
+ LOG(("pasting %s\n", content));
+ GlobalUnlock(h);
+ }
+ CloseClipboard();
+ if (GetFocus() == w->urlbar)
+ SendMessage(w->urlbar, WM_PASTE, 0, 0);
+ else
+ gui_paste_from_clipboard(w, 0, 0);
+ break;
+ }
+ case NSWS_ID_EDIT_DELETE:
+ if (GetFocus() == w->urlbar)
+ SendMessage(w->urlbar, WM_CUT, 0, 0);
+ else
+ browser_window_key_press(w->bw,
+ KEY_DELETE_RIGHT);
+ break;
+ case NSWS_ID_EDIT_SELECT_ALL:
+ if (GetFocus() == w->urlbar)
+ SendMessage(w->urlbar, EM_SETSEL, 0, -1);
+ else
+ selection_select_all(w->bw->sel);
+ break;
+ case NSWS_ID_EDIT_SEARCH:
+ break;
+ case NSWS_ID_EDIT_PREFERENCES:
+ nsws_prefs_dialog_init(w->main);
+ break;
+ case NSWS_ID_NAV_BACK:
+ if ((w->bw != NULL) && (history_back_available(
+ w->bw->history))) {
+ history_back(w->bw, w->bw->history);
+ }
+ nsws_window_update_forward_back(w);
+ break;
+ case NSWS_ID_NAV_FORWARD:
+ if ((w->bw != NULL) && (history_forward_available(
+ w->bw->history))) {
+ history_forward(w->bw, w->bw->history);
+ }
+ nsws_window_update_forward_back(w);
+ break;
+ case NSWS_ID_NAV_HOME:
+ browser_window_go(w->bw, default_page, 0, true);
+ break;
+ case NSWS_ID_NAV_STOP:
+ browser_window_stop(w->bw);
+ break;
+ case NSWS_ID_NAV_RELOAD:
+ browser_window_reload(w->bw, true);
+ break;
+ case NSWS_ID_NAV_LOCALHISTORY:
+ nsws_localhistory_init(w);
+ break;
+ case NSWS_ID_NAV_GLOBALHISTORY:
+ break;
+ case NSWS_ID_VIEW_ZOOMPLUS: {
+ int x, y;
+ gui_window_get_scroll(w, &x, &y);
+ if (w->bw != NULL) {
+ browser_window_set_scale(w->bw,
+ w->bw->scale * 1.1, true);
+ browser_window_reformat(w->bw, w->width,
+ w->height);
+ }
+ gui_window_redraw_window(w);
+ gui_window_set_scroll(w, x, y);
+ break;
+ }
+ case NSWS_ID_VIEW_ZOOMMINUS: {
+ int x, y;
+ gui_window_get_scroll(w, &x, &y);
+ if (w->bw != NULL) {
+ browser_window_set_scale(w->bw,
+ w->bw->scale * 0.9, true);
+ browser_window_reformat(w->bw, w->width,
+ w->height);
+ }
+ gui_window_redraw_window(w);
+ gui_window_set_scroll(w, x, y);
+ break;
+ }
+ case NSWS_ID_VIEW_ZOOMNORMAL: {
+ int x, y;
+ gui_window_get_scroll(w, &x, &y);
+ if (w->bw != NULL) {
+ browser_window_set_scale(w->bw,
+ 1.0, true);
+ browser_window_reformat(w->bw, w->width,
+ w->height);
+ }
+ gui_window_redraw_window(w);
+ gui_window_set_scroll(w, x, y);
+ break;
+ }
+ case NSWS_ID_VIEW_SOURCE:
+ break;
+ case NSWS_ID_VIEW_SAVE_WIN_METRICS: {
+ RECT r;
+ GetWindowRect(hwnd, &r);
+ option_window_x = r.left;
+ option_window_y = r.top;
+ option_window_width = r.right - r.left;
+ option_window_height = r.bottom - r.top;
+ options_write(options_file_location);
+ break;
+ }
+ case NSWS_ID_VIEW_FULLSCREEN: {
+ RECT rdesk;
+ if (w->fullscreen == NULL) {
+ HWND desktop = GetDesktopWindow();
+ w->fullscreen = malloc(sizeof(RECT));
+ if ((desktop == NULL) ||
+ (w->fullscreen == NULL)) {
+ warn_user("NoMemory", 0);
+ break;
+ }
+ GetWindowRect(desktop, &rdesk);
+ GetWindowRect(hwnd, w->fullscreen);
+ DeleteObject(desktop);
+ SetWindowLong(hwnd, GWL_STYLE, 0);
+ SetWindowPos(hwnd, HWND_TOPMOST, 0, 0,
+ rdesk.right - rdesk.left,
+ rdesk.bottom - rdesk.top,
+ SWP_SHOWWINDOW);
+ } else {
+ SetWindowLong(hwnd, GWL_STYLE,
+ WS_OVERLAPPEDWINDOW |
+ WS_HSCROLL | WS_VSCROLL |
+ WS_CLIPCHILDREN |
+ WS_CLIPSIBLINGS | CS_DBLCLKS);
+ SetWindowPos(hwnd, HWND_TOPMOST,
+ w->fullscreen->left,
+ w->fullscreen->top,
+ w->fullscreen->right -
+ w->fullscreen->left,
+ w->fullscreen->bottom -
+ w->fullscreen->top,
+ SWP_SHOWWINDOW |
+ SWP_FRAMECHANGED);
+ free(w->fullscreen);
+ w->fullscreen = NULL;
+ }
+ break;
+ }
+ case NSWS_ID_VIEW_DOWNLOADS:
+ break;
+ case NSWS_ID_VIEW_TOGGLE_DEBUG_RENDERING:
+ html_redraw_debug = !html_redraw_debug;
+ if (w->bw != NULL) {
+ browser_window_reformat(
+ w->bw, w->width, w->height);
+ redraw();
+ }
+ break;
+ case NSWS_ID_VIEW_DEBUGGING_SAVE_BOXTREE:
+ break;
+ case NSWS_ID_VIEW_DEBUGGING_SAVE_DOMTREE:
+ break;
+ case NSWS_ID_HELP_CONTENTS:
+ break;
+ case NSWS_ID_HELP_GUIDE:
+ break;
+ case NSWS_ID_HELP_INFO:
+ break;
+ case NSWS_ID_HELP_ABOUT:
+ nsws_about_dialog_init(hinstance, hwnd);
+ break;
+ case NSWS_ID_LAUNCH_URL:
+ {
+ if (GetFocus() != w->urlbar)
+ break;
+ int len = SendMessage(w->urlbar, WM_GETTEXTLENGTH, 0,
+ 0);
+ char addr[len + 1];
+ SendMessage(w->urlbar, WM_GETTEXT, (WPARAM) (len + 1),
+ (LPARAM) addr);
+ LOG(("launching %s\n", addr));
+ browser_window_go(w->bw, addr, 0, true);
+ break;
+ }
+ case NSWS_ID_URLBAR:
+ /* main message should already have been handled */
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case WM_HSCROLL:
+ {
+ if (w->requestscrollx != 0)
+ break;
+ SCROLLINFO si;
+ int mem;
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_ALL;
+ GetScrollInfo(hwnd, SB_HORZ, &si);
+ mem = si.nPos;
+ switch (LOWORD(wparam))
+ {
+ case SB_LINELEFT:
+ si.nPos -= 30;
+ break;
+ case SB_LINERIGHT:
+ si.nPos += 30;
+ break;
+ case SB_PAGELEFT:
+ si.nPos -= w->width;
+ break;
+ case SB_PAGERIGHT:
+ si.nPos += w->width;
+ break;
+ case SB_THUMBTRACK:
+ si.nPos = si.nTrackPos;
+ break;
+ default:
+ break;
+ }
+ si.fMask = SIF_POS;
+ if ((w->bw != NULL) && (w->bw->current_content != NULL))
+ si.nPos = MIN(si.nPos,
+ w->bw->current_content->width *
+ w->bw->scale - w->width);
+ si.nPos = MAX(si.nPos, 0);
+ SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
+ GetScrollInfo(hwnd, SB_HORZ, &si);
+ if (si.nPos != mem)
+ gui_window_set_scroll(w, w->scrollx +
+ w->requestscrollx + si.nPos - mem, w->scrolly);
+ break;
+ }
+ case WM_VSCROLL:
+ {
+ if (w->requestscrolly != 0)
+ break;
+ SCROLLINFO si;
+ int mem;
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_ALL;
+ GetScrollInfo(hwnd, SB_VERT, &si);
+ mem = si.nPos;
+ switch (LOWORD(wparam))
+ {
+ case SB_TOP:
+ si.nPos = si.nMin;
+ break;
+ case SB_BOTTOM:
+ si.nPos = si.nMax;
+ break;
+ case SB_LINEUP:
+ si.nPos -= 30;
+ break;
+ case SB_LINEDOWN:
+ si.nPos += 30;
+ break;
+ case SB_PAGEUP:
+ si.nPos -= w->height;
+ break;
+ case SB_PAGEDOWN:
+ si.nPos += w->height;
+ break;
+ case SB_THUMBTRACK:
+ si.nPos = si.nTrackPos;
+ break;
+ default:
+ break;
+ }
+ si.fMask = SIF_POS;
+ if ((w->bw != NULL) && (w->bw->current_content != NULL))
+ si.nPos = MIN(si.nPos,
+ w->bw->current_content->height *
+ w->bw->scale - w->height);
+ si.nPos = MAX(si.nPos, 0);
+ SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
+ GetScrollInfo(hwnd, SB_VERT, &si);
+ if (si.nPos != mem)
+ gui_window_set_scroll(w, w->scrollx, w->scrolly +
+ w->requestscrolly + si.nPos - mem);
+ break;
+ }
+ case WM_MOUSEWHEEL:
+#ifdef MSH_MOUSEWHEEL
+ case MSH_MOUSEWHEEL: /* w95 additional module MSWheel */
+#endif
+ {
+ int i, z = GET_WHEEL_DELTA_WPARAM(wparam) / WHEEL_DELTA,
+ key = LOWORD(wparam);
+ DWORD command;
+ unsigned int newmessage = WM_VSCROLL;
+ if (key == MK_SHIFT) {
+ command = (z > 0) ? SB_LINERIGHT : SB_LINELEFT;
+ newmessage = WM_HSCROLL;
+ } else
+ /* add MK_CONTROL -> zoom */
+ command = (z > 0) ? SB_LINEUP : SB_LINEDOWN;
+ z = (z < 0) ? -1 * z : z;
+ for (i = 0; i < z; i++)
+ SendMessage(hwnd, newmessage, MAKELONG(command, 0), 0);
+ break;
+ }
+ case WM_CREATE:
+ {
+ HDC hdc = GetDC(hwnd);
+ int dpi = GetDeviceCaps(hdc,LOGPIXELSY);
+ if (dpi > 10)
+ nscss_screen_dpi = INTTOFIX(dpi);
+ ReleaseDC(hwnd, hdc);
+
+ nsws_window_set_accels(w);
+ nsws_window_set_ico(w);
+ nsws_window_toolbar_create(w);
+ nsws_window_statusbar_create(w);
+ nsws_window_drawingarea_create(w);
+ nsws_window_vscroll_create(w);
+ nsws_window_hscroll_create(w);
+ break;
+ }
+ case WM_PAINT:
+ {
+ if ((w->toolbar == NULL) || (w->urlbar == NULL) ||
+ (w->statusbar == NULL) || (w->vscroll == NULL)
+ || (w->hscroll == NULL))
+ break;
+ HWND focuswnd = GetFocus();
+ SetFocus(w->urlbar);
+ SetFocus(focuswnd);
+ current_hwnd = hwnd;
+ current_gui = w;
+ PAINTSTRUCT ps;
+ BeginPaint(hwnd, &ps);
+/* printf("repaint dc %p erase %d from %ld,%ld to %ld,%ld\n",
+ ps.hdc, (int)ps.fErase, ps.rcPaint.left,
+ ps.rcPaint.top, ps.rcPaint.right,
+ ps.rcPaint.bottom);
+*/ PostMessage(w->toolbar, WM_PAINT, 0, 0);
+ PostMessage(w->urlbar, WM_PAINT, 0, 0);
+ PostMessage(w->statusbar, WM_PAINT, 0, 0);
+ PostMessage(w->main, WM_NCPAINT, 0, 0);
+/* PostMessage(w->vscroll, WM_PAINT, 0, 0);
+ PostMessage(w->hscroll, WM_PAINT, 0, 0);
+*/
+ RECT r, rstatus, rtool;
+ GetClientRect(hwnd, &r);
+ GetWindowRect(w->toolbar, &rtool);
+ GetWindowRect(w->statusbar, &rstatus);
+
+ w->voffset = rtool.bottom - rtool.top - 1;
+ /* 1 seems necessary */
+
+ w->height = r.bottom - w->voffset - (rstatus.bottom -
+ rstatus.top) + 1;
+
+ w->width = r.right + 1;
+
+ w->redraw.left = MAX(ps.rcPaint.left, 0);
+ w->redraw.top = MAX(ps.rcPaint.top - w->voffset, 0);
+ w->redraw.right = MIN(ps.rcPaint.right, w->width);
+ w->redraw.bottom = MIN(ps.rcPaint.bottom, w->height);
+ redraw();
+ EndPaint(hwnd, &ps);
+ plot.clip(0, 0, w->width, w->height);
+ DWORD ret = DefWindowProc(hwnd, msg, wparam, lparam);
+ if (historyactive)
+ current_gui = NULL;
+ return ret;
+ break;
+ }
+ case WM_NCPAINT:
+ PostMessage(w->toolbar, WM_PAINT, 0, 0);
+ PostMessage(w->urlbar, WM_PAINT, 0, 0);
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+ break;
+ case WM_MOVE:
+ DefWindowProc(hwnd, msg, wparam, lparam);
+ gui_window_redraw_window(w);
+ break;
+ case WM_SIZE:
+ {
+ if ((w->toolbar == NULL) || (w->urlbar == NULL) ||
+ (w->statusbar == NULL))
+ break;
+ int x, y;
+ RECT rmain, rstatus, rtool;
+ GetClientRect(hwnd, &rmain);
+ GetClientRect(w->toolbar, &rtool);
+ GetWindowRect(w->statusbar, &rstatus);
+ gui_window_get_scroll(w, &x, &y);
+ w->voffset = rtool.bottom - rtool.top;
+ w->height = HIWORD(lparam) - w->voffset - (rstatus.bottom -
+ rstatus.top);
+ w->width = LOWORD(lparam);
+ HDC hdc = GetDC(hwnd);
+ if (w->bufferdc == NULL)
+ w->bufferdc = CreateCompatibleDC(hdc);
+ if (w->bufferbm != NULL) {
+ DeleteObject(w->bufferbm);
+ w->bufferbm = CreateCompatibleBitmap(hdc, w->width,
+ w->height + w->voffset);
+ SelectObject(w->bufferdc, w->bufferbm);
+ }
+ ReleaseDC(hwnd, hdc);
+ w->urlbarwidth = w->width - w->ntoolbuttons *
+ w->toolbuttondimension - 8 -
+ NSWS_THROBBER_WIDTH;
+ if (w->bw != NULL) {
+ browser_window_reformat(
+ w->bw, w->width, w->height);
+ redraw();
+ }
+ gui_window_set_scroll(w, x, y);
+
+ /* re-create toolbar to adjust width of url bar holder */
+ DestroyWindow(w->toolbar);
+ DestroyWindow(w->throbber);
+ /* memorize url */
+ int len = SendMessage(w->urlbar, WM_GETTEXTLENGTH, 0, 0);
+ char temp[len + 1];
+ SendMessage(w->urlbar, WM_GETTEXT, (WPARAM) (len + 1),
+ (LPARAM) temp);
+ DestroyWindow(w->urlbar);
+ nsws_window_toolbar_create(w);
+ SendMessage(w->urlbar, WM_SETTEXT, 0, (LPARAM) temp);
+/* SendMessage(w->toolbar, TB_AUTOSIZE, 0, 0);
+ */
+ SendMessage(w->statusbar, WM_SIZE, 0, MAKELONG(w->width, 0));
+ nsws_window_update_forward_back(w);
+
+ if (w->toolbar != NULL)
+ SendMessage(w->toolbar, TB_SETSTATE,
+ (WPARAM) NSWS_ID_NAV_STOP,
+ MAKELONG(TBSTATE_INDETERMINATE, 0));
+
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+ break;
+ }
+ case WM_CLOSE:
+ if (--open_windows == 0) {
+ netsurf_quit = true;
+ }
+ DestroyWindow(hwnd);
+ break;
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ break;
+ default:
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+ }
+ return 0;
+}
+
+/**
+ * creation of a new window
+ */
+static void nsws_window_create(struct gui_window *gw)
+{
+ if (gw == NULL)
+ return;
+ LOG(("nsws_window_create %p", gw));
+ const char windowclassname[] = "nsws_window";
+ WNDCLASSEX w;
+ HWND hwnd;
+ INITCOMMONCONTROLSEX icc;
+
+ icc.dwSize = sizeof(icc);
+ icc.dwICC = ICC_BAR_CLASSES | ICC_WIN95_CLASSES;
+#if WINVER > 0x0501
+ icc.dwICC |= ICC_STANDARD_CLASSES;
+#endif
+ InitCommonControlsEx(&icc);
+
+ w.cbSize = sizeof(WNDCLASSEX);
+ w.style = 0;
+ w.lpfnWndProc = nsws_window_event_callback;
+ w.cbClsExtra = 0;
+ w.cbWndExtra = 0;
+ w.hInstance = hinstance;
+ w.hIcon = LoadIcon(NULL, IDI_APPLICATION); /* -> NetSurf */
+ w.hCursor = LoadCursor(NULL, IDC_ARROW);
+ w.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+ w.lpszMenuName = NULL;
+ w.lpszClassName = windowclassname;
+ w.hIconSm = LoadIcon(NULL, IDI_APPLICATION); /* -> NetSurf */
+ RegisterClassEx(&w);
+
+ gw->mainmenu = LoadMenu(hinstance, MAKEINTRESOURCE(NSWS_ID_MAINMENU));
+ gw->rclick = LoadMenu(hinstance, MAKEINTRESOURCE(NSWS_ID_CTXMENU));
+
+ LOG(("creating window for hInstance %p", hinstance));
+ hwnd = CreateWindow(windowclassname,
+ "NetSurf Browser",
+ WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL |
+ WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CS_DBLCLKS,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ gw->width,
+ gw->height,
+ NULL,
+ gw->mainmenu,
+ hinstance,
+ NULL);
+
+ if ((option_window_width >= 100) &&
+ (option_window_height >= 100) &&
+ (option_window_x >= 0) &&
+ (option_window_y >= 0))
+ SetWindowPos(hwnd, HWND_TOPMOST, option_window_x,
+ option_window_y, option_window_width,
+ option_window_height, SWP_SHOWWINDOW);
+
+ ShowWindow(hwnd, SW_SHOWNORMAL);
+ UpdateWindow(hwnd);
+ gw->main = hwnd;
+}
+
+/**
+ * create a new gui_window to contain a browser_window
+ * \param bw the browser_window to connect to the new gui_window
+ */
+struct gui_window *
+gui_create_browser_window(struct browser_window *bw,
+ struct browser_window *clone,
+ bool new_tab)
+{
+ struct gui_window *w;
+
+ w = calloc(1, sizeof(struct gui_window));
+
+ if (w == NULL)
+ return NULL;
+
+ /* connect gui window to browser window */
+ w->bw = bw;
+
+ w->width = 600;
+ w->height = 600;
+ w->ntoolbuttons = NTOOLBUTTONS;
+ w->toolbuttondimension = 32; /* includes padding of 4 every side */
+ w->urlbarwidth = w->width - w->toolbuttondimension * w->ntoolbuttons
+ - 8 - NSWS_THROBBER_WIDTH;
+ w->requestscrollx = 0;
+ w->requestscrolly = 0;
+ w->localhistory = NULL;
+
+ w->mouse = malloc(sizeof(struct browser_mouse));
+ if (w->mouse == NULL) {
+ free(w);
+ return NULL;
+ }
+ w->mouse->gui = w;
+ w->mouse->state = 0;
+ w->mouse->pressed_x = 0;
+ w->mouse->pressed_y = 0;
+
+ if (bw != NULL)
+ switch(bw->browser_window_type) {
+ case BROWSER_WINDOW_NORMAL:
+ break;
+
+ case BROWSER_WINDOW_FRAME:
+ LOG(("create frame"));
+ break;
+
+ default:
+ LOG(("unhandled type"));
+ }
+
+ if (window_list != NULL)
+ window_list->prev = w;
+ w->next = window_list;
+ window_list = w;
+
+ input_window = w;
+
+ open_windows++;
+ nsws_window_create(w);
+
+ return w;
+}
+
+
+
+
+HICON nsws_window_get_ico(bool large)
+{
+ return large ? hIcon : hIconS;
+}
+
+
+
+
+/**
+ * cache pointers for quick swapping
+ */
+static void nsws_window_init_pointers(void)
+{
+ nsws_pointer.hand = LoadCursor(NULL, IDC_HAND);
+ nsws_pointer.ibeam = LoadCursor(NULL, IDC_IBEAM);
+ nsws_pointer.cross = LoadCursor(NULL, IDC_CROSS);
+ nsws_pointer.sizeall = LoadCursor(NULL, IDC_SIZEALL);
+ nsws_pointer.sizewe = LoadCursor(NULL, IDC_SIZEWE);
+ nsws_pointer.sizens = LoadCursor(NULL, IDC_SIZENS);
+ nsws_pointer.sizenesw = LoadCursor(NULL, IDC_SIZENESW);
+ nsws_pointer.sizenwse = LoadCursor(NULL, IDC_SIZENWSE);
+ nsws_pointer.wait = LoadCursor(NULL, IDC_WAIT);
+ nsws_pointer.appstarting = LoadCursor(NULL, IDC_APPSTARTING);
+ nsws_pointer.no = LoadCursor(NULL, IDC_NO);
+ nsws_pointer.help = LoadCursor(NULL, IDC_HELP);
+ nsws_pointer.arrow = LoadCursor(NULL, IDC_ARROW);
+}
+
+
+
+HWND gui_window_main_window(struct gui_window *w)
+{
+ if (w == NULL)
+ return NULL;
+ return w->main;
+}
+
+HWND gui_window_toolbar(struct gui_window *w)
+{
+ if (w == NULL)
+ return NULL;
+ return w->toolbar;
+}
+
+HWND gui_window_urlbar(struct gui_window *w)
+{
+ if (w == NULL)
+ return NULL;
+ return w->urlbar;
+}
+
+HWND gui_window_statusbar(struct gui_window *w)
+{
+ if (w == NULL)
+ return NULL;
+ return w->statusbar;
+}
+
+HWND gui_window_drawingarea(struct gui_window *w)
+{
+ if (w == NULL)
+ return NULL;
+ return w->drawingarea;
+}
+
+struct nsws_localhistory *gui_window_localhistory(struct gui_window *w)
+{
+ if (w == NULL)
+ return NULL;
+ return w->localhistory;
+}
+
+void gui_window_set_localhistory(struct gui_window *w,
+ struct nsws_localhistory *l)
+{
+ if (w != NULL)
+ w->localhistory = l;
+}
+
+RECT *gui_window_redraw_rect(struct gui_window *w)
+{
+ if (w == NULL)
+ return NULL;
+ return &(w->redraw);
+}
+
+RECT *gui_window_clip_rect(struct gui_window *w)
+{
+ if (w == NULL)
+ return NULL;
+ return &(w->clip);
+}
+
+int gui_window_voffset(struct gui_window *w)
+{
+ if (w == NULL)
+ return 0;
+ return w->voffset;
+}
+
+int gui_window_width(struct gui_window *w)
+{
+ if (w == NULL)
+ return 0;
+ return w->width;
+}
+
+int gui_window_height(struct gui_window *w)
+{
+ if (w == NULL)
+ return 0;
+ return w->height;
+}
+
+int gui_window_scrollingx(struct gui_window *w)
+{
+ if (w == NULL)
+ return 0;
+ return w->requestscrollx;
+}
+
+int gui_window_scrollingy(struct gui_window *w)
+{
+ if (w == NULL)
+ return 0;
+ return w->requestscrolly;
+}
+
+struct gui_window *gui_window_iterate(struct gui_window *w)
+{
+ if (w == NULL)
+ return NULL;
+ return w->next;
+}
+
+struct browser_window *gui_window_browser_window(struct gui_window *w)
+{
+ if (w == NULL)
+ return NULL;
+ return w->bw;
+}
+
+/**
+ * window cleanup code
+ */
+void gui_window_destroy(struct gui_window *w)
+{
+ if (w == NULL)
+ return;
+
+ if (w->prev != NULL)
+ w->prev->next = w->next;
+ else
+ window_list = w->next;
+
+ if (w->next != NULL)
+ w->next->prev = w->prev;
+
+ DestroyAcceleratorTable(w->acceltable);
+
+ free(w);
+ w = NULL;
+}
+
+/**
+ * set window title
+ * \param title the [url]
+ */
+void gui_window_set_title(struct gui_window *w, const char *title)
+{
+ if (w == NULL)
+ return;
+ LOG(("%p, title %s", w, title));
+ char *fulltitle = malloc(strlen(title) +
+ SLEN(" - NetSurf") + 1);
+ if (fulltitle == NULL) {
+ warn_user("NoMemory", 0);
+ return;
+ }
+ strcpy(fulltitle, title);
+ strcat(fulltitle, " - NetSurf");
+ SendMessage(w->main, WM_SETTEXT, 0, (LPARAM)fulltitle);
+ free(fulltitle);
+}
+
+/**
+ * redraw a rectangle of the window
+ */
+void gui_window_redraw(struct gui_window *w, int x0, int y0, int x1, int y1)
+{
+ LOG(("redraw %p %d,%d %d,%d", w, x0, y0, x1, y1));
+ if (w == NULL)
+ return;
+ w->redraw.left = x0;
+ w->redraw.top = y0;
+ w->redraw.right = x1;
+ w->redraw.bottom = y1;
+ redraw();
+}
+
+/**
+ * redraw the whole window
+ */
+void gui_window_redraw_window(struct gui_window *w)
+{
+ LOG(("redraw window %p w=%d,h=%d", w, w->width, w->height));
+ if (w == NULL)
+ return;
+ w->redraw.left = 0;
+ w->redraw.top = 0;
+ w->redraw.right = w->width;
+ w->redraw.bottom = w->height;
+ redraw();
+}
+
+void gui_window_update_box(struct gui_window *w,
+ const union content_msg_data *data)
+{
+ if (w == NULL)
+ return;
+ w->redraw.left = (long)data->redraw.x;
+ w->redraw.top = (long)data->redraw.y;
+ w->redraw.right =(long)(data->redraw.x + data->redraw.width);
+ w->redraw.bottom = (long)(data->redraw.y + data->redraw.height);
+ redraw();
+}
+
+bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy)
+{
+ LOG(("get scroll"));
+ if (w == NULL)
+ return false;
+ *sx = w->scrollx;
+ *sy = w->scrolly;
+
+ return true;
+}
+
+/**
+ * scroll the window
+ * \param sx the new 'absolute' scroll location
+ * \param sy the new 'absolute' scroll location
+ */
+void gui_window_set_scroll(struct gui_window *w, int sx, int sy)
+{
+ SCROLLINFO si;
+ POINT p;
+
+ if ((w == NULL) ||
+ (w->bw == NULL) ||
+ (w->bw->current_content == NULL))
+ return;
+
+ /* limit scale range */
+ if (abs(w->bw->scale - 0.0) < 0.00001)
+ w->bw->scale = 1.0;
+
+ w->requestscrollx = sx - w->scrollx;
+ w->requestscrolly = sy - w->scrolly;
+
+ /* set the vertical scroll offset */
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_ALL;
+ si.nMin = 0;
+ si.nMax = w->bw->current_content->height * w->bw->scale;
+ si.nPage = w->height;
+ si.nPos = MAX(w->scrolly + w->requestscrolly, 0);
+ si.nPos = MIN(si.nPos, w->bw->current_content->height * w->bw->scale
+ - w->height);
+ SetScrollInfo(w->main, SB_VERT, &si, TRUE);
+
+ /* set the horizontal scroll offset */
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_ALL;
+ si.nMin = 0;
+ si.nMax = w->bw->current_content->width * w->bw->scale;
+ si.nPage = w->width;
+ si.nPos = MAX(w->scrollx + w->requestscrollx, 0);
+ si.nPos = MIN(si.nPos, w->bw->current_content->width * w->bw->scale
+ - w->width);
+ SetScrollInfo(w->main, SB_HORZ, &si, TRUE);
+
+ /* Set caret position */
+ GetCaretPos(&p);
+ HideCaret(w->main);
+ SetCaretPos(p.x - w->requestscrollx, p.y - w->requestscrolly);
+ ShowCaret(w->main);
+
+ RECT r, redraw;
+ r.top = w->voffset - 1;
+ r.bottom = w->voffset + w->height + 1;
+ r.left = 0;
+ r.right = w->width + 1;
+ ScrollWindowEx(w->main, - w->requestscrollx, - w->requestscrolly, &r,
+ NULL, NULL, &redraw, SW_INVALIDATE);
+ gui_window_redraw(w, redraw.left + (w->requestscrollx + w->scrollx)
+ / w->bw->scale - 1,
+ redraw.top + (w->requestscrolly + w->scrolly)
+ / w->bw->scale - w->voffset - 1,
+ redraw.right + (w->requestscrollx + w->scrollx)
+ / w->bw->scale + 1,
+ redraw.bottom + (w->requestscrolly + w->scrolly)
+ / w->bw->scale - w->voffset + 1);
+}
+
+void gui_window_scroll_visible(struct gui_window *w, int x0, int y0,
+ int x1, int y1)
+{
+ LOG(("scroll visible %s:(%p, %d, %d, %d, %d)", __func__, w, x0,
+ y0, x1, y1));
+}
+
+void gui_window_position_frame(struct gui_window *w, int x0, int y0,
+ int x1, int y1)
+{
+ LOG(("position frame %s: %d, %d, %d, %d", w->bw->name,
+ x0, y0, x1, y1));
+
+}
+
+void gui_window_get_dimensions(struct gui_window *w, int *width, int *height,
+ bool scaled)
+{
+ LOG(("get dimensions %p w=%d h=%d", w, w->width, w->height));
+ if (w == NULL)
+ return;
+ *width = w->width;
+ *height = w->height;
+}
+
+void gui_window_update_extent(struct gui_window *w)
+{
+
+}
+
+/**
+ * set the status bar message
+ */
+void gui_window_set_status(struct gui_window *w, const char *text)
+{
+ if (w == NULL)
+ return;
+ SendMessage(w->statusbar, WM_SETTEXT, 0, (LPARAM)text);
+}
+
+/**
+ * set the pointer shape
+ */
+void gui_window_set_pointer(struct gui_window *w, gui_pointer_shape shape)
+{
+ if (w == NULL)
+ return;
+ switch (shape) {
+ case GUI_POINTER_POINT: /* link */
+ case GUI_POINTER_MENU:
+ SetCursor(nsws_pointer.hand);
+ break;
+
+ case GUI_POINTER_CARET: /* input */
+ SetCursor(nsws_pointer.ibeam);
+ break;
+
+ case GUI_POINTER_CROSS:
+ SetCursor(nsws_pointer.cross);
+ break;
+
+ case GUI_POINTER_MOVE:
+ SetCursor(nsws_pointer.sizeall);
+ break;
+
+ case GUI_POINTER_RIGHT:
+ case GUI_POINTER_LEFT:
+ SetCursor(nsws_pointer.sizewe);
+ break;
+
+ case GUI_POINTER_UP:
+ case GUI_POINTER_DOWN:
+ SetCursor(nsws_pointer.sizens);
+ break;
+
+ case GUI_POINTER_RU:
+ case GUI_POINTER_LD:
+ SetCursor(nsws_pointer.sizenesw);
+ break;
+
+ case GUI_POINTER_RD:
+ case GUI_POINTER_LU:
+ SetCursor(nsws_pointer.sizenwse);
+ break;
+
+ case GUI_POINTER_WAIT:
+ SetCursor(nsws_pointer.wait);
+ break;
+
+ case GUI_POINTER_PROGRESS:
+ SetCursor(nsws_pointer.appstarting);
+ break;
+
+ case GUI_POINTER_NO_DROP:
+ case GUI_POINTER_NOT_ALLOWED:
+ SetCursor(nsws_pointer.no);
+ break;
+
+ case GUI_POINTER_HELP:
+ SetCursor(nsws_pointer.help);
+ break;
+
+ default:
+ SetCursor(nsws_pointer.arrow);
+ break;
+ }
+}
+
+struct nsws_pointers *nsws_get_pointers(void)
+{
+ return &nsws_pointer;
+}
+
+void gui_window_hide_pointer(struct gui_window *w)
+{
+}
+
+void gui_window_set_url(struct gui_window *w, const char *url)
+{
+ if (w == NULL)
+ return;
+ SendMessage(w->urlbar, WM_SETTEXT, 0, (LPARAM) url);
+}
+
+
+void gui_window_start_throbber(struct gui_window *w)
+{
+ if (w == NULL)
+ return;
+ nsws_window_update_forward_back(w);
+
+ if (w->mainmenu != NULL) {
+ EnableMenuItem(w->mainmenu, NSWS_ID_NAV_STOP, MF_ENABLED);
+ EnableMenuItem(w->mainmenu, NSWS_ID_NAV_RELOAD, MF_GRAYED);
+ }
+ if (w->rclick != NULL) {
+ EnableMenuItem(w->rclick, NSWS_ID_NAV_STOP, MF_ENABLED);
+ EnableMenuItem(w->rclick, NSWS_ID_NAV_RELOAD, MF_GRAYED);
+ }
+ if (w->toolbar != NULL) {
+ SendMessage(w->toolbar, TB_SETSTATE, (WPARAM) NSWS_ID_NAV_STOP,
+ MAKELONG(TBSTATE_ENABLED, 0));
+ SendMessage(w->toolbar, TB_SETSTATE,
+ (WPARAM) NSWS_ID_NAV_RELOAD,
+ MAKELONG(TBSTATE_INDETERMINATE, 0));
+ }
+ w->throbbing = true;
+ Animate_Play(w->throbber, 0, -1, -1);
+}
+
+void gui_window_stop_throbber(struct gui_window *w)
+{
+ if (w == NULL)
+ return;
+ nsws_window_update_forward_back(w);
+ if (w->mainmenu != NULL) {
+ EnableMenuItem(w->mainmenu, NSWS_ID_NAV_STOP, MF_GRAYED);
+ EnableMenuItem(w->mainmenu, NSWS_ID_NAV_RELOAD, MF_ENABLED);
+ }
+ if (w->rclick != NULL) {
+ EnableMenuItem(w->rclick, NSWS_ID_NAV_STOP, MF_GRAYED);
+ EnableMenuItem(w->rclick, NSWS_ID_NAV_RELOAD, MF_ENABLED);
+ }
+ if (w->toolbar != NULL) {
+ SendMessage(w->toolbar, TB_SETSTATE, (WPARAM) NSWS_ID_NAV_STOP,
+ MAKELONG(TBSTATE_INDETERMINATE, 0));
+ SendMessage(w->toolbar, TB_SETSTATE,
+ (WPARAM) NSWS_ID_NAV_RELOAD,
+ MAKELONG(TBSTATE_ENABLED, 0));
+ }
+ w->throbbing = false;
+ Animate_Stop(w->throbber);
+ Animate_Seek(w->throbber, 0);
+}
+
+/**
+ * place caret in window
+ */
+void gui_window_place_caret(struct gui_window *w, int x, int y, int height)
+{
+ if (w == NULL)
+ return;
+ CreateCaret(w->main, (HBITMAP)NULL, 1, height * w->bw->scale);
+ SetCaretPos(x * w->bw->scale - w->scrollx,
+ y * w->bw->scale + w->voffset - w->scrolly);
+ ShowCaret(w->main);
+}
+
+/**
+ * clear window caret
+ */
+void
+gui_window_remove_caret(struct gui_window *w)
+{
+ if (w == NULL)
+ return;
+ HideCaret(w->main);
+}
+
+void
+gui_window_set_icon(struct gui_window *g, struct content *icon)
+{
+}
+
+void
+gui_window_set_search_ico(struct content *ico)
+{
+}
+
+bool
+save_complete_gui_save(const char *path,
+ const char *filename,
+ size_t len,
+ const char *sourcedata,
+ content_type type)
+{
+ return false;
+}
+
+int
+save_complete_htmlSaveFileFormat(const char *path,
+ const char *filename,
+ xmlDocPtr cur,
+ const char *encoding,
+ int format)
+{
+ return 0;
+}
+
+
+void gui_window_new_content(struct gui_window *w)
+{
+}
+
+bool gui_window_scroll_start(struct gui_window *w)
+{
+ return true;
+}
+
+bool gui_window_box_scroll_start(struct gui_window *w,
+ int x0, int y0, int x1, int y1)
+{
+ return true;
+}
+
+bool gui_window_frame_resize_start(struct gui_window *w)
+{
+ LOG(("resize frame\n"));
+ return true;
+}
+
+void gui_window_save_as_link(struct gui_window *w, struct content *c)
+{
+}
+
+void gui_window_set_scale(struct gui_window *w, float scale)
+{
+ if (w == NULL)
+ return;
+ w->scale = scale;
+ LOG(("%.2f\n", scale));
+}
+
+void gui_drag_save_object(gui_save_type type, struct content *c,
+ struct gui_window *w)
+{
+}
+
+void gui_drag_save_selection(struct selection *s, struct gui_window *w)
+{
+}
+
+void gui_start_selection(struct gui_window *w)
+{
+}
+
+void gui_paste_from_clipboard(struct gui_window *w, int x, int y)
+{
+ HANDLE clipboard_handle;
+ char *content;
+
+ clipboard_handle = GetClipboardData(CF_TEXT);
+ if (clipboard_handle != NULL) {
+ content = GlobalLock(clipboard_handle);
+ LOG(("pasting %s", content));
+ GlobalUnlock(clipboard_handle);
+ }
+}
+
+bool gui_empty_clipboard(void)
+{
+ return false;
+}
+
+bool gui_add_to_clipboard(const char *text, size_t length, bool space)
+{
+ HANDLE hnew;
+ char *new, *original;
+ HANDLE h = GetClipboardData(CF_TEXT);
+ if (h == NULL)
+ original = (char *)"";
+ else
+ original = GlobalLock(h);
+
+ size_t len = strlen(original) + 1;
+ hnew = GlobalAlloc(GHND, length + len);
+ new = (char *)GlobalLock(hnew);
+ snprintf(new, length + len, "%s%s", original, text);
+
+ if (h != NULL) {
+ GlobalUnlock(h);
+ EmptyClipboard();
+ }
+ GlobalUnlock(hnew);
+ SetClipboardData(CF_TEXT, hnew);
+ return true;
+}
+
+bool gui_commit_clipboard(void)
+{
+ return false;
+}
+
+static bool
+gui_selection_traverse_handler(const char *text,
+ size_t length,
+ struct box *box,
+ void *handle,
+ const char *space_text,
+ size_t space_length)
+{
+ if (space_text) {
+ if (!gui_add_to_clipboard(space_text, space_length, false)) {
+ return false;
+ }
+ }
+
+ if (!gui_add_to_clipboard(text, length, box->space))
+ return false;
+
+ return true;
+}
+
+bool gui_copy_to_clipboard(struct selection *s)
+{
+ if ((s->defined) && (s->bw != NULL) && (s->bw->window != NULL) &&
+ (s->bw->window->main != NULL)) {
+ OpenClipboard(s->bw->window->main);
+ EmptyClipboard();
+ if (selection_traverse(s, gui_selection_traverse_handler,
+ NULL)) {
+ CloseClipboard();
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void gui_create_form_select_menu(struct browser_window *bw,
+ struct form_control *control)
+{
+}
+
+void gui_launch_url(const char *url)
+{
+}
+
+void gui_cert_verify(struct browser_window *bw, struct content *c,
+ const struct ssl_cert_info *certs, unsigned long num)
+{
+}
+
+int WINAPI
+WinMain(HINSTANCE hInstance, HINSTANCE hLastInstance, LPSTR lpcli, int ncmd)
+{
+ char **argv = NULL;
+ int argc = 0, argctemp = 0;
+ size_t len;
+ LPWSTR * argvw;
+
+ if (SLEN(lpcli) > 0) {
+ argvw = CommandLineToArgvW(GetCommandLineW(), &argc);
+ }
+
+ hinstance = hInstance;
+ setbuf(stderr, NULL);
+
+ /* Construct a unix style argc/argv */
+ argv = malloc(sizeof(char *) * argc);
+ while (argctemp < argc) {
+ len = wcstombs(NULL, argvw[argctemp], 0) + 1;
+ if (len > 0)
+ argv[argctemp] = malloc(len);
+ if (argv[argctemp] != NULL) {
+ wcstombs(argv[argctemp], argvw[argctemp], len);
+ /* alter windows-style forward slash flags to
+ * hypen flags.
+ */
+ if (argv[argctemp][0] == '/')
+ argv[argctemp][0] = '-';
+ }
+ argctemp++;
+ }
+ return netsurf_main(argc, argv);
+}
+
+
+static void *myrealloc(void *ptr, size_t len, void *pw)
+{
+ return realloc(ptr, len);
+}
+
+void gui_quit(void)
+{
+ LOG(("gui_quit"));
+
+ hubbub_finalise(myrealloc, NULL);
+}
+
+void gui_init(int argc, char** argv)
+{
+ char buf[PATH_MAX], sbuf[PATH_MAX];
+ int len;
+
+ LOG(("argc %d, argv %p", argc, argv));
+
+ nsws_find_resource(buf, "Aliases", "./windows/res/Aliases");
+ LOG(("Using '%s' as Aliases file", buf));
+
+ hubbub_error he = hubbub_initialise(buf, myrealloc, NULL);
+ LOG(("hubbub init %d", he));
+ if (he != HUBBUB_OK)
+ die("Unable to initialise HTML parsing library.\n");
+
+ /* load browser messages */
+ nsws_find_resource(buf, "messages", "./windows/res/messages");
+ LOG(("Using '%s' as Messages file", buf));
+ messages_load(buf);
+
+ /* load browser options */
+ nsws_find_resource(buf, "preferences", "~/.netsurf/preferences");
+ LOG(("Using '%s' as Preferences file", buf));
+ options_file_location = strdup(buf);
+ options_read(buf);
+
+ /* set up stylesheet urls */
+ getcwd(sbuf, PATH_MAX);
+ len = strlen(sbuf);
+ strncat(sbuf, "windows/res/default.css", PATH_MAX - len);
+ nsws_find_resource(buf, "default.css", sbuf);
+ default_stylesheet_url = path_to_url(buf);
+ LOG(("Using '%s' as Default CSS URL", default_stylesheet_url));
+
+ getcwd(sbuf, PATH_MAX);
+ len = strlen(sbuf);
+ strncat(sbuf, "windows/res/quirks.css", PATH_MAX - len);
+ nsws_find_resource(buf, "quirks.css", sbuf);
+ quirks_stylesheet_url = path_to_url(buf);
+ LOG(("Using '%s' as quirks stylesheet url", quirks_stylesheet_url ));
+
+ option_target_blank = false;
+
+}
+
+void gui_init2(int argc, char** argv)
+{
+ struct browser_window *bw;
+ const char *addr = NETSURF_HOMEPAGE;
+
+ nsws_window_init_pointers();
+ LOG(("argc %d, argv %p", argc, argv));
+
+ if (argc > 1)
+ addr = argv[1];
+ else if (option_homepage_url != NULL && option_homepage_url[0]
+ != '\0')
+ addr = option_homepage_url;
+ else
+ addr = default_page;
+
+ LOG(("calling browser_window_create"));
+ bw = browser_window_create(addr, 0, 0, true, false);
+}
+
+void gui_stdout(void)
+{
+ /* mwindows compile flag normally invalidates stdout unless
+ already redirected */
+ if (_get_osfhandle(fileno(stdout)) == -1) {
+ AllocConsole();
+ freopen("CONOUT$", "w", stdout);
+ }
+}
diff --git a/windows/gui.h b/windows/gui.h
new file mode 100644
index 000000000..e91da3946
--- /dev/null
+++ b/windows/gui.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_WINDOWS_GUI_H_
+#define _NETSURF_WINDOWS_GUI_H_
+
+#include <windows.h>
+#include "desktop/gui.h"
+#include "windows/localhistory.h"
+
+extern HINSTANCE hinstance;
+
+/* bounding box */
+typedef struct bbox_s {
+ int x0;
+ int y0;
+ int x1;
+ int y1;
+} bbox_t;
+
+struct nsws_pointers {
+ HCURSOR hand;
+ HCURSOR ibeam;
+ HCURSOR cross;
+ HCURSOR sizeall;
+ HCURSOR sizewe;
+ HCURSOR sizens;
+ HCURSOR sizenesw;
+ HCURSOR sizenwse;
+ HCURSOR wait;
+ HCURSOR appstarting;
+ HCURSOR no;
+ HCURSOR help;
+ HCURSOR arrow;
+};
+
+struct browser_mouse {
+ struct gui_window *gui;
+ struct box *box;
+
+ double pressed_x;
+ double pressed_y;
+ bool waiting;
+ browser_mouse_state state;
+};
+
+extern struct gui_window *window_list;
+extern char *options_file_location;
+
+HWND gui_window_main_window(struct gui_window *);
+HWND gui_window_toolbar(struct gui_window *);
+HWND gui_window_urlbar(struct gui_window *);
+HWND gui_window_statusbar(struct gui_window *);
+HWND gui_window_drawingarea(struct gui_window *);
+struct nsws_localhistory *gui_window_localhistory(struct gui_window *);
+void gui_window_set_localhistory(struct gui_window *,
+ struct nsws_localhistory *);
+
+RECT *gui_window_redraw_rect(struct gui_window *);
+RECT *gui_window_clip_rect(struct gui_window *w);
+
+int gui_window_voffset(struct gui_window *);
+int gui_window_width(struct gui_window *);
+int gui_window_height(struct gui_window *);
+int gui_window_scrollingx(struct gui_window *w);
+int gui_window_scrollingy(struct gui_window *w);
+
+struct gui_window *gui_window_iterate(struct gui_window *);
+struct browser_window *gui_window_browser_window(struct gui_window *);
+struct nsws_pointers *nsws_get_pointers(void);
+HICON nsws_window_get_ico(bool);
+
+#endif
diff --git a/windows/history.c b/windows/history.c
new file mode 100644
index 000000000..b0cf20495
--- /dev/null
+++ b/windows/history.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.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 "content/urldb.h"
+#include "desktop/browser.h"
+
+void global_history_add(const char *url)
+{
+ const struct url_data *data;
+
+ data = urldb_get_url_data(url);
+ if (!data)
+ return;
+
+
+}
+
+void global_history_add_recent(const char *url)
+{
+}
+
+char **global_history_get_recent(int *count)
+{
+ return NULL;
+}
+
diff --git a/windows/hotlist.c b/windows/hotlist.c
new file mode 100644
index 000000000..48df23bb4
--- /dev/null
+++ b/windows/hotlist.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.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 "desktop/browser.h"
+
+void hotlist_visited(struct content *content)
+{
+}
diff --git a/windows/localhistory.c b/windows/localhistory.c
new file mode 100644
index 000000000..09d6e4f4c
--- /dev/null
+++ b/windows/localhistory.c
@@ -0,0 +1,422 @@
+/*
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <windows.h>
+#include <windowsx.h>
+#define _WIN32_IE (0x0501)
+#include <commctrl.h>
+
+#include "desktop/browser.h"
+#include "desktop/history_core.h"
+#include "desktop/plotters.h"
+#include "utils/utils.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "windows/localhistory.h"
+#include "windows/gui.h"
+#include "windows/plot.h"
+
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+struct nsws_localhistory {
+ HWND hwnd; /**< the window handle */
+ int width; /**< the width of the memory history */
+ int height; /**< the height of the memory history */
+ int guiwidth; /**< the width of the history window */
+ int guiheight; /**< the height of the history window */
+ int vscroll; /**< the vertical scroll location */
+ int hscroll; /**< the horizontal scroll location */
+};
+
+static struct nsws_localhistory localhistory;
+
+LRESULT CALLBACK nsws_localhistory_event_callback(HWND hwnd, UINT msg,
+ WPARAM wparam, LPARAM lparam);
+static void nsws_localhistory_scroll_check(struct gui_window *w);
+static void nsws_localhistory_clear(struct gui_window *w);
+
+void nsws_localhistory_init(struct gui_window *w)
+{
+ LOG(("gui window %p", w));
+ static const char localhistorywindowclassname[] = "nsws_localhistory_window";
+ WNDCLASSEX we;
+ HWND mainhwnd = gui_window_main_window(w);
+ INITCOMMONCONTROLSEX icc;
+ HICON hIcon = nsws_window_get_ico(true);
+ HICON hIconS = nsws_window_get_ico(false);
+ struct browser_window *bw = gui_window_browser_window(w);
+ int margin = 50;
+ RECT r;
+
+ localhistory.width = 0;
+ localhistory.height = 0;
+ current_gui = NULL;
+ current_hwnd = NULL;
+ doublebuffering = false;
+ if ((bw != NULL) && (bw->history != NULL))
+ history_size(bw->history, &(localhistory.width),
+ &(localhistory.height));
+
+ GetWindowRect(mainhwnd, &r);
+ SetWindowPos(mainhwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
+ SWP_NOSIZE | SWP_NOMOVE);
+
+ localhistory.guiwidth = MIN(r.right - r.left - margin,
+ localhistory.width + margin);
+ localhistory.guiheight = MIN(r.bottom - r.top - margin,
+ localhistory.height + margin);
+
+ icc.dwSize = sizeof(icc);
+ icc.dwICC = ICC_BAR_CLASSES | ICC_WIN95_CLASSES;
+#if WINVER > 0x0501
+ icc.dwICC |= ICC_STANDARD_CLASSES;
+#endif
+ InitCommonControlsEx(&icc);
+
+ we.cbSize = sizeof(WNDCLASSEX);
+ we.style = 0;
+ we.lpfnWndProc = nsws_localhistory_event_callback;
+ we.cbClsExtra = 0;
+ we.cbWndExtra = 0;
+ we.hInstance = hinstance;
+ we.hIcon = (hIcon == NULL) ?
+ LoadIcon(NULL, IDI_APPLICATION) : hIcon;
+ we.hCursor = LoadCursor(NULL, IDC_ARROW);
+ we.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+ we.lpszMenuName = NULL;
+ we.lpszClassName = localhistorywindowclassname;
+ we.hIconSm = (hIconS == NULL) ?
+ LoadIcon(NULL, IDI_APPLICATION) : hIconS;
+ RegisterClassEx(&we);
+ LOG(("creating local history window for hInstance %p", hinstance));
+ localhistory.hwnd = CreateWindow(localhistorywindowclassname,
+ "NetSurf History",WS_THICKFRAME | WS_HSCROLL |
+ WS_VSCROLL | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
+ CS_DBLCLKS, r.left + margin/2, r.top + margin/2,
+ localhistory.guiwidth, localhistory.guiheight, NULL,
+ NULL, hinstance, NULL);
+ LOG(("gui_window %p width %d height %d hwnd %p", w,
+ localhistory.guiwidth, localhistory.guiheight,
+ localhistory.hwnd));
+ current_hwnd = localhistory.hwnd;
+ ShowWindow(localhistory.hwnd, SW_SHOWNORMAL);
+ UpdateWindow(localhistory.hwnd);
+ gui_window_set_localhistory(w, &localhistory);
+ nsws_localhistory_up(w);
+}
+
+LRESULT CALLBACK nsws_localhistory_event_callback(HWND hwnd, UINT msg,
+ WPARAM wparam, LPARAM lparam)
+{
+ bool match = false;
+ struct gui_window *w = window_list;
+ struct browser_window *bw = NULL;
+ struct nsws_localhistory *local;
+ while (w != NULL) {
+ local = gui_window_localhistory(w);
+ if ((local != NULL) && (local->hwnd == hwnd)) {
+ match = true;
+ break;
+ }
+ w = gui_window_iterate(w);
+ }
+ if (match)
+ bw = gui_window_browser_window(w);
+ switch(msg) {
+ case WM_CREATE:
+ nsws_localhistory_scroll_check(w);
+ break;
+ case WM_SIZE:
+ localhistory.guiheight = HIWORD(lparam);
+ localhistory.guiwidth = LOWORD(lparam);
+ nsws_localhistory_scroll_check(w);
+ current_gui = NULL;
+ current_hwnd = hwnd;
+ plot.rectangle(0, 0, localhistory.guiwidth,
+ localhistory.guiheight, plot_style_fill_white);
+ break;
+ case WM_MOVE: {
+ RECT r, rmain;
+ int voffset;
+ if (w != NULL) {
+ current_gui = w;
+ current_hwnd = gui_window_main_window(w);
+ voffset = gui_window_voffset(w);
+ GetWindowRect(hwnd, &r);
+ GetWindowRect(current_hwnd, &rmain);
+ gui_window_redraw(w,
+ MIN(r.top - rmain.top - voffset, 0),
+ MIN(r.left - rmain.left, 0),
+ gui_window_height(w) -
+ MIN(rmain.bottom - r.bottom, 0),
+ gui_window_width(w) -
+ MIN(rmain.right - r.right, 0));
+ current_gui = NULL;
+ current_hwnd = hwnd;
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+ }
+ }
+ case WM_LBUTTONUP: {
+ int x,y;
+ x = GET_X_LPARAM(lparam);
+ y = GET_Y_LPARAM(lparam);
+ if (bw == NULL)
+ break;
+ current_hwnd = gui_window_main_window(w);
+ current_gui = w;
+ if ((bw != NULL) && (history_click(bw, bw->history, x, y, false)))
+ DestroyWindow(hwnd);
+ else {
+ current_hwnd = hwnd;
+ current_gui = NULL;
+ }
+ }
+ case WM_MOUSEMOVE: {
+ int x,y;
+ x = GET_X_LPARAM(lparam);
+ y = GET_Y_LPARAM(lparam);
+/* if (bw != NULL)
+ history_hover(bw->history, x, y, (void *)hwnd);*/
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+ break;
+ }
+ case WM_VSCROLL:
+ {
+ if ((w == NULL) || (bw == NULL))
+ break;
+ SCROLLINFO si;
+ int mem;
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_ALL;
+ GetScrollInfo(hwnd, SB_VERT, &si);
+ mem = si.nPos;
+ switch (LOWORD(wparam))
+ {
+ case SB_TOP:
+ si.nPos = si.nMin;
+ break;
+ case SB_BOTTOM:
+ si.nPos = si.nMax;
+ break;
+ case SB_LINEUP:
+ si.nPos -= 30;
+ break;
+ case SB_LINEDOWN:
+ si.nPos += 30;
+ break;
+ case SB_PAGEUP:
+ si.nPos -= localhistory.guiheight;
+ break;
+ case SB_PAGEDOWN:
+ si.nPos += localhistory.guiheight;
+ break;
+ case SB_THUMBTRACK:
+ si.nPos = si.nTrackPos;
+ break;
+ default:
+ break;
+ }
+ si.nPos = MIN(si.nPos, localhistory.width);
+ si.nPos = MAX(si.nPos, 0);
+ si.fMask = SIF_POS;
+ SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
+ GetScrollInfo(hwnd, SB_VERT, &si);
+ if (si.nPos != mem) {
+ current_gui = NULL;
+ current_hwnd = hwnd;
+ localhistory.vscroll += si.nPos - mem;
+ plot.rectangle(0, 0, localhistory.guiwidth,
+ localhistory.guiheight,
+ plot_style_fill_white);
+ history_redraw_rectangle(bw->history,
+ localhistory.hscroll,
+ localhistory.vscroll,
+ localhistory.guiwidth +
+ localhistory.hscroll,
+ localhistory.guiheight
+ + localhistory.vscroll,
+ 0, 0);
+ }
+ break;
+ }
+ case WM_HSCROLL:
+ {
+ if ((w == NULL) || (bw == NULL))
+ break;
+ SCROLLINFO si;
+ int mem;
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_ALL;
+ GetScrollInfo(hwnd, SB_HORZ, &si);
+ mem = si.nPos;
+ switch (LOWORD(wparam))
+ {
+ case SB_LINELEFT:
+ si.nPos -= 30;
+ break;
+ case SB_LINERIGHT:
+ si.nPos += 30;
+ break;
+ case SB_PAGELEFT:
+ si.nPos -= localhistory.guiwidth;
+ break;
+ case SB_PAGERIGHT:
+ si.nPos += localhistory.guiwidth;
+ break;
+ case SB_THUMBTRACK:
+ si.nPos = si.nTrackPos;
+ break;
+ default:
+ break;
+ }
+ si.nPos = MIN(si.nPos, localhistory.height);
+ si.nPos = MAX(si.nPos, 0);
+ si.fMask = SIF_POS;
+ SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
+ GetScrollInfo(hwnd, SB_HORZ, &si);
+ if (si.nPos != mem) {
+ current_gui = NULL;
+ current_hwnd = hwnd;
+ localhistory.hscroll += si.nPos - mem;
+ if (bw == NULL)
+ break;
+ plot.rectangle(0, 0, localhistory.guiwidth,
+ localhistory.guiheight,
+ plot_style_fill_white);
+ history_redraw_rectangle(bw->history,
+ localhistory.hscroll,
+ localhistory.vscroll,
+ localhistory.guiwidth +
+ localhistory.hscroll,
+ localhistory.guiheight
+ + localhistory.vscroll,
+ 0, 0);
+ }
+ break;
+ }
+ case WM_PAINT: {
+ current_gui = NULL;
+ current_hwnd = hwnd;
+ PAINTSTRUCT ps;
+ BeginPaint(hwnd, &ps);
+ if (bw != NULL)
+ history_redraw_rectangle(bw->history,
+ localhistory.hscroll,
+ localhistory.vscroll,
+ localhistory.hscroll + localhistory.guiwidth,
+ localhistory.vscroll + localhistory.guiheight,
+ 0, 0);
+ EndPaint(hwnd, &ps);
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+ break;
+ }
+ case WM_CLOSE:
+ nsws_localhistory_clear(w);
+ DestroyWindow(hwnd);
+ break;
+ case WM_DESTROY:
+ nsws_localhistory_clear(w);
+ PostQuitMessage(0);
+ break;
+ default:
+ return DefWindowProc(hwnd, msg, wparam, lparam);
+ }
+ return 0;
+}
+
+void nsws_localhistory_up(struct gui_window *w)
+{
+ LOG(("gui window %p", w));
+ HDC hdc = GetDC(NULL);
+ struct browser_window *bw = gui_window_browser_window(w);
+
+ localhistory.vscroll = 0;
+ localhistory.hscroll = 0;
+
+ if (bw != NULL)
+ history_redraw(bw->history);
+
+ nsws_localhistory_scroll_check(w);
+
+ ReleaseDC(localhistory.hwnd, hdc);
+}
+
+void nsws_localhistory_scroll_check(struct gui_window *w)
+{
+ if (w == NULL)
+ return;
+ struct browser_window *bw = gui_window_browser_window(w);
+ if ((bw == NULL) || (localhistory.hwnd == NULL))
+ return;
+ history_size(bw->history, &(localhistory.width), &(localhistory.height));
+
+ SCROLLINFO si;
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_ALL;
+ si.nMin = 0;
+ si.nMax = localhistory.height;
+ si.nPage = localhistory.guiheight;
+ si.nPos = 0;
+ SetScrollInfo(localhistory.hwnd, SB_VERT, &si, TRUE);
+
+ si.nMax = localhistory.width;
+ si.nPage = localhistory.guiwidth;
+ SetScrollInfo(localhistory.hwnd, SB_HORZ, &si, TRUE);
+ if (localhistory.guiheight >= localhistory.height)
+ localhistory.vscroll = 0;
+ if (localhistory.guiwidth >= localhistory.width)
+ localhistory.hscroll = 0;
+ SendMessage(localhistory.hwnd, WM_PAINT, 0, 0);
+}
+
+/*
+void history_gui_set_pointer(gui_pointer_shape shape, void *p)
+{
+ struct nsws_pointers *pointers = nsws_get_pointers();
+ if (pointers == NULL)
+ return;
+ switch(shape) {
+ case GUI_POINTER_POINT:
+ SetCursor(pointers->hand);
+ break;
+ default:
+ SetCursor(pointers->arrow);
+ break;
+ }
+}
+*/
+
+void nsws_localhistory_close(struct gui_window *w)
+{
+ struct nsws_localhistory *l = gui_window_localhistory(w);
+ if (l != NULL)
+ DestroyWindow(l->hwnd);
+}
+
+void nsws_localhistory_clear(struct gui_window *w)
+{
+ if (w != NULL)
+ gui_window_set_localhistory(w, NULL);
+}
+
diff --git a/windows/localhistory.h b/windows/localhistory.h
new file mode 100644
index 000000000..422619239
--- /dev/null
+++ b/windows/localhistory.h
@@ -0,0 +1,30 @@
+/*
+* Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+*
+* This file is part of NetSurf, http://www.netsurf-browser.org/
+*
+* NetSurf is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; version 2 of the License.
+*
+* NetSurf is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _NETSURF_WINDOWS_LOCALHISTORY_H_
+#define _NETSURF_WINDOWS_LOCALHISTORY_H_
+
+#include "desktop/browser.h"
+
+struct nsws_localhistory;
+
+void nsws_localhistory_init(struct gui_window *);
+void nsws_localhistory_up(struct gui_window *);
+void nsws_localhistory_close(struct gui_window *);
+
+#endif
diff --git a/windows/login.c b/windows/login.c
new file mode 100644
index 000000000..306de8459
--- /dev/null
+++ b/windows/login.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.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 "desktop/401login.h"
+
+void gui_401login_open(struct browser_window *bw, struct content *c,
+ const char *realm)
+{
+}
diff --git a/windows/misc.c b/windows/misc.c
new file mode 100644
index 000000000..5eebaa383
--- /dev/null
+++ b/windows/misc.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.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 <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <windows.h>
+
+#include "desktop/cookies.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "utils/url.h"
+
+void warn_user(const char *warning, const char *detail)
+{
+ size_t len = 1 + ((warning != NULL) ? strlen(messages_get(warning)) :
+ 0) + ((detail != 0) ? strlen(detail) : 0);
+ char message[len];
+ snprintf(message, len, messages_get(warning), detail);
+ MessageBox(NULL, message, "Warning", MB_ICONWARNING);
+}
+
+void die(const char *error)
+{
+ exit(1);
+}
+
+bool cookies_update(const char *domain, const struct cookie_data *data)
+{
+ return true;
+}
+
+char *url_to_path(const char *url)
+{
+ return strdup(url + 5);
+}
diff --git a/windows/plot.c b/windows/plot.c
new file mode 100644
index 000000000..cef40dbc5
--- /dev/null
+++ b/windows/plot.c
@@ -0,0 +1,837 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+#include <math.h>
+#include <windows.h>
+
+#include "utils/log.h"
+#include "utils/utf8.h"
+#include "utils/utils.h"
+#include "desktop/gui.h"
+#include "desktop/plotters.h"
+
+#include "windows/bitmap.h"
+#include "windows/font.h"
+#include "windows/gui.h"
+#include "windows/plot.h"
+
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+/* set NSWS_PLOT_DEBUG to 0 for no debugging, 1 for debugging */
+#define NSWS_PLOT_DEBUG 0
+
+HWND current_hwnd;
+struct gui_window *current_gui;
+bool doublebuffering;
+bool thumbnail = false;
+HDC bufferdc;
+static float nsws_plot_scale = 1.0;
+static RECT localhistory_clip;
+
+
+static bool clip(int x0, int y0, int x1, int y1)
+{
+ int voffset = (thumbnail ? 0 : gui_window_voffset(current_gui));
+ y0 += voffset;
+ y1 += voffset;
+
+#if NSWS_PLOT_DEBUG
+ LOG(("clip %d,%d to %d,%d thumbnail %d", x0, y0, x1, y1, thumbnail));
+#endif
+ RECT *clip = gui_window_clip_rect(current_gui);
+ if (clip == NULL)
+ clip = &localhistory_clip;
+ x0 = MAX(x0, 0);
+ y0 = MAX(y0, voffset);
+ if (!((current_gui == NULL) || (thumbnail))) {
+ x1 = MIN(x1, gui_window_width(current_gui));
+ y1 = MIN(y1, gui_window_height(current_gui) + voffset);
+ }
+ clip->left = x0;
+ clip->top = y0 ;
+ clip->right = x1;
+ clip->bottom = y1;
+
+ return true;
+}
+
+static bool line(int x0, int y0, int x1, int y1, const plot_style_t *style)
+{
+ y0 += (thumbnail ? 0 : gui_window_voffset(current_gui));
+ y1 += (thumbnail ? 0 : gui_window_voffset(current_gui));
+#if NSWS_PLOT_DEBUG
+ LOG(("ligne from %d,%d to %d,%d thumbnail %d", x0, y0, x1, y1,
+ thumbnail));
+#endif
+ RECT *clipr = gui_window_clip_rect(current_gui);
+ if (clipr == NULL)
+ clipr = &localhistory_clip;
+ HRGN clipregion = CreateRectRgnIndirect(clipr);
+ if (clipregion == NULL) {
+ return false;
+ }
+
+ HDC hdc = doublebuffering ? bufferdc : GetDC(current_hwnd);
+ if (hdc == NULL) {
+ DeleteObject(clipregion);
+ return false;
+ }
+ COLORREF col = (DWORD)(style->stroke_colour & 0x00FFFFFF);
+ /* windows 0x00bbggrr */
+ DWORD penstyle = PS_GEOMETRIC | ((style->stroke_type ==
+ PLOT_OP_TYPE_DOT) ? PS_DOT :
+ (style->stroke_type == PLOT_OP_TYPE_DASH) ? PS_DASH:
+ 0);
+ LOGBRUSH lb = {BS_SOLID, col, 0};
+ HPEN pen = ExtCreatePen(penstyle, style->stroke_width, &lb, 0, NULL);
+ if (pen == NULL) {
+ DeleteObject(clipregion);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ HGDIOBJ bak = SelectObject(hdc, (HGDIOBJ) pen);
+ if (bak == NULL) {
+ DeleteObject(pen);
+ DeleteObject(clipregion);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ RECT r;
+ r.left = x0;
+ r.top = y0;
+ r.right = x1;
+ r.bottom = y1;
+
+ SelectClipRgn(hdc, clipregion);
+
+ MoveToEx(hdc, x0, y0, (LPPOINT) NULL);
+
+ LineTo(hdc, x1, y1);
+
+ SelectClipRgn(hdc, NULL);
+/* ValidateRect(current_hwnd, &r);
+*/
+ pen = SelectObject(hdc, bak);
+ DeleteObject(pen);
+ DeleteObject(clipregion);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return true;
+}
+
+static bool rectangle(int x0, int y0, int x1, int y1, const plot_style_t
+ *style)
+{
+ x1++;
+ y1++;
+ x0 = MAX(x0, 0);
+ y0 = MAX(y0, 0);
+ if (!((current_gui == NULL) || (thumbnail))) {
+ x1 = MIN(x1, gui_window_width(current_gui));
+ y1 = MIN(y1, gui_window_height(current_gui));
+ }
+
+ y0 += (thumbnail ? 0 : gui_window_voffset(current_gui));
+ y1 += (thumbnail ? 0 : gui_window_voffset(current_gui));
+#if NSWS_PLOT_DEBUG
+ LOG(("rectangle from %d,%d to %d,%d thumbnail %d", x0, y0, x1, y1,
+ thumbnail));
+#endif
+ HDC hdc = doublebuffering ? bufferdc : GetDC(current_hwnd);
+ if (hdc == NULL) {
+ return false;
+ }
+ RECT *clipr = gui_window_clip_rect(current_gui);
+ if (clipr == NULL)
+ clipr = &localhistory_clip;
+ HRGN clipregion = CreateRectRgnIndirect(clipr);
+ if (clipregion == NULL) {
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ COLORREF pencol = (DWORD)(style->stroke_colour & 0x00FFFFFF);
+ DWORD penstyle = PS_GEOMETRIC |
+ (style->stroke_type == PLOT_OP_TYPE_DOT ? PS_DOT :
+ (style->stroke_type == PLOT_OP_TYPE_DASH ? PS_DASH :
+ (style->stroke_type == PLOT_OP_TYPE_NONE ? PS_NULL :
+ 0)));
+ LOGBRUSH lb = {BS_SOLID, pencol, 0};
+ LOGBRUSH lb1 = {BS_SOLID, style->fill_colour, 0};
+ if (style->fill_type == PLOT_OP_TYPE_NONE)
+ lb1.lbStyle = BS_HOLLOW;
+
+ HPEN pen = ExtCreatePen(penstyle, style->stroke_width, &lb, 0, NULL);
+ if (pen == NULL) {
+ DeleteObject(clipregion);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ HGDIOBJ penbak = SelectObject(hdc, (HGDIOBJ) pen);
+ if (penbak == NULL) {
+ DeleteObject(clipregion);
+ DeleteObject(pen);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ HBRUSH brush = CreateBrushIndirect(&lb1);
+ if (brush == NULL) {
+ DeleteObject(clipregion);
+ SelectObject(hdc, penbak);
+ DeleteObject(pen);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ HGDIOBJ brushbak = SelectObject(hdc, (HGDIOBJ) brush);
+ if (brushbak == NULL) {
+ DeleteObject(clipregion);
+ SelectObject(hdc, penbak);
+ DeleteObject(pen);
+ DeleteObject(brush);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ RECT r;
+ r.left = x0;
+ r.top = y0;
+ r.right = x1;
+ r.bottom = y1;
+
+ SelectClipRgn(hdc, clipregion);
+
+ Rectangle(hdc, x0, y0, x1, y1);
+
+ SelectClipRgn(hdc, NULL);
+/* ValidateRect(current_hwnd, &r);
+*/
+ pen = SelectObject(hdc, penbak);
+ brush = SelectObject(hdc, brushbak);
+ DeleteObject(clipregion);
+ DeleteObject(pen);
+ DeleteObject(brush);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return true;
+}
+
+
+static bool polygon(const int *p, unsigned int n, const plot_style_t *style)
+{
+#if NSWS_PLOT_DEBUG
+ LOG(("polygon %d points thumbnail %d", n, thumbnail));
+#endif
+ POINT points[n];
+ unsigned int i;
+ HDC hdc = doublebuffering ? bufferdc : GetDC(current_hwnd);
+ if (hdc == NULL) {
+ return false;
+ }
+ RECT *clipr = gui_window_clip_rect(current_gui);
+ if (clipr == NULL)
+ clipr = &localhistory_clip;
+ HRGN clipregion = CreateRectRgnIndirect(clipr);
+ if (clipregion == NULL) {
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ COLORREF pencol = (DWORD)(style->fill_colour & 0x00FFFFFF);
+ COLORREF brushcol = (DWORD)(style->fill_colour & 0x00FFFFFF);
+ HPEN pen = CreatePen(PS_GEOMETRIC | PS_NULL, 1, pencol);
+ if (pen == NULL) {
+ DeleteObject(clipregion);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ HPEN penbak = SelectObject(hdc, pen);
+ if (penbak == NULL) {
+ DeleteObject(clipregion);
+ DeleteObject(pen);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ HBRUSH brush = CreateSolidBrush(brushcol);
+ if (brush == NULL) {
+ DeleteObject(clipregion);
+ SelectObject(hdc, penbak);
+ DeleteObject(pen);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ HBRUSH brushbak = SelectObject(hdc, brush);
+ if (brushbak == NULL) {
+ DeleteObject(clipregion);
+ SelectObject(hdc, penbak);
+ DeleteObject(pen);
+ DeleteObject(brush);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ SetPolyFillMode(hdc, WINDING);
+ for (i = 0; i < n; i++) {
+ points[i].x = (long) p[2 * i];
+ points[i].y = (long) (p[2 * i + 1]
+ + (thumbnail ? 0 :
+ gui_window_voffset(current_gui)));
+
+#if NSWS_PLOT_DEBUG
+ printf ("%ld,%ld ", points[i].x, points[i].y);
+#endif
+ }
+
+ SelectClipRgn(hdc, clipregion);
+
+ if (n >= 2)
+ Polygon(hdc, points, n);
+
+ SelectClipRgn(hdc, NULL);
+
+ pen = SelectObject(hdc, penbak);
+ brush = SelectObject(hdc, brushbak);
+ DeleteObject(clipregion);
+ DeleteObject(pen);
+ DeleteObject(brush);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+#if NSWS_PLOT_DEBUG
+ printf("\n");
+#endif
+ return true;
+}
+
+
+static bool text(int x, int y, const char *text, size_t length,
+ const plot_font_style_t *style)
+{
+#if NSWS_PLOT_DEBUG
+ LOG(("words %s at %d,%d thumbnail %d", text, x, y, thumbnail));
+#endif
+ HDC hdc = doublebuffering ? bufferdc : GetDC(current_hwnd);
+ if (hdc == NULL) {
+ return false;
+ }
+ RECT *clipr = gui_window_clip_rect(current_gui);
+ if (clipr == NULL)
+ clipr = &localhistory_clip;
+ HRGN clipregion = CreateRectRgnIndirect(clipr);
+ if (clipregion == NULL) {
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+
+ HFONT fontbak, font = get_font(style);
+ if (font == NULL) {
+ DeleteObject(clipregion);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ int wlen;
+ SIZE s;
+ LPWSTR wstring;
+ RECT r;
+ fontbak = (HFONT) SelectObject(hdc, font);
+ GetTextExtentPoint(hdc, text, length, &s);
+
+ y += (thumbnail ? 0 : gui_window_voffset(current_gui));
+ r.left = x;
+ r.top = y - (3 * s.cy) / 4;
+ r.right = x + s.cx;
+ r.bottom = y + s.cy / 4;
+
+ SelectClipRgn(hdc, clipregion);
+
+ SetTextAlign(hdc, TA_BASELINE | TA_LEFT);
+ if ((style->background & 0xFF000000) != 0x01000000)
+ /* 100% alpha */
+ SetBkColor(hdc, (DWORD) (style->background & 0x00FFFFFF));
+ SetBkMode(hdc, TRANSPARENT);
+ SetTextColor(hdc, (DWORD) (style->foreground & 0x00FFFFFF));
+
+ wlen = MultiByteToWideChar(CP_UTF8, 0, text, length, NULL, 0);
+ wstring = malloc(2 * (wlen + 1));
+ if (wstring == NULL) {
+ return false;
+ }
+ MultiByteToWideChar(CP_UTF8, 0, text, length, wstring, wlen);
+ TextOutW(hdc, x, y, wstring, wlen);
+
+ SelectClipRgn(hdc, NULL);
+/* ValidateRect(current_hwnd, &r);
+*/
+ free(wstring);
+ font = SelectObject(hdc, fontbak);
+ DeleteObject(clipregion);
+ DeleteObject(font);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return true;
+}
+
+static bool disc(int x, int y, int radius, const plot_style_t *style)
+{
+ y += (thumbnail ? 0 : gui_window_voffset(current_gui));
+#if NSWS_PLOT_DEBUG
+ LOG(("disc at %d,%d radius %d thumbnail %d", x, y, radius, thumbnail));
+#endif
+ HDC hdc = doublebuffering ? bufferdc : GetDC(current_hwnd);
+ if (hdc == NULL) {
+ return false;
+ }
+ RECT *clipr = gui_window_clip_rect(current_gui);
+ if (clipr == NULL)
+ clipr = &localhistory_clip;
+ HRGN clipregion = CreateRectRgnIndirect(clipr);
+ if (clipregion == NULL) {
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+
+ COLORREF col = (DWORD)((style->fill_colour | style->stroke_colour)
+ & 0x00FFFFFF);
+ HPEN pen = CreatePen(PS_GEOMETRIC | PS_SOLID, 1, col);
+ if (pen == NULL) {
+ DeleteObject(clipregion);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ HGDIOBJ penbak = SelectObject(hdc, (HGDIOBJ) pen);
+ if (penbak == NULL) {
+ DeleteObject(clipregion);
+ DeleteObject(pen);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ HBRUSH brush = CreateSolidBrush(col);
+ if (brush == NULL) {
+ DeleteObject(clipregion);
+ SelectObject(hdc, penbak);
+ DeleteObject(pen);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ HGDIOBJ brushbak = SelectObject(hdc, (HGDIOBJ) brush);
+ if (brushbak == NULL) {
+ DeleteObject(clipregion);
+ SelectObject(hdc, penbak);
+ DeleteObject(pen);
+ DeleteObject(brush);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ RECT r;
+ r.left = x - radius;
+ r.top = y - radius;
+ r.right = x + radius;
+ r.bottom = y + radius;
+
+ SelectClipRgn(hdc, clipregion);
+
+ if (style->fill_type == PLOT_OP_TYPE_NONE)
+ Arc(hdc, x - radius, y - radius, x + radius, y + radius,
+ x - radius, y - radius,
+ x - radius, y - radius);
+ else
+ Ellipse(hdc, x - radius, y - radius, x + radius, y + radius);
+
+ SelectClipRgn(hdc, NULL);
+/* ValidateRect(current_hwnd, &r);
+*/
+ pen = SelectObject(hdc, penbak);
+ brush = SelectObject(hdc, brushbak);
+ DeleteObject(clipregion);
+ DeleteObject(pen);
+ DeleteObject(brush);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return true;
+}
+
+static bool arc(int x, int y, int radius, int angle1, int angle2,
+ const plot_style_t *style)
+{
+ y += (thumbnail ? 0 : gui_window_voffset(current_gui));
+#if NSWS_PLOT_DEBUG
+ LOG(("arc centre %d,%d radius %d from %d to %d", x, y, radius,
+ angle1, angle2));
+#endif
+ HDC hdc = doublebuffering ? bufferdc : GetDC(current_hwnd);
+ if (hdc == NULL) {
+ return false;
+ }
+ RECT *clipr = gui_window_clip_rect(current_gui);
+ if (clipr == NULL)
+ clipr = &localhistory_clip;
+ HRGN clipregion = CreateRectRgnIndirect(clipr);
+ if (clipregion == NULL) {
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ COLORREF col = (DWORD)(style->stroke_colour & 0x00FFFFFF);
+ HPEN pen = CreatePen(PS_GEOMETRIC | PS_SOLID, 1, col);
+ if (pen == NULL) {
+ DeleteObject(clipregion);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ HGDIOBJ penbak = SelectObject(hdc, (HGDIOBJ) pen);
+ if (penbak == NULL) {
+ DeleteObject(clipregion);
+ DeleteObject(pen);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ RECT r;
+ int q1, q2;
+ double a1=1.0, a2=1.0, b1=1.0, b2=1.0;
+ q1 = (int) ((angle1 + 45) / 90) - 45;
+ q2 = (int) ((angle2 + 45) / 90) - 45;
+ while (q1 > 4)
+ q1 -= 4;
+ while (q2 > 4)
+ q2 -= 4;
+ while (q1 <= 0)
+ q1 += 4;
+ while (q2 <= 0)
+ q2 += 4;
+ angle1 = ((angle1 + 45) % 90) - 45;
+ angle2 = ((angle2 + 45) % 90) - 45;
+
+ switch(q1) {
+ case 1:
+ a1 = 1.0;
+ b1 = -tan((M_PI / 180) * angle1);
+ break;
+ case 2:
+ b1 = -1.0;
+ a1 = -tan((M_PI / 180) * angle1);
+ break;
+ case 3:
+ a1 = -1.0;
+ b1 = tan((M_PI / 180) * angle1);
+ break;
+ case 4:
+ b1 = 1.0;
+ a1 = tan((M_PI / 180) * angle1);
+ break;
+ }
+
+ switch(q2) {
+ case 1:
+ a2 = 1.0;
+ b2 = -tan((M_PI / 180) * angle2);
+ break;
+ case 2:
+ b2 = -1.0;
+ a2 = -tan((M_PI / 180) * angle2);
+ break;
+ case 3:
+ a2 = -1.0;
+ b2 = tan((M_PI / 180) * angle2);
+ break;
+ case 4:
+ b2 = 1.0;
+ a2 = tan((M_PI / 180) * angle2);
+ break;
+ }
+
+ r.left = x - radius;
+ r.top = y - radius;
+ r.right = x + radius;
+ r.bottom = y + radius;
+
+ SelectClipRgn(hdc, clipregion);
+
+ Arc(hdc, x - radius, y - radius, x + radius, y + radius,
+ x + (int)(a1 * radius), y + (int)(b1 * radius),
+ x + (int)(a2 * radius), y + (int)(b2 * radius));
+
+ SelectClipRgn(hdc, NULL);
+/* ValidateRect(current_hwnd, &r);
+*/
+ pen = SelectObject(hdc, penbak);
+ DeleteObject(clipregion);
+ DeleteObject(pen);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return true;
+}
+
+
+static bool bitmap(int x, int y, int width, int height,
+ struct bitmap *bitmap, colour bg,
+ bitmap_flags_t flags)
+{
+#if NSWS_PLOT_DEBUG
+ LOG(("%p bitmap %d,%d width %d height %d", current_hwnd, x, y, width,
+ height));
+#endif
+ if (bitmap == NULL)
+ return false;
+ int voffset = (thumbnail ? 0 : gui_window_voffset(current_gui));
+ y += voffset;
+ HDC hdc = doublebuffering ? bufferdc : GetDC(current_hwnd);
+ if (hdc == NULL) {
+ return false;
+ }
+ RECT *cliprect = gui_window_clip_rect(current_gui);
+ if (cliprect == NULL)
+ cliprect = &localhistory_clip;
+ HRGN clipregion = CreateRectRgnIndirect(cliprect);
+ if (clipregion == NULL) {
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ HDC Memhdc = CreateCompatibleDC(hdc);
+ if (Memhdc == NULL) {
+ DeleteObject(clipregion);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ BITMAPINFOHEADER bmih;
+ RECT r;
+ int v, vv, vi, h, hh, width4, transparency;
+ unsigned char alpha;
+ bool modifying = false;
+
+ SelectClipRgn(hdc, clipregion);
+ if ((bitmap->width != width) || (bitmap->height != height)) {
+ bitmap = bitmap_scale(bitmap, width, height);
+ if (bitmap == NULL)
+ return false;
+ modifying = true;
+ }
+
+ if ((flags & BITMAPF_REPEAT_X) || (flags & BITMAPF_REPEAT_Y)) {
+ struct bitmap *prebitmap = bitmap_pretile(bitmap,
+ cliprect->right - x,
+ cliprect->bottom - y, flags);
+ if (prebitmap == NULL)
+ return false;
+ if (modifying) {
+ free(bitmap->pixdata);
+ free(bitmap);
+ }
+ modifying = true;
+ bitmap = prebitmap;
+ }
+ BITMAP MemBM;
+ BITMAPINFO *bmi = (BITMAPINFO *) malloc(sizeof(BITMAPINFOHEADER) +
+ (bitmap->width * bitmap->height * 4));
+ if (bmi == NULL) {
+ DeleteObject(clipregion);
+ DeleteDC(Memhdc);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+ HBITMAP MemBMh = CreateCompatibleBitmap(
+ hdc, bitmap->width, bitmap->height);
+ if (MemBMh == NULL){
+ DeleteObject(clipregion);
+ free(bmi);
+ DeleteDC(Memhdc);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+
+ /* save 'background' data for alpha channel work */
+ SelectObject(Memhdc, MemBMh);
+ BitBlt(Memhdc, 0, 0, bitmap->width, bitmap->height, hdc, x, y,
+ SRCCOPY);
+ GetObject(MemBMh, sizeof(BITMAP), &MemBM);
+
+ bmih.biSize = sizeof(bmih);
+ bmih.biWidth = bitmap->width;
+ bmih.biHeight = bitmap->height;
+ bmih.biPlanes = 1;
+ bmih.biBitCount = 32;
+ bmih.biCompression = BI_RGB;
+ bmih.biSizeImage = 4 * bitmap->height * bitmap->width;
+ bmih.biXPelsPerMeter = 3600; /* 100 dpi */
+ bmih.biYPelsPerMeter = 3600;
+ bmih.biClrUsed = 0;
+ bmih.biClrImportant = 0;
+ bmi->bmiHeader = bmih;
+
+ GetDIBits(hdc, MemBMh, 0, bitmap->height, bmi->bmiColors, bmi,
+ DIB_RGB_COLORS);
+
+ /* then load 'foreground' bits from bitmap->pixdata */
+
+ width4 = bitmap->width * 4;
+ for (v = 0, vv = 0, vi = (bitmap->height - 1) * width4;
+ v < bitmap->height;
+ v++, vv += bitmap->width, vi -= width4) {
+ for (h = 0, hh = 0; h < bitmap->width; h++, hh += 4) {
+ alpha = bitmap->pixdata[vi + hh + 3];
+/* multiplication of alpha value; subject to profiling could be optional */
+ if (alpha == 0xFF) {
+ bmi->bmiColors[vv + h].rgbBlue =
+ bitmap->pixdata[vi + hh + 2];
+ bmi->bmiColors[vv + h].rgbGreen =
+ bitmap->pixdata[vi + hh + 1];
+ bmi->bmiColors[vv + h].rgbRed =
+ bitmap->pixdata[vi + hh];
+ } else if (alpha > 0) {
+ transparency = 0x100 - alpha;
+ bmi->bmiColors[vv + h].rgbBlue =
+ (bmi->bmiColors[vv + h].rgbBlue
+ * transparency +
+ (bitmap->pixdata[vi + hh + 2]) *
+ alpha) >> 8;
+ bmi->bmiColors[vv + h].rgbGreen =
+ (bmi->bmiColors[vv + h].
+ rgbGreen
+ * transparency +
+ (bitmap->pixdata[vi + hh + 1]) *
+ alpha) >> 8;
+ bmi->bmiColors[vv + h].rgbRed =
+ (bmi->bmiColors[vv + h].rgbRed
+ * transparency +
+ bitmap->pixdata[vi + hh]
+ * alpha) >> 8;
+ }
+/* alternative simple 2/3 stage alpha value handling */
+/* if (bitmap->pixdata[vi + hh + 3] > 0xAA) {
+ bmi->bmiColors[vv + h].rgbBlue =
+ bitmap->pixdata[vi + hh + 2];
+ bmi->bmiColors[vv + h].rgbGreen =
+ bitmap->pixdata[vi + hh + 1];
+ bmi->bmiColors[vv + h].rgbRed =
+ bitmap->pixdata[vi + hh];
+ } else if (bitmap->pixdata[vi + hh + 3] > 0x70){
+ bmi->bmiColors[vv + h].rgbBlue =
+ (bmi->bmiColors[vv + h].rgbBlue +
+ bitmap->pixdata[vi + hh + 2]) / 2;
+ bmi->bmiColors[vv + h].rgbRed =
+ (bmi->bmiColors[vv + h].rgbRed +
+ bitmap->pixdata[vi + hh]) / 2;
+ bmi->bmiColors[vv + h].rgbGreen =
+ (bmi->bmiColors[vv + h].rgbGreen +
+ bitmap->pixdata[vi + hh + 1]) / 2;
+ } else if (bitmap->pixdata[vi + hh + 3] > 0x30){
+ bmi->bmiColors[vv + h].rgbBlue =
+ (bmi->bmiColors[vv + h].rgbBlue * 3 +
+ bitmap->pixdata[vi + hh + 2]) / 4;
+ bmi->bmiColors[vv + h].rgbRed =
+ (bmi->bmiColors[vv + h].rgbRed * 3 +
+ bitmap->pixdata[vi + hh]) / 4;
+ bmi->bmiColors[vv + h].rgbGreen =
+ (bmi->bmiColors[vv + h].rgbGreen * 3 +
+ bitmap->pixdata[vi + hh + 1]) / 4;
+ }
+*/ }
+ }
+ SetDIBitsToDevice(hdc, x, y, bitmap->width, bitmap->height,
+ 0, 0, 0, bitmap->height, (const void *) bmi->bmiColors,
+ bmi, DIB_RGB_COLORS);
+
+ r.left = x;
+ r.top = y;
+ r.right = x + bitmap->width;
+ r.bottom = y + bitmap->height;
+ if (modifying && bitmap && bitmap->pixdata) {
+ free(bitmap->pixdata);
+ free(bitmap);
+ }
+
+/* ValidateRect(current_hwnd, &r);
+*/ free(bmi);
+/* SelectClipRgn(hdc, NULL);
+*/ DeleteObject(clipregion);
+ DeleteObject(MemBMh);
+ DeleteDC(Memhdc);
+ if (!doublebuffering)
+ ReleaseDC(current_hwnd, hdc);
+ return true;
+}
+
+static bool flush(void)
+{
+#if NSWS_PLOT_DEBUG
+ LOG(("flush unimplemented"));
+#endif
+ return true;
+}
+
+static bool path(const float *p, unsigned int n, colour fill, float width,
+ colour c, const float transform[6])
+{
+#if NSWS_PLOT_DEBUG
+ LOG(("path unimplemented"));
+#endif
+ return true;
+}
+
+void nsws_plot_set_scale(float s)
+{
+ nsws_plot_scale = s;
+}
+
+float nsws_plot_get_scale(void)
+{
+ return nsws_plot_scale;
+}
+
+struct plotter_table plot = {
+ .rectangle = rectangle,
+ .line = line,
+ .polygon = polygon,
+ .clip = clip,
+ .text = text,
+ .disc = disc,
+ .arc = arc,
+ .bitmap = bitmap,
+ .flush = flush,
+ .path = path,
+ .option_knockout = true,
+};
diff --git a/windows/plot.h b/windows/plot.h
new file mode 100644
index 000000000..1502412dd
--- /dev/null
+++ b/windows/plot.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <windows.h>
+#include "desktop/gui.h"
+
+extern HWND current_hwnd;
+extern struct gui_window *current_gui;
+extern HDC bufferdc;
+extern bool doublebuffering;
+extern bool thumbnail;
+
+void nsws_plot_set_scale(float s);
+float nsws_plot_get_scale(void);
+
diff --git a/windows/prefs.c b/windows/prefs.c
new file mode 100644
index 000000000..f41f96663
--- /dev/null
+++ b/windows/prefs.c
@@ -0,0 +1,635 @@
+/*
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <windows.h>
+#define _WIN32_IE (0x0501)
+#include <commctrl.h>
+#include "desktop/options.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+#include "windows/gui.h"
+#include "windows/prefs.h"
+#include "windows/resourceid.h"
+
+#define NSWS_PREFS_WINDOW_WIDTH 600
+#define NSWS_PREFS_WINDOW_HEIGHT 400
+
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+/* static HWND prefswindow = NULL; */
+
+void nsws_prefs_window_create(HWND parent);
+BOOL CALLBACK nsws_prefs_event_callback(HWND hwnd, UINT msg, WPARAM wparam,
+ LPARAM lparam);
+CHOOSEFONT *nsws_prefs_font_prepare(int fontfamily, HWND parent);
+
+void nsws_prefs_dialog_init(HWND parent)
+{
+ int ret = DialogBox(hinstance, MAKEINTRESOURCE(NSWS_ID_PREFS_DIALOG),
+ parent, nsws_prefs_event_callback);
+ if (ret == -1) {
+ warn_user(messages_get("NoMemory"), 0);
+ return;
+ }
+}
+
+
+BOOL CALLBACK nsws_prefs_event_callback(HWND hwnd, UINT msg, WPARAM wparam,
+ LPARAM lparam)
+{
+ HWND sub;
+ char *temp, number[6];
+ int len;
+ switch(msg) {
+ case WM_INITDIALOG: {
+ if ((option_homepage_url != NULL) &&
+ (option_homepage_url[0] != '\0')) {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_HOMEPAGE);
+ SendMessage(sub, WM_SETTEXT, 0,
+ (LPARAM)option_homepage_url);
+ }
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_PROXYTYPE);
+ SendMessage(sub, CB_ADDSTRING, 0, (LPARAM)"None");
+ SendMessage(sub, CB_ADDSTRING, 0, (LPARAM)"Simple");
+ SendMessage(sub, CB_ADDSTRING, 0, (LPARAM)"Basic Auth");
+ SendMessage(sub, CB_ADDSTRING, 0, (LPARAM)"NTLM Auth");
+ if (option_http_proxy)
+ SendMessage(sub, CB_SETCURSEL, (WPARAM)
+ (option_http_proxy_auth + 1), 0);
+ else
+ SendMessage(sub, CB_SETCURSEL, 0, 0);
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_PROXYHOST);
+ if ((option_http_proxy_host != NULL) &&
+ (option_http_proxy_host[0] != '\0'))
+ SendMessage(sub, WM_SETTEXT, 0,
+ (LPARAM)option_http_proxy_host);
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_PROXYPORT);
+ if (option_http_proxy_port != 0) {
+ snprintf(number, 6, "%d", option_http_proxy_port);
+ SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number);
+ }
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_PROXYNAME);
+ if ((option_http_proxy_auth_user != NULL) &&
+ (option_http_proxy_auth_user[0] != '\0'))
+ SendMessage(sub, WM_SETTEXT, 0,
+ (LPARAM)option_http_proxy_auth_user);
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_PROXYPASS);
+ if ((option_http_proxy_auth_pass != NULL) &&
+ (option_http_proxy_auth_pass[0] != '\0'))
+ SendMessage(sub, WM_SETTEXT, 0,
+ (LPARAM)option_http_proxy_auth_pass);
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FONTDEF);
+ SendMessage(sub, CB_ADDSTRING, 0, (LPARAM)"Sans serif");
+ SendMessage(sub, CB_ADDSTRING, 0, (LPARAM)"Serif");
+ SendMessage(sub, CB_ADDSTRING, 0, (LPARAM)"Monospace");
+ SendMessage(sub, CB_ADDSTRING, 0, (LPARAM)"Cursive");
+ SendMessage(sub, CB_ADDSTRING, 0, (LPARAM)"Fantasy");
+ SendMessage(sub, CB_SETCURSEL,
+ (WPARAM) (option_font_default - 1), 0);
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_ADVERTS);
+ SendMessage(sub, BM_SETCHECK, (WPARAM) ((option_block_ads) ?
+ BST_CHECKED : BST_UNCHECKED), 0);
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_REFERER);
+ SendMessage(sub, BM_SETCHECK, (WPARAM)((option_send_referer) ?
+ BST_CHECKED : BST_UNCHECKED), 0);
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_NOANIMATION);
+ SendMessage(sub, BM_SETCHECK, (WPARAM)((option_animate_images)
+ ? BST_UNCHECKED : BST_CHECKED), 0);
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FETCHERS);
+ snprintf(number, 6, "%d", option_max_fetchers);
+ SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number);
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FETCH_HOST);
+ snprintf(number, 6, "%d", option_max_fetchers_per_host);
+ SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number);
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FETCH_HANDLES);
+ snprintf(number, 6, "%d", option_max_cached_fetch_handles);
+ SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number);
+
+ if ((option_font_sans != NULL) &&
+ (option_font_sans[0] != '\0')) {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_SANS);
+ SendMessage(sub, WM_SETTEXT, 0,
+ (LPARAM)option_font_sans);
+ }
+ if ((option_font_serif != NULL) &&
+ (option_font_serif[0] != '\0')) {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_SERIF);
+ SendMessage(sub, WM_SETTEXT, 0,
+ (LPARAM)option_font_serif);
+ }
+ if ((option_font_mono != NULL) &&
+ (option_font_mono[0] != '\0')) {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_MONO);
+ SendMessage(sub, WM_SETTEXT, 0,
+ (LPARAM)option_font_mono);
+ }
+ if ((option_font_cursive != NULL) &&
+ (option_font_cursive[0] != '\0')) {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_CURSIVE);
+ SendMessage(sub, WM_SETTEXT, 0,
+ (LPARAM)option_font_cursive);
+ }
+ if ((option_font_fantasy != NULL) &&
+ (option_font_fantasy[0] != '\0')) {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FANTASY);
+ SendMessage(sub, WM_SETTEXT, 0,
+ (LPARAM)option_font_fantasy);
+ }
+ if (option_font_min_size != 0) {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FONT_MINSIZE);
+ snprintf(number, 6, "%.1f", option_font_min_size /
+ 10.0);
+ SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number);
+ }
+ if (option_font_size != 0) {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FONT_SIZE);
+ snprintf(number, 6, "%.1f", option_font_size / 10.0);
+ SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number);
+ }
+ if (option_max_fetchers != 0) {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FETCHERS);
+ snprintf(number, 6, "%d", option_max_fetchers);
+ SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number);
+ }
+ if (option_max_fetchers_per_host != 0) {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FETCH_HOST);
+ snprintf(number, 6, "%d",
+ option_max_fetchers_per_host);
+ SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number);
+ }
+ if (option_max_cached_fetch_handles != 0) {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FETCH_HANDLES);
+ snprintf(number, 6, "%d",
+ option_max_cached_fetch_handles);
+ SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number);
+ }
+ if (option_minimum_gif_delay != 0) {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_ANIMATIONDELAY);
+ snprintf(number, 6, "%.1f", option_minimum_gif_delay /
+ 100.0);
+ SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number);
+ }
+ return TRUE;
+ }
+ case WM_CREATE:
+ return TRUE;
+ case WM_COMMAND:
+ switch(LOWORD(wparam)) {
+ case IDOK: {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_HOMEPAGE);
+ len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0);
+ if (option_homepage_url != NULL)
+ free(option_homepage_url);
+ option_homepage_url = malloc(len + 1);
+ if (option_homepage_url != NULL)
+ SendMessage(sub, WM_GETTEXT,
+ (WPARAM) (len + 1),
+ (LPARAM) option_homepage_url);
+/* seems to segfault at startup
+
+ option_block_ads = (IsDlgButtonChecked(hwnd,
+ NSWS_ID_PREFS_ADVERTS) == BST_CHECKED)
+ ? true : false;
+*/
+ option_send_referer = (IsDlgButtonChecked(hwnd,
+ NSWS_ID_PREFS_REFERER) == BST_CHECKED)
+ ? true : false;
+ option_animate_images = (IsDlgButtonChecked(hwnd,
+ NSWS_ID_PREFS_NOANIMATION) ==
+ BST_CHECKED) ? false : true;
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FETCHERS);
+ len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0);
+ temp = malloc(len + 1);
+ if (temp != NULL) {
+ SendMessage(sub, WM_GETTEXT, (WPARAM)(len + 1),
+ (LPARAM)temp);
+ option_max_fetchers = atoi(temp);
+ free(temp);
+ }
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FETCH_HOST);
+ len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0);
+ temp = malloc(len + 1);
+ if (temp != NULL) {
+ SendMessage(sub, WM_GETTEXT, (WPARAM)(len + 1),
+ (LPARAM)temp);
+ option_max_fetchers_per_host = atoi(temp);
+ free(temp);
+ }
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FETCH_HANDLES);
+ len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0);
+ temp = malloc(len + 1);
+ if (temp != NULL) {
+ SendMessage(sub, WM_GETTEXT, (WPARAM)(len + 1),
+ (LPARAM)temp);
+ option_max_cached_fetch_handles = atoi(temp);
+ free(temp);
+ }
+ sub = GetDlgItem(hwnd,
+ NSWS_ID_PREFS_FONT_SIZE);
+ len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0);
+ temp = malloc(len + 1);
+ if (temp != NULL) {
+ SendMessage(sub, WM_GETTEXT, (WPARAM)
+ (len + 1), (LPARAM) temp);
+ option_font_size = (int)
+ (10 * strtod(temp, NULL));
+ free(temp);
+ }
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FONT_MINSIZE);
+ len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0);
+ temp = malloc(len + 1);
+ if (temp != NULL) {
+ SendMessage(sub, WM_GETTEXT, (WPARAM)
+ (len + 1), (LPARAM) temp);
+ option_font_min_size = (int)
+ (10 * strtod(temp, NULL));
+ free(temp);
+ }
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_ANIMATIONDELAY);
+ len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0);
+ temp = malloc(len + 1);
+ if (temp != NULL) {
+ SendMessage(sub, WM_GETTEXT, (WPARAM)
+ (len + 1), (LPARAM) temp);
+ option_minimum_gif_delay = (int)
+ (100 * strtod(temp, NULL));
+ free(temp);
+ }
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_PROXYHOST);
+ len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0);
+ temp = malloc(len + 1);
+ if (temp != NULL) {
+ if (option_http_proxy_host != NULL)
+ free(option_http_proxy_host);
+ SendMessage(sub, WM_GETTEXT, (WPARAM)(len + 1),
+ (LPARAM)temp);
+ option_http_proxy_host = strdup(temp);
+ free(temp);
+ }
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_PROXYPORT);
+ len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0);
+ temp = malloc(len + 1);
+ if (temp != NULL) {
+ SendMessage(sub, WM_GETTEXT, (WPARAM)(len + 1),
+ (LPARAM)temp);
+ option_http_proxy_port = atoi(temp);
+ free(temp);
+ }
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_PROXYNAME);
+ len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0);
+ temp = malloc(len + 1);
+ if (temp != NULL) {
+ if (option_http_proxy_auth_user != NULL)
+ free(option_http_proxy_auth_user);
+ SendMessage(sub, WM_GETTEXT, (WPARAM)(len + 1),
+ (LPARAM)temp);
+ option_http_proxy_auth_user = strdup(temp);
+ free(temp);
+ }
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_PROXYPASS);
+ len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0);
+ temp = malloc(len + 1);
+ if (temp != NULL) {
+ if (option_http_proxy_auth_pass != NULL)
+ free(option_http_proxy_auth_pass);
+ SendMessage(sub, WM_GETTEXT, (WPARAM)(len + 1),
+ (LPARAM)temp);
+ option_http_proxy_auth_pass = strdup(temp);
+ free(temp);
+ }
+ options_write(options_file_location);
+ }
+ case IDCANCEL:
+ EndDialog(hwnd, IDOK);
+ break;
+ case NSWS_ID_PREFS_HOMEPAGE:
+ break;
+ case NSWS_ID_PREFS_ADVERTS:
+ break;
+ case NSWS_ID_PREFS_POPUPS:
+ printf("wparam %d, lparam %ld hi %d lo %d\n", wparam,
+ lparam, HIWORD(lparam),
+ LOWORD(lparam));
+ break;
+ case NSWS_ID_PREFS_PLUGINS:
+ printf("wparam %d, lparam %ld hi %d lo %d\n", wparam,
+ lparam, HIWORD(lparam),
+ LOWORD(lparam));
+ break;
+ case NSWS_ID_PREFS_REFERER:
+ printf("wparam %d, lparam %ld hi %d lo %d\n", wparam,
+ lparam, HIWORD(lparam),
+ LOWORD(lparam));
+ break;
+ case NSWS_ID_PREFS_PROXYTYPE:
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_PROXYTYPE);
+ option_http_proxy_auth = SendMessage(sub,
+ CB_GETCURSEL, 0, 0) - 1;
+ option_http_proxy = (option_http_proxy_auth != -1);
+ option_http_proxy_auth += (option_http_proxy) ? 0 : 1;
+ break;
+ case NSWS_ID_PREFS_PROXYHOST:
+ break;
+ case NSWS_ID_PREFS_PROXYNAME:
+ break;
+ case NSWS_ID_PREFS_PROXYPASS:
+ break;
+ case NSWS_ID_PREFS_SANS: {
+ CHOOSEFONT *cf = nsws_prefs_font_prepare(FF_SWISS,
+ hwnd);
+ if (cf == NULL)
+ break;
+ if (ChooseFont(cf) == TRUE) {
+ if (option_font_sans != NULL)
+ free(option_font_sans);
+ option_font_sans = strdup(
+ cf->lpLogFont->lfFaceName);
+ }
+ free(cf->lpLogFont);
+ free(cf);
+ if ((option_font_sans != NULL) &&
+ (option_font_sans[0] != '\0')) {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_SANS);
+ SendMessage(sub, WM_SETTEXT, 0,
+ (LPARAM)option_font_sans);
+ }
+ break;
+ }
+ case NSWS_ID_PREFS_SERIF: {
+ CHOOSEFONT *cf = nsws_prefs_font_prepare(FF_ROMAN,
+ hwnd);
+ if (cf == NULL)
+ break;
+
+ if (ChooseFont(cf) == TRUE) {
+ if (option_font_serif != NULL)
+ free(option_font_serif);
+ option_font_serif = strdup(
+ cf->lpLogFont->lfFaceName);
+ }
+ free(cf->lpLogFont);
+ free(cf);
+ if ((option_font_serif != NULL) &&
+ (option_font_serif[0] != '\0')) {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_SERIF);
+ SendMessage(sub, WM_SETTEXT, 0,
+ (LPARAM)option_font_serif);
+ }
+ break;
+ }
+ case NSWS_ID_PREFS_MONO: {
+ CHOOSEFONT *cf = nsws_prefs_font_prepare(FF_MODERN,
+ hwnd);
+ if (cf == NULL)
+ break;
+
+ if (ChooseFont(cf) == TRUE) {
+ if (option_font_mono != NULL)
+ free(option_font_mono);
+ option_font_mono = strdup(
+ cf->lpLogFont->lfFaceName);
+ }
+ free(cf->lpLogFont);
+ free(cf);
+ if ((option_font_mono != NULL) &&
+ (option_font_mono[0] != '\0')) {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_MONO);
+ SendMessage(sub, WM_SETTEXT, 0,
+ (LPARAM)option_font_mono);
+ }
+ break;
+ }
+ case NSWS_ID_PREFS_CURSIVE: {
+ CHOOSEFONT *cf = nsws_prefs_font_prepare(FF_SCRIPT,
+ hwnd);
+ if (cf == NULL)
+ break;
+
+ if (ChooseFont(cf) == TRUE) {
+ if (option_font_cursive != NULL)
+ free(option_font_cursive);
+ option_font_cursive = strdup(
+ cf->lpLogFont->lfFaceName);
+ }
+ free(cf->lpLogFont);
+ free(cf);
+ if ((option_font_cursive != NULL) &&
+ (option_font_cursive[0] != '\0')) {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_CURSIVE);
+ SendMessage(sub, WM_SETTEXT, 0,
+ (LPARAM)option_font_cursive);
+ }
+ break;
+ }
+ case NSWS_ID_PREFS_FANTASY: {
+ CHOOSEFONT *cf = nsws_prefs_font_prepare(FF_DECORATIVE,
+ hwnd);
+ if (cf == NULL)
+ break;
+ if (ChooseFont(cf) == TRUE) {
+ if (option_font_fantasy != NULL)
+ free(option_font_fantasy);
+ option_font_fantasy = strdup(
+ cf->lpLogFont->lfFaceName);
+ }
+ free(cf->lpLogFont);
+ free(cf);
+ if ((option_font_fantasy != NULL) &&
+ (option_font_fantasy[0] != '\0')) {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FANTASY);
+ SendMessage(sub, WM_SETTEXT, 0,
+ (LPARAM)option_font_fantasy);
+ }
+ break;
+ }
+ case NSWS_ID_PREFS_FONTDEF: {
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FONTDEF);
+ option_font_default = SendMessage(sub, CB_GETCURSEL, 0, 0) + 1;
+ break;
+ }
+ case NSWS_ID_PREFS_FETCHERS:
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FETCHERS);
+ len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0);
+ temp = malloc(len + 1);
+ if (temp == NULL)
+ return FALSE;
+ SendMessage(sub, WM_GETTEXT, (WPARAM)
+ (len + 1), (LPARAM) temp);
+ option_max_fetchers = atoi(temp);
+ free(temp);
+ break;
+ case NSWS_ID_PREFS_FETCH_HOST:
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FETCH_HOST);
+ len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0);
+ temp = malloc(len + 1);
+ if (temp == NULL)
+ return FALSE;
+ SendMessage(sub, WM_GETTEXT, (WPARAM)
+ (len + 1), (LPARAM) temp);
+ option_max_fetchers_per_host = atoi(temp);
+ free(temp);
+ break;
+ case NSWS_ID_PREFS_FETCH_HANDLES:
+ sub = GetDlgItem(hwnd, NSWS_ID_PREFS_FETCH_HANDLES);
+ len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0);
+ temp = malloc(len + 1);
+ if (temp == NULL)
+ return FALSE;
+ SendMessage(sub, WM_GETTEXT, (WPARAM)
+ (len + 1), (LPARAM) temp);
+ option_max_cached_fetch_handles = atoi(temp);
+ free(temp);
+ break;
+ default:
+ return FALSE;
+ }
+ break;
+ case WM_NOTIFY: {
+ NMHDR *nm = (NMHDR *)lparam;
+ NMUPDOWN *ud = (NMUPDOWN *)lparam;
+ if (nm->code == UDN_DELTAPOS)
+ switch(nm->idFrom) {
+ case NSWS_ID_PREFS_FONT_SIZE_SPIN: {
+ double size = 0;
+ sub = GetDlgItem(hwnd,
+ NSWS_ID_PREFS_FONT_SIZE);
+ len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0);
+ temp = malloc(len + 1);
+ if (temp == NULL)
+ return FALSE;
+ SendMessage(sub, WM_GETTEXT, (WPARAM)
+ (len + 1), (LPARAM) temp);
+ if (ud->iDelta == 1) {
+ size = strtod(temp, NULL) + 0.1;
+ }
+ else if (ud->iDelta == -1) {
+ size = strtod(temp, NULL) - 0.1;
+ }
+ free(temp);
+ size = MAX(size, 0);
+ snprintf(number, 6, "%.1f", size);
+ SendMessage(sub, WM_SETTEXT, 0,
+ (LPARAM)number);
+ return TRUE;
+ }
+ case NSWS_ID_PREFS_FONT_MINSIZE_SPIN: {
+ double size = 0;
+ sub = GetDlgItem(hwnd,
+ NSWS_ID_PREFS_FONT_MINSIZE);
+ len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0);
+ temp = malloc(len + 1);
+ if (temp == NULL)
+ return FALSE;
+ SendMessage(sub, WM_GETTEXT, (WPARAM)
+ (len + 1), (LPARAM) temp);
+ if (ud->iDelta == 1) {
+ size = strtod(temp, NULL) + 0.1;
+ }
+ else if (ud->iDelta == -1) {
+ size = strtod(temp, NULL) - 0.1;
+ }
+ free(temp);
+ size = MAX(size, 0);
+ snprintf(number, 6, "%.1f", size);
+ SendMessage(sub, WM_SETTEXT, 0,
+ (LPARAM)number);
+ return TRUE;
+ }
+ case NSWS_ID_PREFS_ANIMATIONDELAY_SPIN: {
+ double animation=0;
+ sub = GetDlgItem(hwnd,
+ NSWS_ID_PREFS_ANIMATIONDELAY);
+ len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0);
+ temp = malloc(len + 1);
+ if (temp == NULL)
+ return FALSE;
+ SendMessage(sub, WM_GETTEXT, (WPARAM)
+ (len + 1), (LPARAM) temp);
+ if (ud->iDelta == 1) {
+ animation = strtod(temp, NULL) + 0.1;
+ }
+ else if (ud->iDelta == -1) {
+ animation = strtod(temp, NULL) - 0.1;
+ }
+ free(temp);
+ animation = MAX(animation, 0);
+ snprintf(number, 6, "%.1f", animation);
+ SendMessage(sub, WM_SETTEXT, 0,
+ (LPARAM)number);
+ return TRUE;
+ }
+ }
+ break;
+ }
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+CHOOSEFONT *nsws_prefs_font_prepare(int fontfamily, HWND parent)
+{
+ CHOOSEFONT *cf = malloc(sizeof(CHOOSEFONT));
+ if (cf == NULL) {
+ warn_user(messages_get("NoMemory"),0);
+ return NULL;
+ }
+ LOGFONT *lf = malloc(sizeof(LOGFONT));
+ if (lf == NULL) {
+ warn_user(messages_get("NoMemory"),0);
+ free(cf);
+ return NULL;
+ }
+ switch(fontfamily) {
+ case FF_ROMAN:
+ snprintf(lf->lfFaceName, LF_FACESIZE, "%s",
+ option_font_serif);
+ break;
+ case FF_MODERN:
+ snprintf(lf->lfFaceName, LF_FACESIZE, "%s",
+ option_font_mono);
+ break;
+ case FF_SCRIPT:
+ snprintf(lf->lfFaceName, LF_FACESIZE, "%s",
+ option_font_cursive);
+ break;
+ case FF_DECORATIVE:
+ snprintf(lf->lfFaceName, LF_FACESIZE, "%s",
+ option_font_fantasy);
+ break;
+ case FF_SWISS:
+ default:
+ snprintf(lf->lfFaceName, LF_FACESIZE, "%s",
+ option_font_sans);
+ break;
+ }
+ cf->lStructSize = sizeof(CHOOSEFONT);
+ cf->hwndOwner = parent;
+ cf->lpLogFont = lf;
+ cf->Flags = CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT | CF_LIMITSIZE;
+ cf->nSizeMin = 16;
+ cf->nSizeMax = 24;
+
+ return cf;
+}
diff --git a/windows/prefs.h b/windows/prefs.h
new file mode 100644
index 000000000..6662b7a69
--- /dev/null
+++ b/windows/prefs.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_WINDOWS_PREFS_H_
+#define _NETSURF_WINDOWS_PREFS_H_
+
+#include <windows.h>
+
+void nsws_prefs_dialog_init(HWND parent);
+
+#endif
diff --git a/windows/res/Aliases b/windows/res/Aliases
new file mode 120000
index 000000000..a95a734da
--- /dev/null
+++ b/windows/res/Aliases
@@ -0,0 +1 @@
+../../!NetSurf/Resources/Aliases \ No newline at end of file
diff --git a/windows/res/NetSurf16.ico b/windows/res/NetSurf16.ico
new file mode 100644
index 000000000..1cb432828
--- /dev/null
+++ b/windows/res/NetSurf16.ico
Binary files differ
diff --git a/windows/res/NetSurf32.ico b/windows/res/NetSurf32.ico
new file mode 100644
index 000000000..28198ccb6
--- /dev/null
+++ b/windows/res/NetSurf32.ico
Binary files differ
diff --git a/windows/res/back.bmp b/windows/res/back.bmp
new file mode 100644
index 000000000..c0088c9e8
--- /dev/null
+++ b/windows/res/back.bmp
Binary files differ
diff --git a/windows/res/default.css b/windows/res/default.css
new file mode 120000
index 000000000..6d2d4da5b
--- /dev/null
+++ b/windows/res/default.css
@@ -0,0 +1 @@
+../../!NetSurf/Resources/CSS,f79 \ No newline at end of file
diff --git a/windows/res/forward.bmp b/windows/res/forward.bmp
new file mode 100644
index 000000000..e9ff4079c
--- /dev/null
+++ b/windows/res/forward.bmp
Binary files differ
diff --git a/windows/res/home.bmp b/windows/res/home.bmp
new file mode 100644
index 000000000..80bddfd84
--- /dev/null
+++ b/windows/res/home.bmp
Binary files differ
diff --git a/windows/res/messages b/windows/res/messages
new file mode 120000
index 000000000..f4a4d2bba
--- /dev/null
+++ b/windows/res/messages
@@ -0,0 +1 @@
+../../!NetSurf/Resources/en/Messages \ No newline at end of file
diff --git a/windows/res/quirks.css b/windows/res/quirks.css
new file mode 120000
index 000000000..d9fb80334
--- /dev/null
+++ b/windows/res/quirks.css
@@ -0,0 +1 @@
+../../!NetSurf/Resources/Quirks,f79 \ No newline at end of file
diff --git a/windows/res/reload.bmp b/windows/res/reload.bmp
new file mode 100644
index 000000000..0809a6763
--- /dev/null
+++ b/windows/res/reload.bmp
Binary files differ
diff --git a/windows/res/resource.rc b/windows/res/resource.rc
new file mode 100644
index 000000000..ba5a27954
--- /dev/null
+++ b/windows/res/resource.rc
@@ -0,0 +1,217 @@
+// Generated by ResEdit 1.4.8
+// Copyright (C) 2006-2009
+// http://www.resedit.net
+
+#include <windows.h>
+#include <commctrl.h>
+#include <richedit.h>
+#include "resource.h"
+
+
+
+//
+// Menu resources
+//
+//LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+NSWS_ID_CTXMENU MENU
+{
+ POPUP "Context"
+ {
+ MENUITEM "&Back", NSWS_ID_NAV_BACK
+ MENUITEM "F&orward", NSWS_ID_NAV_FORWARD
+ MENUITEM "&Home", NSWS_ID_NAV_HOME
+ MENUITEM "&Stop", NSWS_ID_NAV_STOP
+ MENUITEM "&Reload", NSWS_ID_NAV_RELOAD
+ MENUITEM SEPARATOR
+ MENUITEM "C&ut", NSWS_ID_EDIT_CUT, GRAYED
+ MENUITEM "&Copy", NSWS_ID_EDIT_COPY, GRAYED
+ MENUITEM "&Paste", NSWS_ID_EDIT_PASTE, GRAYED
+ MENUITEM "&Delete", NSWS_ID_EDIT_DELETE, GRAYED
+ }
+}
+
+
+
+//LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+NSWS_ID_MAINMENU MENU
+{
+ POPUP "&File"
+ {
+ MENUITEM "&New Window", NSWS_ID_FILE_OPEN_WINDOW
+ MENUITEM "Open &Location", NSWS_ID_FILE_OPEN_LOCATION
+ MENUITEM "&Close", NSWS_ID_FILE_CLOSE_WINDOW
+ MENUITEM SEPARATOR
+ MENUITEM "&Save Page", NSWS_ID_FILE_SAVE_PAGE, HELP, GRAYED
+ POPUP "Save Page &As"
+ {
+ MENUITEM "Text", NSWS_ID_FILE_SAVEAS_TEXT, GRAYED
+ MENUITEM "PDF", NSWS_ID_FILE_SAVEAS_PDF, GRAYED
+ MENUITEM "Drawfile", NSWS_ID_FILE_SAVEAS_DRAWFILE, GRAYED
+ MENUITEM "Postscript", NSWS_ID_FILE_SAVEAS_POSTSCRIPT, GRAYED
+ }
+ MENUITEM SEPARATOR
+ MENUITEM "Print Pre&view", NSWS_ID_FILE_PRINT_PREVIEW
+ MENUITEM "&Print", NSWS_ID_FILE_PRINT
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", NSWS_ID_FILE_QUIT
+ }
+ POPUP "&Edit"
+ {
+ MENUITEM "Cu&t", NSWS_ID_EDIT_CUT
+ MENUITEM "&Copy", NSWS_ID_EDIT_COPY
+ MENUITEM "&Paste", NSWS_ID_EDIT_PASTE
+ MENUITEM "&Delete", NSWS_ID_EDIT_DELETE
+ MENUITEM SEPARATOR
+ MENUITEM "Select &All", NSWS_ID_EDIT_SELECT_ALL
+ MENUITEM SEPARATOR
+ MENUITEM "&Find", NSWS_ID_EDIT_SEARCH
+ }
+ POPUP "&View"
+ {
+ MENUITEM "Stop", NSWS_ID_NAV_STOP
+ MENUITEM "Reload", NSWS_ID_NAV_RELOAD
+ MENUITEM SEPARATOR
+ POPUP "&Zoom"
+ {
+ MENUITEM "Zoom &In", NSWS_ID_VIEW_ZOOMPLUS
+ MENUITEM "Zoom &Out", NSWS_ID_VIEW_ZOOMMINUS
+ MENUITEM "&Reset", NSWS_ID_VIEW_ZOOMNORMAL
+ }
+ MENUITEM SEPARATOR
+ MENUITEM "Page S&ource", NSWS_ID_VIEW_SOURCE
+ MENUITEM "&Full Screen", NSWS_ID_VIEW_FULLSCREEN
+ }
+ POPUP "&History"
+ {
+ MENUITEM "Back", NSWS_ID_NAV_BACK
+ MENUITEM "Forward", NSWS_ID_NAV_FORWARD
+ MENUITEM "Home", NSWS_ID_NAV_HOME
+ MENUITEM SEPARATOR
+ MENUITEM "Local History", NSWS_ID_NAV_LOCALHISTORY
+ MENUITEM "Global History", NSWS_ID_NAV_GLOBALHISTORY, GRAYED
+ }
+ POPUP "&Tools"
+ {
+ MENUITEM "&Downloads", NSWS_ID_VIEW_DOWNLOADS
+ MENUITEM "Save size and location", NSWS_ID_VIEW_SAVE_WIN_METRICS
+ POPUP "Debugging"
+ {
+ MENUITEM "Debug rendering", NSWS_ID_VIEW_TOGGLE_DEBUG_RENDERING
+ MENUITEM "Save Box Tree", NSWS_ID_VIEW_DEBUGGING_SAVE_BOXTREE, GRAYED
+ MENUITEM "Save DOM Tree", NSWS_ID_VIEW_DEBUGGING_SAVE_DOMTREE, GRAYED
+ }
+ MENUITEM SEPARATOR
+ MENUITEM "Options...", NSWS_ID_EDIT_PREFERENCES
+ }
+ POPUP "&Help"
+ {
+ MENUITEM "&Contents", NSWS_ID_HELP_CONTENTS, GRAYED
+ MENUITEM "G&uide", NSWS_ID_HELP_GUIDE, GRAYED
+ MENUITEM "&Info", NSWS_ID_HELP_INFO, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "&About NetSurf", NSWS_ID_HELP_ABOUT
+ }
+}
+
+
+
+//
+// Dialog resources
+//
+//LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+NSWS_ID_ABOUT_DIALOG DIALOG 0, 0, 400, 400
+STYLE DS_MODALFRAME | DS_SETFONT | WS_BORDER | WS_CAPTION | WS_DLGFRAME | WS_POPUP | WS_SYSMENU
+CAPTION "About NetSurf"
+FONT 8, "MS Sans Serif"
+{
+ DEFPUSHBUTTON "&OK", IDOK, 350, 365, 30, 20
+ GROUPBOX "About NetSurf", IDC_STATIC, 10, 10, 380, 380
+ CTEXT "content", NSWS_ID_ABOUT_CONTENT, 20, 20, 350, 330, SS_CENTER
+}
+
+
+
+//LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+NSWS_ID_DOWNLOAD_DIALOG DIALOG 0, 0, 200, 100
+STYLE DS_MODALFRAME | DS_SETFONT | WS_BORDER | WS_CAPTION | WS_DLGFRAME | WS_POPUP | WS_SYSMENU
+CAPTION "download"
+FONT 8, "MS Sans Serif"
+{
+ PUSHBUTTON "&OK", IDOK, 150, 75, 30, 20
+ PUSHBUTTON "&Cancel", IDCANCEL, 110, 75, 35, 20
+ CTEXT "downloading [file] [size] from [domain] to [destination]", NSWS_ID_DOWNLOAD_LABEL, 6, 6, 189, 35, SS_CENTER
+ CONTROL "progress", NSWS_ID_DOWNLOAD_PROGRESS, PROGRESS_CLASS, 0, 6, 50, 189, 10
+}
+
+
+
+//LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+NSWS_ID_PREFS_DIALOG DIALOG 0, 0, 388, 205
+STYLE DS_MODALFRAME | DS_SETFONT | WS_BORDER | WS_CAPTION | WS_DLGFRAME | WS_POPUP | WS_SYSMENU
+CAPTION "Edit preferences"
+FONT 8, "MS Sans Serif"
+{
+ PUSHBUTTON "&OK", IDOK, 297, 179, 34, 18
+ PUSHBUTTON "&Cancel", IDCANCEL, 336, 179, 45, 18
+ CTEXT "Home Page:", IDC_STATIC, 11, 17, 40, 8, SS_CENTER
+ EDITTEXT NSWS_ID_PREFS_HOMEPAGE, 55, 15, 322, 12, ES_AUTOHSCROLL | ES_OEMCONVERT
+ AUTOCHECKBOX "Hide Advertisements", NSWS_ID_PREFS_ADVERTS, 203, 51, 81, 10
+ AUTOCHECKBOX "Disable Pop-ups", NSWS_ID_PREFS_POPUPS, 203, 63, 67, 10
+ AUTOCHECKBOX "Disable Plugins", NSWS_ID_PREFS_PLUGINS, 203, 76, 64, 10
+ AUTOCHECKBOX "Send referer", NSWS_ID_PREFS_REFERER, 203, 89, 55, 10
+ CTEXT "HTTP proxy", IDC_STATIC, 9, 51, 40, 10, SS_CENTER
+ COMBOBOX NSWS_ID_PREFS_PROXYTYPE, 52, 49, 131, 60, CBS_DROPDOWNLIST
+ CTEXT "Host:", IDC_STATIC, 31, 70, 18, 8, SS_CENTER
+ EDITTEXT NSWS_ID_PREFS_PROXYHOST, 52, 69, 89, 12, ES_AUTOHSCROLL | ES_OEMCONVERT
+ EDITTEXT NSWS_ID_PREFS_PROXYPORT, 163, 69, 20, 12, ES_AUTOHSCROLL | ES_OEMCONVERT
+ CTEXT "Username:", IDC_STATIC, 14, 88, 35, 8, SS_CENTER
+ EDITTEXT NSWS_ID_PREFS_PROXYNAME, 52, 86, 45, 12, ES_AUTOHSCROLL | ES_OEMCONVERT
+ CTEXT "Password:", IDC_STATIC, 101, 89, 34, 8, SS_CENTER
+ EDITTEXT NSWS_ID_PREFS_PROXYPASS, 138, 86, 45, 12, ES_AUTOHSCROLL | ES_OEMCONVERT
+ CTEXT "Size", IDC_STATIC, 32, 140, 14, 8, SS_CENTER
+ EDITTEXT NSWS_ID_PREFS_FONT_SIZE, 49, 137, 26, 15
+ CONTROL "Font Size", NSWS_ID_PREFS_FONT_SIZE_SPIN, UPDOWN_CLASS, UDS_NOTHOUSANDS, 75, 137, 11, 15
+ CTEXT "Min Size", IDC_STATIC, 18, 162, 28, 8, SS_CENTER
+ EDITTEXT NSWS_ID_PREFS_FONT_MINSIZE, 49, 159, 26, 15
+ CONTROL "Font Size", NSWS_ID_PREFS_FONT_MINSIZE_SPIN, UPDOWN_CLASS, UDS_NOTHOUSANDS, 76, 159, 11, 15
+ CTEXT "Sans-serif:", IDC_STATIC, 125, 135, 34, 8, SS_CENTER
+ PUSHBUTTON "Sans", NSWS_ID_PREFS_SANS, 165, 132, 65, 15
+ CTEXT "Serif:", IDC_STATIC, 142, 119, 17, 8, SS_CENTER
+ PUSHBUTTON "Serif", NSWS_ID_PREFS_SERIF, 165, 116, 65, 15
+ CTEXT "Monospace:", IDC_STATIC, 119, 169, 40, 8, SS_CENTER
+ PUSHBUTTON "Monospace", NSWS_ID_PREFS_MONO, 165, 166, 65, 15
+ CTEXT "Cursive:", IDC_STATIC, 133, 152, 26, 8, SS_CENTER
+ PUSHBUTTON "Cursive", NSWS_ID_PREFS_CURSIVE, 165, 149, 65, 15
+ CTEXT "Fantasy:", IDC_STATIC, 131, 186, 28, 8, SS_CENTER
+ PUSHBUTTON "Fantasy", NSWS_ID_PREFS_FANTASY, 165, 183, 65, 15
+ CTEXT "Font default", IDC_STATIC, 8, 121, 38, 8, SS_CENTER
+ COMBOBOX NSWS_ID_PREFS_FONTDEF, 49, 118, 68, 60, CBS_DROPDOWNLIST
+ CTEXT "Max Fetchers", IDC_STATIC, 266, 122, 44, 8, SS_CENTER
+ EDITTEXT NSWS_ID_PREFS_FETCHERS, 314, 120, 25, 15
+ CONTROL "Max Fetchers", NSWS_ID_PREFS_FETCHERS_SPIN, UPDOWN_CLASS, UDS_AUTOBUDDY | UDS_SETBUDDYINT, 340, 120, 11, 15
+ CTEXT "Fetches per host", IDC_STATIC, 256, 139, 54, 8, SS_CENTER
+ EDITTEXT NSWS_ID_PREFS_FETCH_HOST, 314, 137, 25, 15
+ CONTROL "Fetches per host", NSWS_ID_PREFS_FETCH_HOST_SPIN, UPDOWN_CLASS, UDS_AUTOBUDDY | UDS_SETBUDDYINT, 341, 137, 11, 15
+ CTEXT "Cached Fetches", IDC_STATIC, 258, 157, 53, 8, SS_CENTER
+ EDITTEXT NSWS_ID_PREFS_FETCH_HANDLES, 314, 154, 25, 15
+ CONTROL "cached Fetches", NSWS_ID_PREFS_FETCH_HANDLES_SPIN, UPDOWN_CLASS, UDS_AUTOBUDDY | UDS_SETBUDDYINT, 341, 154, 11, 15
+ AUTOCHECKBOX "Disable", NSWS_ID_PREFS_NOANIMATION, 307, 51, 39, 10
+ CTEXT "Min delay", IDC_STATIC, 308, 68, 31, 8, SS_CENTER
+ EDITTEXT NSWS_ID_PREFS_ANIMATIONDELAY, 343, 65, 20, 15
+ CONTROL "Min delay", NSWS_ID_PREFS_ANIMATIONDELAY_SPIN, UPDOWN_CLASS, UDS_NOTHOUSANDS, 363, 65, 11, 15
+ GROUPBOX "Startup", IDC_STATIC, 3, 2, 379, 31
+ GROUPBOX "Connection", IDC_STATIC, 4, 37, 186, 67
+ CTEXT "Port:", IDC_STATIC, 144, 71, 16, 8, SS_CENTER
+ GROUPBOX "Content", IDC_STATIC, 198, 37, 91, 68
+ GROUPBOX "Animation", IDC_STATIC, 298, 37, 85, 68
+ GROUPBOX "Fonts", IDC_STATIC, 3, 108, 234, 94
+ GROUPBOX "Fetchers", IDC_STATIC, 247, 108, 134, 69
+}
+
+
+
+//
+// Icon resources
+//
+//LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+ID ICON "NetSurf32.ico"
diff --git a/windows/res/stop.bmp b/windows/res/stop.bmp
new file mode 100644
index 000000000..01ae930a1
--- /dev/null
+++ b/windows/res/stop.bmp
Binary files differ
diff --git a/windows/res/throbber.avi b/windows/res/throbber.avi
new file mode 100644
index 000000000..cced3a556
--- /dev/null
+++ b/windows/res/throbber.avi
Binary files differ
diff --git a/windows/res/throbber/throbber0.png b/windows/res/throbber/throbber0.png
new file mode 100755
index 000000000..ad13c5408
--- /dev/null
+++ b/windows/res/throbber/throbber0.png
Binary files differ
diff --git a/windows/res/throbber/throbber1.png b/windows/res/throbber/throbber1.png
new file mode 100755
index 000000000..9e4e575a3
--- /dev/null
+++ b/windows/res/throbber/throbber1.png
Binary files differ
diff --git a/windows/res/throbber/throbber2.png b/windows/res/throbber/throbber2.png
new file mode 100755
index 000000000..f571f7093
--- /dev/null
+++ b/windows/res/throbber/throbber2.png
Binary files differ
diff --git a/windows/res/throbber/throbber3.png b/windows/res/throbber/throbber3.png
new file mode 100755
index 000000000..0bc8b66b5
--- /dev/null
+++ b/windows/res/throbber/throbber3.png
Binary files differ
diff --git a/windows/res/throbber/throbber4.png b/windows/res/throbber/throbber4.png
new file mode 100755
index 000000000..37c9ce842
--- /dev/null
+++ b/windows/res/throbber/throbber4.png
Binary files differ
diff --git a/windows/res/throbber/throbber5.png b/windows/res/throbber/throbber5.png
new file mode 100755
index 000000000..54f83d224
--- /dev/null
+++ b/windows/res/throbber/throbber5.png
Binary files differ
diff --git a/windows/res/throbber/throbber6.png b/windows/res/throbber/throbber6.png
new file mode 100755
index 000000000..e36e1f872
--- /dev/null
+++ b/windows/res/throbber/throbber6.png
Binary files differ
diff --git a/windows/res/throbber/throbber7.png b/windows/res/throbber/throbber7.png
new file mode 100755
index 000000000..c6f2628b5
--- /dev/null
+++ b/windows/res/throbber/throbber7.png
Binary files differ
diff --git a/windows/res/throbber/throbber8.png b/windows/res/throbber/throbber8.png
new file mode 100755
index 000000000..d29d94414
--- /dev/null
+++ b/windows/res/throbber/throbber8.png
Binary files differ
diff --git a/windows/resourceid.h b/windows/resourceid.h
new file mode 100644
index 000000000..73fedebc5
--- /dev/null
+++ b/windows/resourceid.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_WINDOWS_RESOURCEID_H_
+#define _NETSURF_WINDOWS_RESOURCEID_H_
+
+#ifndef IDC_STATIC
+#define IDC_STATIC (-1)
+#endif
+
+#define NSWS_ID_MAINMENU 101
+#define NSWS_ID_CTXMENU 103
+#define NSWS_ID_ABOUT_DIALOG 11111
+#define NSWS_ID_ABOUT_CONTENT 11112
+#define NSWS_ID_PREFS_DIALOG 11113
+#define NSWS_ID_PREFS_HOMEPAGE 11114
+#define NSWS_ID_PREFS_ADVERTS 11115
+#define NSWS_ID_PREFS_POPUPS 11116
+#define NSWS_ID_PREFS_PLUGINS 11117
+#define NSWS_ID_PREFS_REFERER 11118
+#define NSWS_ID_PREFS_PROXYTYPE 11119
+#define NSWS_ID_PREFS_PROXYHOST 11120
+#define NSWS_ID_PREFS_PROXYPORT 11121
+#define NSWS_ID_PREFS_PROXYNAME 11122
+#define NSWS_ID_PREFS_PROXYPASS 11123
+#define NSWS_ID_PREFS_FONT_SIZE 11124
+#define NSWS_ID_PREFS_FONT_SIZE_SPIN 11125
+#define NSWS_ID_PREFS_FONT_MINSIZE 11126
+#define NSWS_ID_PREFS_FONT_MINSIZE_SPIN 11127
+#define NSWS_ID_PREFS_SANS 11128
+#define NSWS_ID_PREFS_SERIF 11129
+#define NSWS_ID_PREFS_MONO 11130
+#define NSWS_ID_PREFS_CURSIVE 11131
+#define NSWS_ID_PREFS_FANTASY 11132
+#define NSWS_ID_PREFS_FONTDEF 11133
+#define NSWS_ID_PREFS_FETCHERS 11134
+#define NSWS_ID_PREFS_FETCHERS_SPIN 11135
+#define NSWS_ID_PREFS_FETCH_HOST 11136
+#define NSWS_ID_PREFS_FETCH_HOST_SPIN 11137
+#define NSWS_ID_PREFS_FETCH_HANDLES 11138
+#define NSWS_ID_PREFS_FETCH_HANDLES_SPIN 11139
+#define NSWS_ID_PREFS_NOANIMATION 11140
+#define NSWS_ID_PREFS_ANIMATIONDELAY 11141
+#define NSWS_ID_PREFS_ANIMATIONDELAY_SPIN 11142
+#define NSWS_ID_DOWNLOAD_DIALOG 11143
+#define NSWS_ID_DOWNLOAD_LABEL 11144
+#define NSWS_ID_DOWNLOAD_PROGRESS 11145
+#define NSWS_ID_FILE_OPEN_WINDOW 40000
+#define NSWS_ID_FILE_OPEN_LOCATION 40001
+#define NSWS_ID_FILE_CLOSE_WINDOW 40002
+#define NSWS_ID_FILE_SAVEAS_TEXT 40003
+#define NSWS_ID_FILE_SAVEAS_PDF 40004
+#define NSWS_ID_FILE_SAVEAS_DRAWFILE 40005
+#define NSWS_ID_FILE_SAVEAS_POSTSCRIPT 40006
+#define NSWS_ID_FILE_PRINT_PREVIEW 40007
+#define NSWS_ID_FILE_PRINT 40008
+#define NSWS_ID_FILE_QUIT 40009
+#define NSWS_ID_FILE_SAVE_PAGE 40010
+#define NSWS_ID_EDIT_CUT 40011
+#define NSWS_ID_EDIT_COPY 40012
+#define NSWS_ID_EDIT_PASTE 40013
+#define NSWS_ID_EDIT_DELETE 40014
+#define NSWS_ID_EDIT_SELECT_ALL 40015
+#define NSWS_ID_EDIT_SEARCH 40016
+#define NSWS_ID_EDIT_PREFERENCES 40017
+#define NSWS_ID_HELP_CONTENTS 40018
+#define NSWS_ID_HELP_GUIDE 40019
+#define NSWS_ID_HELP_INFO 40020
+#define NSWS_ID_HELP_ABOUT 40021
+#define NSWS_ID_VIEW_FULLSCREEN 40022
+#define NSWS_ID_VIEW_SOURCE 40023
+#define NSWS_ID_VIEW_ZOOMPLUS 40024
+#define NSWS_ID_VIEW_ZOOMMINUS 40025
+#define NSWS_ID_VIEW_ZOOMNORMAL 40026
+#define NSWS_ID_NAV_BACK 40027
+#define NSWS_ID_NAV_FORWARD 40028
+#define NSWS_ID_NAV_HOME 40029
+#define NSWS_ID_NAV_STOP 40030
+#define NSWS_ID_NAV_RELOAD 40031
+#define NSWS_ID_NAV_LOCALHISTORY 40032
+#define NSWS_ID_NAV_GLOBALHISTORY 40033
+#define NSWS_ID_VIEW_DOWNLOADS 40034
+#define NSWS_ID_VIEW_SAVE_WIN_METRICS 40035
+#define NSWS_ID_VIEW_TOGGLE_DEBUG_RENDERING 40036
+#define NSWS_ID_VIEW_DEBUGGING_SAVE_BOXTREE 40037
+#define NSWS_ID_VIEW_DEBUGGING_SAVE_DOMTREE 40038
+
+#endif
diff --git a/windows/schedule.c b/windows/schedule.c
new file mode 100644
index 000000000..5414f6d56
--- /dev/null
+++ b/windows/schedule.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.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 <sys/time.h>
+#include <time.h>
+
+#include "desktop/browser.h"
+#include "windows/schedule.h"
+
+#include "utils/log.h"
+
+/* linked list of scheduled callbacks */
+static struct nscallback *schedule_list = NULL;
+
+#ifndef timeradd
+#define timeradd(a, aa, result) \
+ do {\
+ (result)->tv_sec = (a)->tv_sec + (aa)->tv_sec;\
+ (result)->tv_usec = (a)->tv_usec + (aa)->tv_usec;\
+ if ((result)->tv_usec >= 1000000)\
+ {\
+ ++(result)->tv_sec;\
+ (result)->tv_usec -= 1000000;\
+ }\
+ } while (0)
+#endif
+
+/**
+ * scheduled callback.
+ */
+struct nscallback
+{
+ struct nscallback *next;
+ struct timeval tv;
+ void (*callback)(void *p);
+ void *p;
+};
+
+
+/**
+ * Schedule a callback.
+ *
+ * \param tival interval before the callback should be made / cs
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ *
+ * The callback function will be called as soon as possible after t cs have
+ * passed.
+ */
+
+void schedule(int cs_ival, void (*callback)(void *p), void *p)
+{
+ struct nscallback *nscb;
+ struct timeval tv;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = cs_ival * 10000;
+
+ nscb = calloc(1, sizeof(struct nscallback));
+
+ LOG(("adding callback %p for %p(%p) at %d cs", nscb, callback, p, cs_ival));
+
+ gettimeofday(&nscb->tv, NULL);
+ timeradd(&nscb->tv, &tv, &nscb->tv);
+
+ nscb->callback = callback;
+ nscb->p = p;
+
+ /* add to list front */
+ nscb->next = schedule_list;
+ schedule_list = nscb;
+}
+
+/**
+ * Unschedule a callback.
+ *
+ * \param callback callback function
+ * \param p user parameter, passed to callback function
+ *
+ * All scheduled callbacks matching both callback and p are removed.
+ */
+
+void schedule_remove(void (*callback)(void *p), void *p)
+{
+ struct nscallback *cur_nscb;
+ struct nscallback *prev_nscb;
+ struct nscallback *unlnk_nscb;
+
+ if (schedule_list == NULL)
+ return;
+
+ LOG(("removing %p, %p", callback, p));
+
+ cur_nscb = schedule_list;
+ prev_nscb = NULL;
+
+ while (cur_nscb != NULL) {
+ if ((cur_nscb->callback == callback) &&
+ (cur_nscb->p == p)) {
+ /* item to remove */
+
+ LOG(("callback entry %p removing %p(%p)",
+ cur_nscb, cur_nscb->callback, cur_nscb->p));
+
+ /* remove callback */
+ unlnk_nscb = cur_nscb;
+ cur_nscb = unlnk_nscb->next;
+
+ if (prev_nscb == NULL) {
+ schedule_list = cur_nscb;
+ } else {
+ prev_nscb->next = cur_nscb;
+ }
+ free (unlnk_nscb);
+ } else {
+ /* move to next element */
+ prev_nscb = cur_nscb;
+ cur_nscb = prev_nscb->next;
+ }
+ }
+}
+
+/**
+ * Process events up to current time.
+ */
+
+bool schedule_run(void)
+{
+ struct timeval tv;
+ struct nscallback *cur_nscb;
+ struct nscallback *prev_nscb;
+ struct nscallback *unlnk_nscb;
+
+ if (schedule_list == NULL)
+ return false;
+
+ cur_nscb = schedule_list;
+ prev_nscb = NULL;
+
+ gettimeofday(&tv, NULL);
+
+ while (cur_nscb != NULL) {
+ if (timercmp(&tv, &cur_nscb->tv, >)) {
+ /* scheduled time */
+
+ /* remove callback */
+ unlnk_nscb = cur_nscb;
+
+ if (prev_nscb == NULL) {
+ schedule_list = unlnk_nscb->next;
+ } else {
+ prev_nscb->next = unlnk_nscb->next;
+ }
+
+ LOG(("callback entry %p running %p(%p)",
+ unlnk_nscb, unlnk_nscb->callback, unlnk_nscb->p));
+ /* call callback */
+ unlnk_nscb->callback(unlnk_nscb->p);
+
+ free (unlnk_nscb);
+
+ /* the callback might have modded the list, so start
+ * again
+ */
+ cur_nscb = schedule_list;
+ prev_nscb = NULL;
+
+ } else {
+ /* move to next element */
+ prev_nscb = cur_nscb;
+ cur_nscb = prev_nscb->next;
+ }
+ }
+ return true;
+}
+
+void list_schedule(void)
+{
+ struct timeval tv;
+ struct nscallback *cur_nscb;
+
+ gettimeofday(&tv, NULL);
+
+ LOG(("schedule list at %ld:%ld", tv.tv_sec, tv.tv_usec));
+
+ cur_nscb = schedule_list;
+
+ while (cur_nscb != NULL) {
+ LOG(("Schedule %p at %ld:%ld",
+ cur_nscb, cur_nscb->tv.tv_sec, cur_nscb->tv.tv_usec));
+ cur_nscb = cur_nscb->next;
+ }
+}
diff --git a/windows/schedule.h b/windows/schedule.h
new file mode 100644
index 000000000..64be0c4d1
--- /dev/null
+++ b/windows/schedule.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _NETSURF_WINDOWS_SCHEDULE_H_
+#define _NETSURF_WINDOWS_SCHEDULE_H_
+
+void list_schedule(void);
+
+#endif
diff --git a/windows/thumbnail.c b/windows/thumbnail.c
new file mode 100644
index 000000000..8305ee1cc
--- /dev/null
+++ b/windows/thumbnail.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "content/urldb.h"
+#include "desktop/browser.h"
+#include "utils/log.h"
+
+#include "windows/bitmap.h"
+#include "windows/gui.h"
+#include "windows/plot.h"
+
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+bool thumbnail_create(struct content *content, struct bitmap *bitmap,
+ const char *url)
+{
+ LOG(("creating thumbnail %p for url %s content %p", bitmap, url,
+ content));
+ int width = MIN(content->width, 1024);
+ int height = MIN(content->height, 768);
+ int i;
+ uint8_t *pixdata;
+ HDC hdc, minidc;
+ HBITMAP bufferbm, minibm, minibm2;
+ BITMAPINFO *bmi = (BITMAPINFO *) malloc(sizeof(BITMAPINFOHEADER) +
+ (bitmap->width * bitmap->height * 4));
+ BITMAPINFOHEADER bmih;
+ bmih.biSize = sizeof(bmih);
+ bmih.biWidth = bitmap->width;
+ bmih.biHeight = - bitmap->height;
+ bmih.biPlanes = 1;
+ bmih.biBitCount = 32;
+ bmih.biCompression = BI_RGB;
+ bmih.biSizeImage = 4 * bitmap->height * bitmap->width;
+ bmih.biXPelsPerMeter = 3600; /* 100 dpi */
+ bmih.biYPelsPerMeter = 3600;
+ bmih.biClrUsed = 0;
+ bmih.biClrImportant = 0;
+ bmi->bmiHeader = bmih;
+
+ doublebuffering = true;
+
+ if (bufferdc != NULL)
+ DeleteDC(bufferdc);
+ hdc = GetDC(current_hwnd);
+
+ bufferdc = CreateCompatibleDC(hdc);
+ if ((bufferdc == NULL) || (bmi == NULL)) {
+ doublebuffering = false;
+ ReleaseDC(current_hwnd, hdc);
+ return false;
+ }
+
+ bufferbm = CreateCompatibleBitmap(hdc, width, height);
+ if (bufferbm == NULL) {
+ doublebuffering = false;
+ ReleaseDC(current_hwnd, hdc);
+ free(bmi);
+ return false;
+ }
+ SelectObject(bufferdc, bufferbm);
+ thumbnail = true;
+ content_redraw(content, 0, 0, content->width, content->height, 0, 0,
+ width, height, 1.0, 0xFFFFFF);
+ thumbnail = false;
+
+/* scale bufferbm to minibm */
+
+ minidc = CreateCompatibleDC(hdc);
+ if (minidc == NULL) {
+ doublebuffering = false;
+ DeleteObject(bufferbm);
+ ReleaseDC(current_hwnd, hdc);
+ free(bmi);
+ return false;
+ }
+
+ minibm = CreateCompatibleBitmap(hdc, bitmap->width, bitmap->height);
+ if (minibm == NULL) {
+ doublebuffering = false;
+ DeleteObject(bufferbm);
+ DeleteDC(minidc);
+ ReleaseDC(current_hwnd, hdc);
+ free(bmi);
+ return false;
+ }
+ ReleaseDC(current_hwnd, hdc);
+
+ SelectObject(minidc, minibm);
+
+ StretchBlt(minidc, 0, 0, bitmap->width, bitmap->height, bufferdc, 0, 0,
+ width, height, SRCCOPY);
+ minibm2 = CreateCompatibleBitmap(minidc, bitmap->width,
+ bitmap->height);
+ if (minibm2 == NULL) {
+ doublebuffering = false;
+ DeleteObject(bufferbm);
+ DeleteObject(minibm);
+ DeleteDC(minidc);
+ free(bmi);
+ return false;
+ }
+ SelectObject(minidc, minibm2);
+
+/* save data from minibm bmi */
+ GetDIBits(minidc, minibm, 0, 1 - bitmap->height,
+ bmi->bmiColors, bmi, DIB_RGB_COLORS);
+
+ pixdata = (uint8_t *)(bitmap->pixdata);
+ for (i = 0; i < bitmap->width * bitmap->height; i++) {
+ pixdata[4 * i] = bmi->bmiColors[i].rgbRed;
+ pixdata[4 * i + 1] = bmi->bmiColors[i].rgbGreen;
+ pixdata[4 * i + 2] = bmi->bmiColors[i].rgbBlue;
+ pixdata[4 * i + 3] = 0xFF;
+ }
+ doublebuffering = false;
+
+ DeleteObject(bufferbm);
+ DeleteObject(minibm);
+ DeleteObject(minibm2);
+ DeleteDC(minidc);
+ free(bmi);
+ if (url)
+ urldb_set_thumbnail(url, bitmap);
+
+ doublebuffering = false;
+ return true;
+}
diff --git a/windows/tree.c b/windows/tree.c
new file mode 100644
index 000000000..e5cb390b5
--- /dev/null
+++ b/windows/tree.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2008 Vincent Sanders <vince@simtec.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 "desktop/tree.h"
+
+void tree_initialise_redraw(struct tree *tree)
+{
+}
+
+void tree_redraw_area(struct tree *tree, int x, int y, int width, int height)
+{
+}
+
+void tree_draw_line(int x, int y, int width, int height)
+{
+}
+
+void tree_draw_node_element(struct tree *tree, struct node_element *element)
+{
+}
+
+void tree_draw_node_expansion(struct tree *tree, struct node *node)
+{
+}
+
+void tree_recalculate_node_element(struct node_element *element)
+{
+}
+
+void tree_update_URL_node(struct node *node, const char *url,
+ const struct url_data *data)
+{
+}
+
+void tree_resized(struct tree *tree)
+{
+}
+
+void tree_set_node_sprite_folder(struct node *node)
+{
+}
+
+void tree_set_node_sprite(struct node *node, const char *sprite,
+ const char *expanded)
+{
+}
+