From 55162445db4c8ea46be671c2abed4ad4e77e1dcd Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sun, 31 Jan 2010 00:36:02 +0000 Subject: Add Windows frontend svn path=/trunk/netsurf/; revision=9940 --- Docs/BUILDING-Windows | 228 ++++ Makefile | 56 +- Makefile.defaults | 28 + Makefile.resources | 13 +- Makefile.sources | 11 + desktop/gui.h | 1 + desktop/netsurf.c | 26 +- utils/config.h | 26 +- utils/filename.c | 10 +- utils/useragent.c | 3 +- utils/utils.c | 14 + utils/utils.h | 5 + utils/utsname.h | 39 + windows/NetSurfInstaller.nsi | 95 ++ windows/about.c | 174 +++ windows/about.h | 24 + windows/bitmap.c | 333 +++++ windows/bitmap.h | 36 + windows/download.c | 294 +++++ windows/download.h | 64 + windows/filetype.c | 57 + windows/findfile.c | 118 ++ windows/findfile.h | 29 + windows/font.c | 208 ++++ windows/font.h | 40 + windows/gui.c | 2402 ++++++++++++++++++++++++++++++++++++ windows/gui.h | 89 ++ windows/history.c | 41 + windows/hotlist.c | 23 + windows/localhistory.c | 422 +++++++ windows/localhistory.h | 30 + windows/login.c | 24 + windows/misc.c | 52 + windows/plot.c | 837 +++++++++++++ windows/plot.h | 30 + windows/prefs.c | 635 ++++++++++ windows/prefs.h | 26 + windows/res/Aliases | 1 + windows/res/NetSurf16.ico | Bin 0 -> 1406 bytes windows/res/NetSurf32.ico | Bin 0 -> 4286 bytes windows/res/back.bmp | Bin 0 -> 406 bytes windows/res/default.css | 1 + windows/res/forward.bmp | Bin 0 -> 406 bytes windows/res/home.bmp | Bin 0 -> 406 bytes windows/res/messages | 1 + windows/res/quirks.css | 1 + windows/res/reload.bmp | Bin 0 -> 406 bytes windows/res/resource.rc | 217 ++++ windows/res/stop.bmp | Bin 0 -> 406 bytes windows/res/throbber.avi | Bin 0 -> 23980 bytes windows/res/throbber/throbber0.png | Bin 0 -> 730 bytes windows/res/throbber/throbber1.png | Bin 0 -> 928 bytes windows/res/throbber/throbber2.png | Bin 0 -> 906 bytes windows/res/throbber/throbber3.png | Bin 0 -> 917 bytes windows/res/throbber/throbber4.png | Bin 0 -> 927 bytes windows/res/throbber/throbber5.png | Bin 0 -> 923 bytes windows/res/throbber/throbber6.png | Bin 0 -> 904 bytes windows/res/throbber/throbber7.png | Bin 0 -> 940 bytes windows/res/throbber/throbber8.png | Bin 0 -> 921 bytes windows/resourceid.h | 103 ++ windows/schedule.c | 208 ++++ windows/schedule.h | 25 + windows/thumbnail.c | 149 +++ windows/tree.c | 62 + 64 files changed, 7287 insertions(+), 24 deletions(-) create mode 100644 Docs/BUILDING-Windows create mode 100644 utils/utsname.h create mode 100644 windows/NetSurfInstaller.nsi create mode 100644 windows/about.c create mode 100644 windows/about.h create mode 100644 windows/bitmap.c create mode 100644 windows/bitmap.h create mode 100644 windows/download.c create mode 100644 windows/download.h create mode 100644 windows/filetype.c create mode 100644 windows/findfile.c create mode 100644 windows/findfile.h create mode 100644 windows/font.c create mode 100644 windows/font.h create mode 100644 windows/gui.c create mode 100644 windows/gui.h create mode 100644 windows/history.c create mode 100644 windows/hotlist.c create mode 100644 windows/localhistory.c create mode 100644 windows/localhistory.h create mode 100644 windows/login.c create mode 100644 windows/misc.c create mode 100644 windows/plot.c create mode 100644 windows/plot.h create mode 100644 windows/prefs.c create mode 100644 windows/prefs.h create mode 120000 windows/res/Aliases create mode 100644 windows/res/NetSurf16.ico create mode 100644 windows/res/NetSurf32.ico create mode 100644 windows/res/back.bmp create mode 120000 windows/res/default.css create mode 100644 windows/res/forward.bmp create mode 100644 windows/res/home.bmp create mode 120000 windows/res/messages create mode 120000 windows/res/quirks.css create mode 100644 windows/res/reload.bmp create mode 100644 windows/res/resource.rc create mode 100644 windows/res/stop.bmp create mode 100644 windows/res/throbber.avi create mode 100755 windows/res/throbber/throbber0.png create mode 100755 windows/res/throbber/throbber1.png create mode 100755 windows/res/throbber/throbber2.png create mode 100755 windows/res/throbber/throbber3.png create mode 100755 windows/res/throbber/throbber4.png create mode 100755 windows/res/throbber/throbber5.png create mode 100755 windows/res/throbber/throbber6.png create mode 100755 windows/res/throbber/throbber7.png create mode 100755 windows/res/throbber/throbber8.png create mode 100644 windows/resourceid.h create mode 100644 windows/schedule.c create mode 100644 windows/schedule.h create mode 100644 windows/thumbnail.c create mode 100644 windows/tree.c 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,15 +449,44 @@ ifeq ($(TARGET),gtk) CFLAGS += $(GTKCFLAGS) LDFLAGS += $(GTKLDFLAGS) - # ---------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Windows flag setup - # ---------------------------------------------------------------------------- + # --------------------------------------------------------------------------- ifeq ($(HOST),Windows_NT) CFLAGS += -U__STRICT_ANSI__ endif 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 #include #include -#include + #include #include #include + #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 #include #include + +#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 . */ -#include #include #include +#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 + * + * 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 . + */ + +#ifndef _NETSURF_UTILS_UTSNAME_H_ +#define _NETSURF_UTILS_UTSNAME_H_ + +#ifdef HAVE_UTSNAME +#include +#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 +* +* 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 . +*/ + +#include +#include + +#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 +* +* 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 . +*/ + +#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 + * Copyright 2009 Mark Benjamin + * + * 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 . + */ + +#include +#include + +#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 + * Copyright 2009 Mark Benjamin + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include +#define _WIN32_IE 0x0500 +#include +#include +#include + +#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 + * + * 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 . + */ + +#ifndef _NETSURF_WINDOWS_DOWNLOAD_H_ +#define _NETSURF_WINDOWS_DOWNLOAD_H_ + +#include +#include +#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 + * + * 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 . + */ + +#include +#include +#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 + * Copyright 2009 Mark Benjamin + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include + +#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 + * + * 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 . + */ + +#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 + * Copyright 2008 Vincent Sanders + * Copyright 2009 Mark Benjamin + * + * 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 . + */ + +#include + +#include +#include +#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 + * Copyright 2009 Mark Benjamin + * + * 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 . + */ + +#ifndef _NETSURF_WINDOWS_FONT_H_ +#define _NETSURF_WINDOWS_FONT_H_ + +#include +#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 + * Copyright 2009 Mark Benjamin + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#define _WIN32_IE (0x0501) +#include + +#include + +#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 + * Copyright 2009 Mark Benjamin + * + * 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 . + */ + +#ifndef _NETSURF_WINDOWS_GUI_H_ +#define _NETSURF_WINDOWS_GUI_H_ + +#include +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include +#include +#define _WIN32_IE (0x0501) +#include + +#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 +* +* 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 . +*/ + +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include +#include +#include +#include +#include + +#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 + * Copyright 2009 Mark Benjamin + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include + +#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 + * + * 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 . + */ + +#include +#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 + * + * 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 . + */ + +#include +#define _WIN32_IE (0x0501) +#include +#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 + * + * 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 . + */ + +#ifndef _NETSURF_WINDOWS_PREFS_H_ +#define _NETSURF_WINDOWS_PREFS_H_ + +#include + +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 Binary files /dev/null and b/windows/res/NetSurf16.ico differ diff --git a/windows/res/NetSurf32.ico b/windows/res/NetSurf32.ico new file mode 100644 index 000000000..28198ccb6 Binary files /dev/null and b/windows/res/NetSurf32.ico differ diff --git a/windows/res/back.bmp b/windows/res/back.bmp new file mode 100644 index 000000000..c0088c9e8 Binary files /dev/null and b/windows/res/back.bmp 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 Binary files /dev/null and b/windows/res/forward.bmp differ diff --git a/windows/res/home.bmp b/windows/res/home.bmp new file mode 100644 index 000000000..80bddfd84 Binary files /dev/null and b/windows/res/home.bmp 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 Binary files /dev/null and b/windows/res/reload.bmp 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 +#include +#include +#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 Binary files /dev/null and b/windows/res/stop.bmp differ diff --git a/windows/res/throbber.avi b/windows/res/throbber.avi new file mode 100644 index 000000000..cced3a556 Binary files /dev/null and b/windows/res/throbber.avi differ diff --git a/windows/res/throbber/throbber0.png b/windows/res/throbber/throbber0.png new file mode 100755 index 000000000..ad13c5408 Binary files /dev/null and b/windows/res/throbber/throbber0.png differ diff --git a/windows/res/throbber/throbber1.png b/windows/res/throbber/throbber1.png new file mode 100755 index 000000000..9e4e575a3 Binary files /dev/null and b/windows/res/throbber/throbber1.png differ diff --git a/windows/res/throbber/throbber2.png b/windows/res/throbber/throbber2.png new file mode 100755 index 000000000..f571f7093 Binary files /dev/null and b/windows/res/throbber/throbber2.png differ diff --git a/windows/res/throbber/throbber3.png b/windows/res/throbber/throbber3.png new file mode 100755 index 000000000..0bc8b66b5 Binary files /dev/null and b/windows/res/throbber/throbber3.png differ diff --git a/windows/res/throbber/throbber4.png b/windows/res/throbber/throbber4.png new file mode 100755 index 000000000..37c9ce842 Binary files /dev/null and b/windows/res/throbber/throbber4.png differ diff --git a/windows/res/throbber/throbber5.png b/windows/res/throbber/throbber5.png new file mode 100755 index 000000000..54f83d224 Binary files /dev/null and b/windows/res/throbber/throbber5.png differ diff --git a/windows/res/throbber/throbber6.png b/windows/res/throbber/throbber6.png new file mode 100755 index 000000000..e36e1f872 Binary files /dev/null and b/windows/res/throbber/throbber6.png differ diff --git a/windows/res/throbber/throbber7.png b/windows/res/throbber/throbber7.png new file mode 100755 index 000000000..c6f2628b5 Binary files /dev/null and b/windows/res/throbber/throbber7.png differ diff --git a/windows/res/throbber/throbber8.png b/windows/res/throbber/throbber8.png new file mode 100755 index 000000000..d29d94414 Binary files /dev/null and b/windows/res/throbber/throbber8.png 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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#include +#include + +#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 + * Copyright 2009 Mark Benjamin + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#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 + * + * 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 . + */ + +#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) +{ +} + -- cgit v1.2.3