From d21447d096a320a08b3efb2b8768fad0dcdcfd64 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Thu, 5 May 2016 22:28:51 +0100 Subject: move frontends into sub directory --- frontends/windows/Makefile | 75 ++ frontends/windows/Makefile.defaults | 25 + frontends/windows/about.c | 151 +++ frontends/windows/about.h | 24 + frontends/windows/bitmap.c | 387 ++++++ frontends/windows/bitmap.h | 40 + frontends/windows/download.c | 346 +++++ frontends/windows/download.h | 37 + frontends/windows/drawable.c | 625 +++++++++ frontends/windows/drawable.h | 25 + frontends/windows/file.c | 302 +++++ frontends/windows/file.h | 29 + frontends/windows/filetype.c | 60 + frontends/windows/filetype.h | 24 + frontends/windows/findfile.c | 156 +++ frontends/windows/findfile.h | 26 + frontends/windows/font.c | 298 +++++ frontends/windows/font.h | 53 + frontends/windows/gui.c | 170 +++ frontends/windows/gui.h | 58 + frontends/windows/localhistory.c | 401 ++++++ frontends/windows/localhistory.h | 32 + frontends/windows/main.c | 271 ++++ frontends/windows/plot.c | 868 +++++++++++++ frontends/windows/plot.h | 24 + frontends/windows/pointers.c | 128 ++ frontends/windows/pointers.h | 40 + frontends/windows/prefs.c | 680 ++++++++++ frontends/windows/prefs.h | 24 + frontends/windows/res/NetSurf.ico | Bin 0 -> 18614 bytes frontends/windows/res/adblock.css | 1 + frontends/windows/res/banner.bmp | Bin 0 -> 79518 bytes frontends/windows/res/ca-bundle.crt | 1 + frontends/windows/res/credits.html | 1 + frontends/windows/res/default.css | 1 + frontends/windows/res/home.bmp | Bin 0 -> 2358 bytes frontends/windows/res/icons/back.png | Bin 0 -> 653 bytes frontends/windows/res/icons/back_g.png | Bin 0 -> 306 bytes frontends/windows/res/icons/back_h.png | Bin 0 -> 607 bytes frontends/windows/res/icons/forward.png | Bin 0 -> 697 bytes frontends/windows/res/icons/forward_g.png | Bin 0 -> 538 bytes frontends/windows/res/icons/forward_h.png | Bin 0 -> 635 bytes frontends/windows/res/icons/home.png | Bin 0 -> 745 bytes frontends/windows/res/icons/home_g.png | Bin 0 -> 576 bytes frontends/windows/res/icons/home_h.png | Bin 0 -> 751 bytes frontends/windows/res/icons/reload.png | Bin 0 -> 1062 bytes frontends/windows/res/icons/reload_g.png | Bin 0 -> 814 bytes frontends/windows/res/icons/reload_h.png | Bin 0 -> 1046 bytes frontends/windows/res/icons/stop.png | Bin 0 -> 1135 bytes frontends/windows/res/icons/stop_g.png | Bin 0 -> 850 bytes frontends/windows/res/icons/stop_h.png | Bin 0 -> 1119 bytes frontends/windows/res/installer.nsi | 141 +++ frontends/windows/res/internal.css | 1 + frontends/windows/res/licence.html | 1 + frontends/windows/res/netsurf.gif | Bin 0 -> 14119 bytes frontends/windows/res/netsurf.png | 1 + frontends/windows/res/quirks.css | 1 + frontends/windows/res/resource.rc | 265 ++++ frontends/windows/res/throbber.avi | Bin 0 -> 23980 bytes frontends/windows/res/throbber/throbber0.bmp | Bin 0 -> 1866 bytes frontends/windows/res/throbber/throbber0.png | Bin 0 -> 730 bytes frontends/windows/res/throbber/throbber1.bmp | Bin 0 -> 1866 bytes frontends/windows/res/throbber/throbber1.png | Bin 0 -> 928 bytes frontends/windows/res/throbber/throbber2.bmp | Bin 0 -> 1866 bytes frontends/windows/res/throbber/throbber2.png | Bin 0 -> 906 bytes frontends/windows/res/throbber/throbber3.bmp | Bin 0 -> 1866 bytes frontends/windows/res/throbber/throbber3.png | Bin 0 -> 917 bytes frontends/windows/res/throbber/throbber4.bmp | Bin 0 -> 1866 bytes frontends/windows/res/throbber/throbber4.png | Bin 0 -> 927 bytes frontends/windows/res/throbber/throbber5.bmp | Bin 0 -> 1866 bytes frontends/windows/res/throbber/throbber5.png | Bin 0 -> 923 bytes frontends/windows/res/throbber/throbber6.bmp | Bin 0 -> 1866 bytes frontends/windows/res/throbber/throbber6.png | Bin 0 -> 904 bytes frontends/windows/res/throbber/throbber7.bmp | Bin 0 -> 1866 bytes frontends/windows/res/throbber/throbber7.png | Bin 0 -> 940 bytes frontends/windows/res/throbber/throbber8.png | Bin 0 -> 921 bytes frontends/windows/res/toolbar.bmp | Bin 0 -> 8694 bytes frontends/windows/res/toolbarg.bmp | Bin 0 -> 8694 bytes frontends/windows/res/toolbarh.bmp | Bin 0 -> 8694 bytes frontends/windows/res/welcome.html | 1 + frontends/windows/resourceid.h | 138 ++ frontends/windows/schedule.c | 235 ++++ frontends/windows/schedule.h | 65 + frontends/windows/windbg.c | 663 ++++++++++ frontends/windows/windbg.h | 34 + frontends/windows/window.c | 1741 ++++++++++++++++++++++++++ frontends/windows/window.h | 109 ++ 87 files changed, 8779 insertions(+) create mode 100644 frontends/windows/Makefile create mode 100644 frontends/windows/Makefile.defaults create mode 100644 frontends/windows/about.c create mode 100644 frontends/windows/about.h create mode 100644 frontends/windows/bitmap.c create mode 100644 frontends/windows/bitmap.h create mode 100644 frontends/windows/download.c create mode 100644 frontends/windows/download.h create mode 100644 frontends/windows/drawable.c create mode 100644 frontends/windows/drawable.h create mode 100644 frontends/windows/file.c create mode 100644 frontends/windows/file.h create mode 100644 frontends/windows/filetype.c create mode 100644 frontends/windows/filetype.h create mode 100644 frontends/windows/findfile.c create mode 100644 frontends/windows/findfile.h create mode 100644 frontends/windows/font.c create mode 100644 frontends/windows/font.h create mode 100644 frontends/windows/gui.c create mode 100644 frontends/windows/gui.h create mode 100644 frontends/windows/localhistory.c create mode 100644 frontends/windows/localhistory.h create mode 100644 frontends/windows/main.c create mode 100644 frontends/windows/plot.c create mode 100644 frontends/windows/plot.h create mode 100644 frontends/windows/pointers.c create mode 100644 frontends/windows/pointers.h create mode 100644 frontends/windows/prefs.c create mode 100644 frontends/windows/prefs.h create mode 100644 frontends/windows/res/NetSurf.ico create mode 120000 frontends/windows/res/adblock.css create mode 100644 frontends/windows/res/banner.bmp create mode 120000 frontends/windows/res/ca-bundle.crt create mode 120000 frontends/windows/res/credits.html create mode 120000 frontends/windows/res/default.css create mode 100644 frontends/windows/res/home.bmp create mode 100644 frontends/windows/res/icons/back.png create mode 100644 frontends/windows/res/icons/back_g.png create mode 100644 frontends/windows/res/icons/back_h.png create mode 100644 frontends/windows/res/icons/forward.png create mode 100644 frontends/windows/res/icons/forward_g.png create mode 100644 frontends/windows/res/icons/forward_h.png create mode 100644 frontends/windows/res/icons/home.png create mode 100644 frontends/windows/res/icons/home_g.png create mode 100644 frontends/windows/res/icons/home_h.png create mode 100644 frontends/windows/res/icons/reload.png create mode 100644 frontends/windows/res/icons/reload_g.png create mode 100644 frontends/windows/res/icons/reload_h.png create mode 100644 frontends/windows/res/icons/stop.png create mode 100644 frontends/windows/res/icons/stop_g.png create mode 100644 frontends/windows/res/icons/stop_h.png create mode 100644 frontends/windows/res/installer.nsi create mode 120000 frontends/windows/res/internal.css create mode 120000 frontends/windows/res/licence.html create mode 100644 frontends/windows/res/netsurf.gif create mode 120000 frontends/windows/res/netsurf.png create mode 120000 frontends/windows/res/quirks.css create mode 100644 frontends/windows/res/resource.rc create mode 100644 frontends/windows/res/throbber.avi create mode 100644 frontends/windows/res/throbber/throbber0.bmp create mode 100755 frontends/windows/res/throbber/throbber0.png create mode 100644 frontends/windows/res/throbber/throbber1.bmp create mode 100755 frontends/windows/res/throbber/throbber1.png create mode 100644 frontends/windows/res/throbber/throbber2.bmp create mode 100755 frontends/windows/res/throbber/throbber2.png create mode 100644 frontends/windows/res/throbber/throbber3.bmp create mode 100755 frontends/windows/res/throbber/throbber3.png create mode 100644 frontends/windows/res/throbber/throbber4.bmp create mode 100755 frontends/windows/res/throbber/throbber4.png create mode 100644 frontends/windows/res/throbber/throbber5.bmp create mode 100755 frontends/windows/res/throbber/throbber5.png create mode 100644 frontends/windows/res/throbber/throbber6.bmp create mode 100755 frontends/windows/res/throbber/throbber6.png create mode 100644 frontends/windows/res/throbber/throbber7.bmp create mode 100755 frontends/windows/res/throbber/throbber7.png create mode 100755 frontends/windows/res/throbber/throbber8.png create mode 100644 frontends/windows/res/toolbar.bmp create mode 100644 frontends/windows/res/toolbarg.bmp create mode 100644 frontends/windows/res/toolbarh.bmp create mode 120000 frontends/windows/res/welcome.html create mode 100644 frontends/windows/resourceid.h create mode 100644 frontends/windows/schedule.c create mode 100644 frontends/windows/schedule.h create mode 100644 frontends/windows/windbg.c create mode 100644 frontends/windows/windbg.h create mode 100644 frontends/windows/window.c create mode 100644 frontends/windows/window.h (limited to 'frontends/windows') diff --git a/frontends/windows/Makefile b/frontends/windows/Makefile new file mode 100644 index 000000000..a3a95d9da --- /dev/null +++ b/frontends/windows/Makefile @@ -0,0 +1,75 @@ +# +# Makefile for NetSurf Windows target +# +# This file is part of NetSurf + +LDFLAGS += -L${GCCSDK_INSTALL_ENV}/lib +CFLAGS += -I${GCCSDK_INSTALL_ENV}/include/ + + +$(eval $(call pkg_config_find_and_add,libcares,Cares)) +$(eval $(call pkg_config_find_and_add,zlib,ZLib)) + + +LDFLAGS += -lssl -lcrypto -lgnurx -lgdi32 -lcomctl32 -lws2_32 -lmsimg32 -mwindows + +CFLAGS += -U__STRICT_ANSI__ -mwin32 +# only windows versions after XP are supported +CFLAGS += '-DWINVER=0x0501' +CFLAGS += '-D_WIN32_WINNT=0x0501' +CFLAGS += '-D_WIN32_WINDOWS=0x0501' +CFLAGS += '-D_WIN32_IE=0x0501' + +#installed resource path +CFLAGS += '-DNETSURF_WINDOWS_RESPATH="$(NETSURF_WINDOWS_RESPATH)"' + +WSCFLAGS := -std=c99 -DCURL_STATICLIB -DCARES_STATICLIB -g + +CFLAGS += $(WSCFLAGS) +LDFLAGS += $(WSCFLAGS) + +# ---------------------------------------------------------------------------- +# built-in resource setup +# ---------------------------------------------------------------------------- + +$(OBJROOT)/windows_resource.o: $(FRONTEND_RESOURCES_DIR)/resource.rc + $(VQ)echo " WINDRES: compiling windows resources" + ${Q}$(WINDRES) $< -O coff -o $@ + +S_RESOURCES := windows_resource.o + +# ---------------------------------------------------------------------------- +# Source file setup +# ---------------------------------------------------------------------------- + +# sources purely for the windows build +S_FRONTEND := main.c window.c gui.c drawable.c plot.c findfile.c \ + font.c bitmap.c about.c prefs.c download.c filetype.c file.c \ + localhistory.c schedule.c windbg.c pointers.c + +# This is the final source build list +# Note this is deliberately *not* expanded here as common and image +# are not yet available +SOURCES = $(S_COMMON) $(S_IMAGE) $(S_BROWSER) $(S_FRONTEND) $(S_RESOURCES) +EXETARGET := NetSurf.exe + +# ---------------------------------------------------------------------------- +# Install target +# ---------------------------------------------------------------------------- + +install-windows: + +# ---------------------------------------------------------------------------- +# Package target +# ---------------------------------------------------------------------------- + +package-windows: netsurf-installer.exe + +WIN_RES_OBJ := installer.nsi NetSurf.ico netsurf.png welcome.html default.css +WIN_RES_INS_OBJ := $(addprefix $(FRONTEND_RESOURCES_DIR)/,$(WIN_RES_OBJ)) $(OBJROOT)/messages + +$(OBJROOT)/messages: resources/FatMessages + $(Q)$(SPLIT_MESSAGES) -l en -p win -f messages resources/FatMessages > $@ + +netsurf-installer.exe: $(EXETARGET) $(WIN_RES_INS_OBJ) + makensis -V4 -NOCD $(FRONTEND_RESOURCES_DIR)/installer.nsi diff --git a/frontends/windows/Makefile.defaults b/frontends/windows/Makefile.defaults new file mode 100644 index 000000000..1d844f112 --- /dev/null +++ b/frontends/windows/Makefile.defaults @@ -0,0 +1,25 @@ +# ---------------------------------------------------------------------------- +# windows-specific options +# ---------------------------------------------------------------------------- + +# Where to search for NetSurf's resources after looking in ~/.netsurf and +# $NETSURFRES. It must have a trailing backslash +NETSURF_WINDOWS_RESPATH := + +# 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 + +# no pdf support +NETSURF_USE_HARU_PDF := NO + +# Optimisation levels +CFLAGS += -O2 diff --git a/frontends/windows/about.c b/frontends/windows/about.c new file mode 100644 index 000000000..4716a5c91 --- /dev/null +++ b/frontends/windows/about.c @@ -0,0 +1,151 @@ +/* +* 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 . +*/ + +/** + * \file + * This is The win32 API about dialog implementation. + */ + +#include + +#include "utils/config.h" + +#include + +#include "utils/log.h" +#include "utils/utils.h" +#include "utils/messages.h" +#include "desktop/version.h" + +#include "windows/gui.h" +#include "windows/window.h" +#include "windows/about.h" +#include "windows/resourceid.h" + +#include "windbg.h" + +/** + * Initialize the about dialog text fields + */ +static BOOL init_about_dialog(HWND hwnd) +{ + char ver_str[128]; + HWND dlg_itm; + HFONT hFont; + + dlg_itm = GetDlgItem(hwnd, IDC_ABOUT_VERSION); + if (dlg_itm != NULL) { + + hFont=CreateFont (26, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial"); + if (hFont != NULL) { + LOG("Setting font object"); + SendMessage(dlg_itm, WM_SETFONT, (WPARAM)hFont, 0); + } + + snprintf(ver_str, sizeof(ver_str), "%s %s", + messages_get("NetSurf"), netsurf_version); + + SendMessage(dlg_itm, WM_SETTEXT, 0, (LPARAM)ver_str); + } + + dlg_itm = GetDlgItem(hwnd, IDC_ABOUT_COPYRIGHT); + if (dlg_itm != NULL) { + snprintf(ver_str, sizeof(ver_str), "%s", + messages_get("NetSurfCopyright")); + + SendMessage(dlg_itm, WM_SETTEXT, 0, (LPARAM)ver_str); + } + + return TRUE; +} + +/** + * destroy resources used to create about dialog + */ +static BOOL destroy_about_dialog(HWND hwnd) +{ + HWND dlg_itm; + HFONT hFont; + + dlg_itm = GetDlgItem(hwnd, IDC_ABOUT_VERSION); + if (dlg_itm != NULL) { + hFont = (HFONT)SendMessage(dlg_itm, WM_GETFONT, 0, 0); + if (hFont != NULL) { + LOG("Destroyed font object"); + DeleteObject(hFont); + } + } + + return TRUE; + +} + +static BOOL CALLBACK +nsws_about_event_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + + LOG_WIN_MSG(hwnd, msg, wparam, lparam); + + switch(msg) { + case WM_INITDIALOG: + return init_about_dialog(hwnd); + + case WM_COMMAND: + switch(LOWORD(wparam)) { + case IDOK: + LOG("OK clicked"); + EndDialog(hwnd, IDOK); + break; + + case IDCANCEL: + LOG("Cancel clicked"); + EndDialog(hwnd, IDOK); + break; + + case IDC_BTN_CREDITS: + nsws_window_go(hwnd, "about:credits"); + EndDialog(hwnd, IDOK); + break; + + case IDC_BTN_LICENCE: + nsws_window_go(hwnd, "about:licence"); + EndDialog(hwnd, IDOK); + break; + + } + break; + + case WM_CREATE: + return TRUE; + + case WM_DESTROY: + return destroy_about_dialog(hwnd); + + } + return FALSE; +} + +void nsws_about_dialog_init(HINSTANCE hinst, HWND parent) +{ + int ret = DialogBox(hinst, MAKEINTRESOURCE(IDD_DLG_ABOUT), parent, + nsws_about_event_callback); + if (ret == -1) { + win32_warning(messages_get("NoMemory"), 0); + return; + } +} diff --git a/frontends/windows/about.h b/frontends/windows/about.h new file mode 100644 index 000000000..e0315b507 --- /dev/null +++ b/frontends/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/frontends/windows/bitmap.c b/frontends/windows/bitmap.c new file mode 100644 index 000000000..664244838 --- /dev/null +++ b/frontends/windows/bitmap.c @@ -0,0 +1,387 @@ +/* + * 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 . + */ + +/** + * \file + * win32 implementation of the bitmap operations. + */ + +#include "utils/config.h" + +#include +#include +#include +#include + +#include "utils/log.h" +#include "image/bitmap.h" +#include "desktop/plotters.h" +#include "content/content.h" + +#include "windows/plot.h" +#include "windows/bitmap.h" + +/** + * 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 *win32_bitmap_create(int width, int height, unsigned int state) +{ + struct bitmap *bitmap; + BITMAPV5HEADER *pbmi; + HBITMAP windib; + uint8_t *pixdata; + + LOG("width %d, height %d, state %u", width, height, state); + + pbmi = calloc(1, sizeof(BITMAPV5HEADER)); + if (pbmi == NULL) { + return NULL; + } + + pbmi->bV5Size = sizeof(BITMAPV5HEADER); + pbmi->bV5Width = width; + pbmi->bV5Height = -height; + pbmi->bV5Planes = 1; + pbmi->bV5BitCount = 32; + pbmi->bV5Compression = BI_BITFIELDS; + + pbmi->bV5RedMask = 0xff; /* red mask */ + pbmi->bV5GreenMask = 0xff00; /* green mask */ + pbmi->bV5BlueMask = 0xff0000; /* blue mask */ + pbmi->bV5AlphaMask = 0xff000000; /* alpha mask */ + + windib = CreateDIBSection(NULL, (BITMAPINFO *)pbmi, DIB_RGB_COLORS, (void **)&pixdata, NULL, 0); + + if (windib == NULL) { + free(pbmi); + return NULL; + } + + bitmap = calloc(1 , sizeof(struct bitmap)); + if (bitmap == NULL) { + DeleteObject(windib); + free(pbmi); + return NULL; + } + + bitmap->width = width; + bitmap->height = height; + bitmap->windib = windib; + bitmap->pbmi = pbmi; + bitmap->pixdata = pixdata; + if ((state & BITMAP_OPAQUE) != 0) { + bitmap->opaque = true; + } else { + bitmap->opaque = false; + } + + LOG("bitmap %p", bitmap); + + return bitmap; +} + + +/** + * Return a pointer to the pixel data in a bitmap. + * + * 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(). + * + * \param bitmap a bitmap, as returned by bitmap_create() + * \return pointer to the pixel buffer + */ +static 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 + */ +static 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 win32_bitmap_destroy(void *bitmap) +{ + struct bitmap *bm = bitmap; + + if (bitmap == NULL) { + LOG("NULL bitmap!"); + return; + } + + DeleteObject(bm->windib); + free(bm->pbmi); + 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 + * \param flags flags controlling how the bitmap is saved. + * \return true on success, false on error and error reported + */ +static bool bitmap_save(void *bitmap, const char *path, unsigned flags) +{ + return true; +} + + +/** + * The bitmap image has changed, so flush any persistant cache. + * + * \param bitmap a bitmap, as returned by bitmap_create() + */ +static void bitmap_modified(void *bitmap) { +} + +/** + * Sets whether a bitmap should be plotted opaque + * + * \param bitmap a bitmap, as returned by bitmap_create() + * \param opaque whether the bitmap should be plotted opaque + */ +static 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 + */ +static 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() + */ +static bool bitmap_get_opaque(void *bitmap) +{ + struct bitmap *bm = bitmap; + + if (bitmap == NULL) { + LOG("NULL bitmap!"); + return false; + } + + return bm->opaque; +} + +static int bitmap_get_width(void *bitmap) +{ + struct bitmap *bm = bitmap; + + if (bitmap == NULL) { + LOG("NULL bitmap!"); + return 0; + } + + return(bm->width); +} + +static int bitmap_get_height(void *bitmap) +{ + struct bitmap *bm = bitmap; + + if (bitmap == NULL) { + LOG("NULL bitmap!"); + return 0; + } + + return(bm->height); +} + +static size_t bitmap_get_bpp(void *bitmap) +{ + return 4; +} + +struct bitmap *bitmap_scale(struct bitmap *prescale, int width, int height) +{ + struct bitmap *ret = malloc(sizeof(struct bitmap)); + 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; + +} + + +static nserror +bitmap_render(struct bitmap *bitmap, struct hlcache_handle *content) +{ + int width; + int height; + HDC hdc, bufferdc, minidc; + struct bitmap *fsbitmap; + struct redraw_context ctx = { + .interactive = false, + .background_images = true, + .plot = &win_plotters + }; + + width = min(content_get_width(content), 1024); + height = ((width * bitmap->height) + (bitmap->width / 2)) / + bitmap->width; + + LOG("bitmap %p for content %p width %d, height %d", + bitmap, content, width, height); + + /* create two memory device contexts to put the bitmaps in */ + bufferdc = CreateCompatibleDC(NULL); + if ((bufferdc == NULL)) { + return NSERROR_NOMEM; + } + + minidc = CreateCompatibleDC(NULL); + if ((minidc == NULL)) { + DeleteDC(bufferdc); + return NSERROR_NOMEM; + } + + /* create a full size bitmap and plot into it */ + fsbitmap = win32_bitmap_create(width, height, BITMAP_NEW | BITMAP_CLEAR_MEMORY | BITMAP_OPAQUE); + + SelectObject(bufferdc, fsbitmap->windib); + + hdc = plot_hdc; + plot_hdc = bufferdc; + /* render the content */ + content_scaled_redraw(content, width, height, &ctx); + plot_hdc = hdc; + + /* scale bitmap bufferbm into minibm */ + SelectObject(minidc, bitmap->windib); + + bitmap->opaque = true; + + StretchBlt(minidc, 0, 0, bitmap->width, bitmap->height, bufferdc, 0, 0, width, height, SRCCOPY); + + DeleteDC(bufferdc); + DeleteDC(minidc); + win32_bitmap_destroy(fsbitmap); + + return NSERROR_OK; +} + +static struct gui_bitmap_table bitmap_table = { + .create = win32_bitmap_create, + .destroy = win32_bitmap_destroy, + .set_opaque = bitmap_set_opaque, + .get_opaque = bitmap_get_opaque, + .test_opaque = bitmap_test_opaque, + .get_buffer = bitmap_get_buffer, + .get_rowstride = bitmap_get_rowstride, + .get_width = bitmap_get_width, + .get_height = bitmap_get_height, + .get_bpp = bitmap_get_bpp, + .save = bitmap_save, + .modified = bitmap_modified, + .render = bitmap_render, +}; + +struct gui_bitmap_table *win32_bitmap_table = &bitmap_table; diff --git a/frontends/windows/bitmap.h b/frontends/windows/bitmap.h new file mode 100644 index 000000000..c723159e1 --- /dev/null +++ b/frontends/windows/bitmap.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_BITMAP_H_ +#define _NETSURF_WINDOWS_BITMAP_H_ + +struct gui_bitmap_table *win32_bitmap_table; + +struct bitmap { + HBITMAP windib; + BITMAPV5HEADER *pbmi; + int width; + int height; + uint8_t *pixdata; + bool opaque; +}; + +struct bitmap *bitmap_scale(struct bitmap *prescale, int width, int height); + +void *win32_bitmap_create(int width, int height, unsigned int state); + +void win32_bitmap_destroy(void *bitmap); + +#endif diff --git a/frontends/windows/download.c b/frontends/windows/download.c new file mode 100644 index 000000000..b281ea76a --- /dev/null +++ b/frontends/windows/download.c @@ -0,0 +1,346 @@ +/* + * 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 "utils/config.h" + +#include +#include + +#include "utils/sys_time.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/url.h" +#include "utils/nsurl.h" +#include "utils/utils.h" +#include "utils/string.h" +#include "content/fetch.h" +#include "desktop/gui_download.h" +#include "desktop/download.h" + +#include "windows/download.h" +#include "windows/window.h" +#include "windows/gui.h" +#include "windows/resourceid.h" +#include "windows/schedule.h" + +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 gui_window *window; + FILE *file; + download_status status; +}; + +static bool downloading = false; +static struct gui_download_window *download1; + +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); + +static bool nsws_download_window_up(struct gui_download_window *w) +{ + w->hwnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DLG_DOWNLOAD), + gui_window_main_window(w->window), + nsws_download_event_callback); + if (w->hwnd == NULL) { + return false; + } + ShowWindow(w->hwnd, SW_SHOW); + return true; +} + +static struct gui_download_window * +gui_download_window_create(download_context *ctx, struct gui_window *gui) +{ + if (downloading) { + /* initial implementation */ + win32_warning("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) { + win32_warning(messages_get("NoMemory"), 0); + return NULL; + } + int total_size = download_context_get_total_length(ctx); + char *domain, *filename, *destination; + nsurl *url = download_context_get_url(ctx); + bool unknown_size = (total_size == 0); + const char *size = (unknown_size) ? + messages_get("UnknownSize") : + human_friendly_bytesize(total_size); + + if (nsurl_nice(url, &filename, false) != NSERROR_OK) { + filename = strdup(messages_get("UnknownFile")); + } + if (filename == NULL) { + win32_warning(messages_get("NoMemory"), 0); + free(w); + return NULL; + } + + if (nsurl_has_component(url, NSURL_HOST)) { + domain = strdup(lwc_string_data(nsurl_get_component(url, NSURL_HOST))); + } else { + domain = strdup(messages_get("UnknownHost")); + } + if (domain == NULL) { + win32_warning(messages_get("NoMemory"), 0); + free(filename); + free(w); + return NULL; + } + destination = malloc(PATH_MAX); + if (destination == NULL) { + win32_warning(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->title = filename; + w->domain = domain; + w->size = total_size; + w->total_size = strdup(size); + if (w->total_size == NULL) { + win32_warning(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) { + win32_warning(messages_get("FileOpenWriteError"), destination); + free(destination); + free(domain); + free(filename); + free(w->total_size); + free(w->time_left); + free(w); + return NULL; + } + download1 = w; + + if (nsws_download_window_up(w) == false) { + win32_warning(messages_get("NoMemory"), 0); + free(destination); + free(domain); + free(filename); + free(w->total_size); + free(w->time_left); + free(w); + return NULL; + } + return w; +} + + +BOOL CALLBACK nsws_download_event_callback(HWND hwnd, UINT msg, WPARAM wparam, + LPARAM lparam) +{ + HWND sub; + switch(msg){ + case WM_INITDIALOG: + sub = GetDlgItem(hwnd, IDC_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) { + win32_schedule(-1, nsws_download_update_label, p); + return; + } + HWND sub = GetDlgItem(w->hwnd, IDC_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) { + win32_schedule(500, nsws_download_update_label, p); + } +} + +void nsws_download_update_progress(void *p) +{ + struct gui_download_window *w = p; + if (w->hwnd == NULL) { + win32_schedule(-1, nsws_download_update_progress, p); + return; + } + HWND sub = GetDlgItem(w->hwnd, IDC_DOWNLOAD_PROGRESS); + SendMessage(sub, PBM_SETPOS, (WPARAM)(w->progress / 100), 0); + if (w->progress < 10000) { + win32_schedule(500, 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); + win32_schedule(-1, nsws_download_update_progress, (void *)w); + win32_schedule(-1, nsws_download_update_label, (void *)w); +} + + +static nserror +gui_download_window_data(struct gui_download_window *w, const char *data, + unsigned int size) +{ + if ((w == NULL) || (w->file == NULL)) + return NSERROR_SAVE_FAILED; + 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); + return NSERROR_OK; +} + +static void gui_download_window_error(struct gui_download_window *w, + const char *error_msg) +{ + LOG("error %s", error_msg); +} + +static 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); +} + +static struct gui_download_table download_table = { + .create = gui_download_window_create, + .data = gui_download_window_data, + .error = gui_download_window_error, + .done = gui_download_window_done, +}; + +struct gui_download_table *win32_download_table = &download_table; + diff --git a/frontends/windows/download.h b/frontends/windows/download.h new file mode 100644 index 000000000..2fe3b54c9 --- /dev/null +++ b/frontends/windows/download.h @@ -0,0 +1,37 @@ +/* + * 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_ + +extern struct gui_download_table *win32_download_table; + +typedef enum { + DOWNLOAD_NONE, + DOWNLOAD_WORKING, + DOWNLOAD_ERROR, + DOWNLOAD_COMPLETE, + DOWNLOAD_CANCELED +} download_status; + +/** + * Initialise the win32 window class for the download window + */ +void nsws_download_window_init(struct gui_window *); + +#endif diff --git a/frontends/windows/drawable.c b/frontends/windows/drawable.c new file mode 100644 index 000000000..4480eeaaa --- /dev/null +++ b/frontends/windows/drawable.c @@ -0,0 +1,625 @@ +/* + * Copyright 2011 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 "utils/config.h" + +#include +#include + +#include "desktop/browser.h" +#include "desktop/textinput.h" +#include "desktop/plotters.h" +#include "utils/errors.h" +#include "utils/log.h" +#include "utils/utils.h" + +#include "windows/windbg.h" +#include "windows/plot.h" +#include "windows/window.h" +#include "windows/localhistory.h" +#include "windows/drawable.h" + +static const char windowclassname_drawable[] = "nswsdrawablewindow"; + +/** + * Handle wheel scroll messages. + */ +static LRESULT +nsws_drawable_wheel(struct gui_window *gw, HWND hwnd, WPARAM wparam) +{ + int i, z = GET_WHEEL_DELTA_WPARAM(wparam) / WHEEL_DELTA; + int 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); + } + + return 0; +} + +/** + * Handle vertical scroll messages. + */ +static LRESULT +nsws_drawable_vscroll(struct gui_window *gw, HWND hwnd, WPARAM wparam) +{ + int width, height; + SCROLLINFO si; + int mem; + + LOG("VSCROLL %d", gw->requestscrolly); + + if (gw->requestscrolly != 0) + return 0; + + 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 -= gw->height; + break; + + case SB_PAGEDOWN: + si.nPos += gw->height; + break; + + case SB_THUMBTRACK: + si.nPos = si.nTrackPos; + break; + + default: + break; + } + + si.fMask = SIF_POS; + if ((gw->bw != NULL) && + (browser_window_get_extents(gw->bw, true, + &width, &height) == NSERROR_OK)) { + si.nPos = min(si.nPos, height - gw->height); + } + + si.nPos = max(si.nPos, 0); + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); + GetScrollInfo(hwnd, SB_VERT, &si); + if (si.nPos != mem) { + win32_window_set_scroll(gw, gw->scrollx, gw->scrolly + + gw->requestscrolly + si.nPos - mem); + } + + return 0; +} + + +/** + * Handle horizontal scroll messages. + */ +static LRESULT +nsws_drawable_hscroll(struct gui_window *gw, HWND hwnd, WPARAM wparam) +{ + int width, height; + SCROLLINFO si; + int mem; + + LOG("HSCROLL %d", gw->requestscrollx); + + if (gw->requestscrollx != 0) + return 0; + + 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 -= gw->width; + break; + + case SB_PAGERIGHT: + si.nPos += gw->width; + break; + + case SB_THUMBTRACK: + si.nPos = si.nTrackPos; + break; + + default: + break; + } + + si.fMask = SIF_POS; + + if ((gw->bw != NULL) && + (browser_window_get_extents(gw->bw, true, + &width, &height) == NSERROR_OK)) { + si.nPos = min(si.nPos, width - gw->width); + } + si.nPos = max(si.nPos, 0); + SetScrollInfo(hwnd, SB_HORZ, &si, TRUE); + GetScrollInfo(hwnd, SB_HORZ, &si); + if (si.nPos != mem) { + win32_window_set_scroll(gw, + gw->scrollx + gw->requestscrollx + si.nPos - mem, + gw->scrolly); + } + + return 0; +} + +/** + * Handle resize events. + */ +static LRESULT +nsws_drawable_resize(struct gui_window *gw) +{ + browser_window_schedule_reformat(gw->bw); + return 0; +} + +/** + * Handle key press messages. + */ +static LRESULT +nsws_drawable_key(struct gui_window *gw, HWND hwnd, WPARAM wparam) +{ + if (GetFocus() != hwnd) + return 0 ; + + uint32_t i; + bool shift = ((GetKeyState(VK_SHIFT) & 0x8000) == 0x8000); + bool capslock = ((GetKeyState(VK_CAPITAL) & 1) == 1); + + switch(wparam) { + case VK_LEFT: + i = NS_KEY_LEFT; + if (shift) + SendMessage(hwnd, WM_HSCROLL, + MAKELONG(SB_LINELEFT, 0), 0); + break; + + case VK_RIGHT: + i = NS_KEY_RIGHT; + if (shift) + SendMessage(hwnd, WM_HSCROLL, + MAKELONG(SB_LINERIGHT, 0), 0); + break; + + case VK_UP: + i = NS_KEY_UP; + if (shift) + SendMessage(hwnd, WM_VSCROLL, + MAKELONG(SB_LINEUP, 0), 0); + break; + + case VK_DOWN: + i = NS_KEY_DOWN; + if (shift) + SendMessage(hwnd, WM_VSCROLL, + MAKELONG(SB_LINEDOWN, 0), 0); + break; + + case VK_HOME: + i = NS_KEY_LINE_START; + if (shift) + SendMessage(hwnd, WM_HSCROLL, + MAKELONG(SB_PAGELEFT, 0), 0); + break; + + case VK_END: + i = NS_KEY_LINE_END; + if (shift) + SendMessage(hwnd, WM_HSCROLL, + MAKELONG(SB_PAGERIGHT, 0), 0); + break; + + case VK_DELETE: + i = NS_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 (gw != NULL) + browser_window_key_press(gw->bw, i); + + return 0; +} + + +/** + * Handle paint messages. + */ +static LRESULT +nsws_drawable_paint(struct gui_window *gw, HWND hwnd) +{ + struct rect clip; + PAINTSTRUCT ps; + struct redraw_context ctx = { + .interactive = true, + .background_images = true, + .plot = &win_plotters + }; + + BeginPaint(hwnd, &ps); + + if (gw != NULL) { + plot_hdc = ps.hdc; + + clip.x0 = ps.rcPaint.left; + clip.y0 = ps.rcPaint.top; + clip.x1 = ps.rcPaint.right; + clip.y1 = ps.rcPaint.bottom; + + browser_window_redraw(gw->bw, + -gw->scrollx / gw->scale, + -gw->scrolly / gw->scale, + &clip, &ctx); + } + + EndPaint(hwnd, &ps); + + return 0; +} + + +/** + * Handle mouse button up messages. + */ +static LRESULT +nsws_drawable_mouseup(struct gui_window *gw, + int x, + int y, + browser_mouse_state press, + browser_mouse_state click) +{ + bool shift = ((GetKeyState(VK_SHIFT) & 0x8000) == 0x8000); + bool ctrl = ((GetKeyState(VK_CONTROL) & 0x8000) == 0x8000); + bool alt = ((GetKeyState(VK_MENU) & 0x8000) == 0x8000); + + if ((gw == NULL) || + (gw->mouse == NULL) || + (gw->bw == NULL)) + return 0; + + LOG("state 0x%x, press 0x%x", gw->mouse->state, press); + if ((gw->mouse->state & press) != 0) { + gw->mouse->state &= ~press; + gw->mouse->state |= click; + } + + if (((gw->mouse->state & BROWSER_MOUSE_MOD_1) != 0) && !shift) + gw->mouse->state &= ~BROWSER_MOUSE_MOD_1; + if (((gw->mouse->state & BROWSER_MOUSE_MOD_2) != 0) && !ctrl) + gw->mouse->state &= ~BROWSER_MOUSE_MOD_2; + if (((gw->mouse->state & BROWSER_MOUSE_MOD_3) != 0) && !alt) + gw->mouse->state &= ~BROWSER_MOUSE_MOD_3; + + if ((gw->mouse->state & click) != 0) { + LOG("mouse click bw %p, state 0x%x, x %f, y %f", gw->bw, gw->mouse->state, (x + gw->scrollx) / gw->scale, (y + gw->scrolly) / gw->scale); + + browser_window_mouse_click(gw->bw, + gw->mouse->state, + (x + gw->scrollx) / gw->scale, + (y + gw->scrolly) / gw->scale); + } else { + browser_window_mouse_track(gw->bw, + 0, + (x + gw->scrollx) / gw->scale, + (y + gw->scrolly) / gw->scale); + } + + gw->mouse->state = 0; + return 0; +} + + +/** + * Handle mouse button down messages. + */ +static LRESULT +nsws_drawable_mousedown(struct gui_window *gw, + int x, int y, + browser_mouse_state button) +{ + if ((gw == NULL) || + (gw->mouse == NULL) || + (gw->bw == NULL)) { + nsws_localhistory_close(gw); + return 0; + } + + gw->mouse->state = button; + if ((GetKeyState(VK_SHIFT) & 0x8000) == 0x8000) + gw->mouse->state |= BROWSER_MOUSE_MOD_1; + if ((GetKeyState(VK_CONTROL) & 0x8000) == 0x8000) + gw->mouse->state |= BROWSER_MOUSE_MOD_2; + if ((GetKeyState(VK_MENU) & 0x8000) == 0x8000) + gw->mouse->state |= BROWSER_MOUSE_MOD_3; + + gw->mouse->pressed_x = (x + gw->scrollx) / gw->scale; + gw->mouse->pressed_y = (y + gw->scrolly) / gw->scale; + + LOG("mouse click bw %p, state %x, x %f, y %f", gw->bw, gw->mouse->state, (x + gw->scrollx) / gw->scale, (y + gw->scrolly) / gw->scale); + + browser_window_mouse_click(gw->bw, gw->mouse->state, + (x + gw->scrollx) / gw->scale, + (y + gw->scrolly) / gw->scale); + + return 0; +} + +/** + * Handle mouse movement messages. + */ +static LRESULT +nsws_drawable_mousemove(struct gui_window *gw, int x, int y) +{ + bool shift = ((GetKeyState(VK_SHIFT) & 0x8000) == 0x8000); + bool ctrl = ((GetKeyState(VK_CONTROL) & 0x8000) == 0x8000); + bool alt = ((GetKeyState(VK_MENU) & 0x8000) == 0x8000); + + if ((gw == NULL) || (gw->mouse == NULL) || (gw->bw == NULL)) + return 0; + + /* scale co-ordinates */ + x = (x + gw->scrollx) / gw->scale; + y = (y + gw->scrolly) / gw->scale; + + /* if mouse button held down and pointer moved more than + * minimum distance drag is happening */ + if (((gw->mouse->state & (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2)) != 0) && + (abs(x - gw->mouse->pressed_x) >= 5) && + (abs(y - gw->mouse->pressed_y) >= 5)) { + + LOG("Drag start state 0x%x", gw->mouse->state); + + if ((gw->mouse->state & BROWSER_MOUSE_PRESS_1) != 0) { + browser_window_mouse_click(gw->bw, BROWSER_MOUSE_DRAG_1, + gw->mouse->pressed_x, + gw->mouse->pressed_y); + gw->mouse->state &= ~BROWSER_MOUSE_PRESS_1; + gw->mouse->state |= BROWSER_MOUSE_HOLDING_1 | + BROWSER_MOUSE_DRAG_ON; + } + else if ((gw->mouse->state & BROWSER_MOUSE_PRESS_2) != 0) { + browser_window_mouse_click(gw->bw, BROWSER_MOUSE_DRAG_2, + gw->mouse->pressed_x, + gw->mouse->pressed_y); + gw->mouse->state &= ~BROWSER_MOUSE_PRESS_2; + gw->mouse->state |= BROWSER_MOUSE_HOLDING_2 | + BROWSER_MOUSE_DRAG_ON; + } + } + + if (((gw->mouse->state & BROWSER_MOUSE_MOD_1) != 0) && !shift) + gw->mouse->state &= ~BROWSER_MOUSE_MOD_1; + if (((gw->mouse->state & BROWSER_MOUSE_MOD_2) != 0) && !ctrl) + gw->mouse->state &= ~BROWSER_MOUSE_MOD_2; + if (((gw->mouse->state & BROWSER_MOUSE_MOD_3) != 0) && !alt) + gw->mouse->state &= ~BROWSER_MOUSE_MOD_3; + + + browser_window_mouse_track(gw->bw, gw->mouse->state, x, y); + + return 0; +} + +/** + * Called when activity occours within the drawable window. + */ +static LRESULT CALLBACK +nsws_window_drawable_event_callback(HWND hwnd, + UINT msg, + WPARAM wparam, + LPARAM lparam) +{ + struct gui_window *gw; + + LOG_WIN_MSG(hwnd, msg, wparam, lparam); + + gw = nsws_get_gui_window(hwnd); + if (gw == NULL) { + LOG("Unable to find gui window structure for hwnd %p", hwnd); + return DefWindowProc(hwnd, msg, wparam, lparam); + } + + switch(msg) { + + case WM_MOUSEMOVE: + return nsws_drawable_mousemove(gw, + GET_X_LPARAM(lparam), + GET_Y_LPARAM(lparam)); + + case WM_LBUTTONDOWN: + nsws_drawable_mousedown(gw, + GET_X_LPARAM(lparam), + GET_Y_LPARAM(lparam), + BROWSER_MOUSE_PRESS_1); + SetFocus(hwnd); + nsws_localhistory_close(gw); + return 0; + break; + + case WM_RBUTTONDOWN: + nsws_drawable_mousedown(gw, + GET_X_LPARAM(lparam), + GET_Y_LPARAM(lparam), + BROWSER_MOUSE_PRESS_2); + SetFocus(hwnd); + return 0; + break; + + case WM_LBUTTONUP: + return nsws_drawable_mouseup(gw, + GET_X_LPARAM(lparam), + GET_Y_LPARAM(lparam), + BROWSER_MOUSE_PRESS_1, + BROWSER_MOUSE_CLICK_1); + + case WM_RBUTTONUP: + return nsws_drawable_mouseup(gw, + GET_X_LPARAM(lparam), + GET_Y_LPARAM(lparam), + BROWSER_MOUSE_PRESS_2, + BROWSER_MOUSE_CLICK_2); + + case WM_ERASEBKGND: /* ignore as drawable window is redrawn on paint */ + return 0; + + case WM_PAINT: /* redraw the exposed part of the window */ + return nsws_drawable_paint(gw, hwnd); + + case WM_KEYDOWN: + return nsws_drawable_key(gw, hwnd, wparam); + + case WM_SIZE: + return nsws_drawable_resize(gw); + + case WM_HSCROLL: + return nsws_drawable_hscroll(gw, hwnd, wparam); + + case WM_VSCROLL: + return nsws_drawable_vscroll(gw, hwnd, wparam); + + case WM_MOUSEWHEEL: + return nsws_drawable_wheel(gw, hwnd, wparam); + + } + return DefWindowProc(hwnd, msg, wparam, lparam); +} + +/** + * Create a drawable window. + */ +HWND +nsws_window_create_drawable(HINSTANCE hinstance, + HWND hparent, + struct gui_window *gw) +{ + HWND hwnd; + hwnd = CreateWindow(windowclassname_drawable, + NULL, + WS_VISIBLE | WS_CHILD, + 0, 0, 0, 0, + hparent, + NULL, + hinstance, + NULL); + + if (hwnd == NULL) { + win_perror("WindowCreateDrawable"); + LOG("Window creation failed"); + return NULL; + } + + /* set the gui window associated with this toolbar */ + SetProp(hwnd, TEXT("GuiWnd"), (HANDLE)gw); + + return hwnd; +} + +/** + * Create the drawable window class. + */ +nserror +nsws_create_drawable_class(HINSTANCE hinstance) { + nserror ret = NSERROR_OK; + WNDCLASSEX w; + + /* drawable area */ + w.cbSize = sizeof(WNDCLASSEX); + w.style = 0; + w.lpfnWndProc = nsws_window_drawable_event_callback; + w.cbClsExtra = 0; + w.cbWndExtra = 0; + w.hInstance = hinstance; + w.hIcon = NULL; + w.hCursor = NULL; + w.hbrBackground = (HBRUSH)(COLOR_MENU + 1); + w.lpszMenuName = NULL; + w.lpszClassName = windowclassname_drawable; + w.hIconSm = NULL; + + if (RegisterClassEx(&w) == 0) { + win_perror("DrawableClass"); + ret = NSERROR_INIT_FAILED; + } + + return ret; +} diff --git a/frontends/windows/drawable.h b/frontends/windows/drawable.h new file mode 100644 index 000000000..e770f94b2 --- /dev/null +++ b/frontends/windows/drawable.h @@ -0,0 +1,25 @@ +/* + * Copyright 2011 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_WINDOWS_DRAWABLE_H_ +#define _NETSURF_WINDOWS_DRAWABLE_H_ + +nserror nsws_create_drawable_class(HINSTANCE hinstance); +HWND nsws_window_create_drawable(HINSTANCE hinstance, HWND hparent, struct gui_window *gw); + +#endif /* _NETSURF_WINDOWS_DRAWABLE_H_ */ diff --git a/frontends/windows/file.c b/frontends/windows/file.c new file mode 100644 index 000000000..e9eb9caf9 --- /dev/null +++ b/frontends/windows/file.c @@ -0,0 +1,302 @@ +/* + * Copyright 2014, 2015 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 . + */ + +/** + * \file + * Windows file operation table implementation. + */ + +#include +#include +#include +#include +#include + +#include "utils/errors.h" +#include "utils/nsurl.h" +#include "utils/log.h" +#include "utils/utils.h" +#include "utils/corestrings.h" +#include "utils/url.h" +#include "utils/file.h" +#include "utils/string.h" +#include "desktop/browser.h" + +#include "windows/file.h" + +/** + * Generate a windows path from one or more component elemnts. + * + * If a string is allocated it must be freed by the caller. + * + * @param[in,out] str pointer to string pointer if this is NULL enough + * storage will be allocated for the complete path. + * @param[in,out] size The size of the space available if \a str not + * NULL on input and if not NULL set to the total + * output length on output. + * @param[in] nelm The number of elements. + * @param[in] ap The elements of the path as string pointers. + * @return NSERROR_OK and the complete path is written to str + * or error code on faliure. + */ +static nserror windows_mkpath(char **str, size_t *size, size_t nelm, va_list ap) +{ + return vsnstrjoin(str, size, '\\', nelm, ap); +} + + +/** + * Get the basename of a file using windows path handling. + * + * This gets the last element of a path and returns it. + * + * @param[in] path The path to extract the name from. + * @param[in,out] str Pointer to string pointer if this is NULL enough + * storage will be allocated for the path element. + * @param[in,out] size The size of the space available if \a + * str not NULL on input and set to the total + * output length on output. + * @return NSERROR_OK and the complete path is written to str + * or error code on faliure. + */ +static nserror windows_basename(const char *path, char **str, size_t *size) +{ + const char *leafname; + char *fname; + + if (path == NULL) { + return NSERROR_BAD_PARAMETER; + } + + leafname = strrchr(path, '\\'); + if (!leafname) { + leafname = path; + } else { + leafname += 1; + } + + fname = strdup(leafname); + if (fname == NULL) { + return NSERROR_NOMEM; + } + + *str = fname; + if (size != NULL) { + *size = strlen(fname); + } + return NSERROR_OK; +} + + +/** + * Create a path from a nsurl using windows file handling. + * + * @param[in] url The url to encode. + * @param[out] path_out A string containing the result path which should + * be freed by the caller. + * @return NSERROR_OK and the path is written to \a path or error code + * on faliure. + */ +static nserror windows_nsurl_to_path(struct nsurl *url, char **path_out) +{ + lwc_string *urlpath; + char *path; + bool match; + lwc_string *scheme; + nserror res; + + if ((url == NULL) || (path_out == NULL)) { + return NSERROR_BAD_PARAMETER; + } + + scheme = nsurl_get_component(url, NSURL_SCHEME); + + if (lwc_string_caseless_isequal(scheme, corestring_lwc_file, + &match) != lwc_error_ok) + { + return NSERROR_BAD_PARAMETER; + } + lwc_string_unref(scheme); + if (match == false) { + return NSERROR_BAD_PARAMETER; + } + + urlpath = nsurl_get_component(url, NSURL_PATH); + if (urlpath == NULL) { + return NSERROR_BAD_PARAMETER; + } + + res = url_unescape(lwc_string_data(urlpath), &path); + lwc_string_unref(urlpath); + if (res != NSERROR_OK) { + return res; + } + + /* if there is a drive: prefix treat path as DOS filename */ + if ((path[2] == ':') || (path[2] == '|')) { + char *sidx; /* slash index */ + + /* move the string down to remove leading / note the + * strlen is *not* copying too much data as we are + * moving the null too! + */ + memmove(path, path + 1, strlen(path)); + + /* swap / for \ */ + sidx = strrchr(path, '/'); + while (sidx != NULL) { + *sidx = '\\'; + sidx = strrchr(path, '/'); + } + } + /* if the path does not have a drive letter we return the + * complete path. + */ + /** @todo Need to check returning the unaltered path in this + * case is correct + */ + + *path_out = path; + + return NSERROR_OK; +} + + +/** + * Create a nsurl from a path using windows file handling. + * + * Perform the necessary operations on a path to generate a nsurl. + * + * @param[in] path The path to convert. + * @param[out] url_out pointer to recive the nsurl, The returned url + * should be unreferenced by the caller. + * @return NSERROR_OK and the url is placed in \a url or error code on + * faliure. + */ +static nserror windows_path_to_nsurl(const char *path, struct nsurl **url_out) +{ + nserror ret; + int urllen; + char *urlstr; + char *sidx; /* slash index */ + + if ((path == NULL) || (url_out == NULL) || (*path == 0)) { + return NSERROR_BAD_PARAMETER; + } + + /* build url as a string for nsurl constructor */ + urllen = strlen(path) + FILE_SCHEME_PREFIX_LEN + 5; + urlstr = malloc(urllen); + if (urlstr == NULL) { + return NSERROR_NOMEM; + } + + /** @todo check if this should be url escaping the path. */ + if (*path == '/') { + /* unix style path start, so try wine Z: */ + snprintf(urlstr, urllen, "%sZ%%3A%s", FILE_SCHEME_PREFIX, path); + } else { + snprintf(urlstr, urllen, "%s%s", FILE_SCHEME_PREFIX, path); + } + + sidx = strrchr(urlstr, '\\'); + while (sidx != NULL) { + *sidx = '/'; + sidx = strrchr(urlstr, '\\'); + } + + ret = nsurl_create(urlstr, url_out); + free(urlstr); + + return ret; +} + + +/** + * Ensure that all directory elements needed to store a filename exist. + * + * @param fname The filename to ensure the path to exists. + * @return NSERROR_OK on success or error code on failure. + */ +static nserror windows_mkdir_all(const char *fname) +{ + char *dname; + char *sep; + struct stat sb; + + dname = strdup(fname); + + sep = strrchr(dname, '\\'); + if (sep == NULL) { + /* no directory separator path is just filename so its ok */ + free(dname); + return NSERROR_OK; + } + + *sep = 0; /* null terminate directory path */ + + if (stat(dname, &sb) == 0) { + free(dname); + if (S_ISDIR(sb.st_mode)) { + /* path to file exists and is a directory */ + return NSERROR_OK; + } + return NSERROR_NOT_DIRECTORY; + } + *sep = '\\'; /* restore separator */ + + sep = dname; + while (*sep == '\\') { + sep++; + } + while ((sep = strchr(sep, '\\')) != NULL) { + *sep = 0; + if (stat(dname, &sb) != 0) { + if (nsmkdir(dname, S_IRWXU) != 0) { + /* could not create path element */ + free(dname); + return NSERROR_NOT_FOUND; + } + } else { + if (! S_ISDIR(sb.st_mode)) { + /* path element not a directory */ + free(dname); + return NSERROR_NOT_DIRECTORY; + } + } + *sep = '\\'; /* restore separator */ + /* skip directory separators */ + while (*sep == '\\') { + sep++; + } + } + + free(dname); + return NSERROR_OK; +} + +/* windows file handling */ +static struct gui_file_table file_table = { + .mkpath = windows_mkpath, + .basename = windows_basename, + .nsurl_to_path = windows_nsurl_to_path, + .path_to_nsurl = windows_path_to_nsurl, + .mkdir_all = windows_mkdir_all, +}; + +struct gui_file_table *win32_file_table = &file_table; diff --git a/frontends/windows/file.h b/frontends/windows/file.h new file mode 100644 index 000000000..5262dde2c --- /dev/null +++ b/frontends/windows/file.h @@ -0,0 +1,29 @@ +/* + * Copyright 2015 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 . + */ + +/** + * \file + * Windows file operation table interface. + */ + +#ifndef _NETSURF_WINDOWS_FILE_H_ +#define _NETSURF_WINDOWS_FILE_H_ + +struct gui_file_table *win32_file_table; + +#endif diff --git a/frontends/windows/filetype.c b/frontends/windows/filetype.c new file mode 100644 index 000000000..b06534d6a --- /dev/null +++ b/frontends/windows/filetype.c @@ -0,0 +1,60 @@ +/* + * 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 "utils/log.h" +#include "utils/utils.h" +#include "content/fetch.h" +#include "desktop/gui_fetch.h" + +#include "windows/filetype.h" + +/** + * filetype -- determine the MIME type of a local file + */ +static 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"; +} + +static struct gui_fetch_table fetch_table = { + .filetype = fetch_filetype, +}; + +struct gui_fetch_table *win32_fetch_table = &fetch_table; diff --git a/frontends/windows/filetype.h b/frontends/windows/filetype.h new file mode 100644 index 000000000..f71a0b2da --- /dev/null +++ b/frontends/windows/filetype.h @@ -0,0 +1,24 @@ +/* + * Copyright 2014 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_WINDOWS_FILETYPE_H_ +#define _NETSURF_WINDOWS_FILETYPE_H_ + +struct gui_fetch_table *win32_fetch_table; + +#endif diff --git a/frontends/windows/findfile.c b/frontends/windows/findfile.c new file mode 100644 index 000000000..8c8906a80 --- /dev/null +++ b/frontends/windows/findfile.c @@ -0,0 +1,156 @@ +/* + * 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 +#include + + +#include + +#include "utils/log.h" +#include "utils/url.h" +#include "utils/utils.h" +#include "utils/filepath.h" + +#include "windows/findfile.h" + +/** Create an array of valid paths to search for resources. + * + * The idea is that all the complex path computation to find resources + * is performed here, once, rather than every time a resource is + * searched for. + */ +char ** +nsws_init_resource(const char *resource_path) +{ + char **pathv; /* resource path string vector */ + char **respath; /* resource paths vector */ + const char *lang = NULL; + char *winpath; + int pathi; + char *slsh; + + pathv = filepath_path_to_strvec(resource_path); + if (pathv == NULL) + return NULL; + + winpath = malloc(MAX_PATH); + GetModuleFileName(NULL, winpath, MAX_PATH); + slsh = strrchr(winpath, '\\'); + if (slsh != NULL) + *slsh=0; + strncat(winpath, "\\windows\\res", MAX_PATH); + + pathi = 0; + while (pathv[pathi] != NULL) + pathi++; + pathv[pathi] = winpath; + + respath = filepath_generate(pathv, &lang); + + filepath_free_strvec(pathv); + + return respath; +} + +static char *realpath(const char *path, char *resolved_path) +{ + /* useless, but there we go */ + return strncpy(resolved_path, path, PATH_MAX); +} + + +/** + * Locate a shared resource file by searching known places in order. + * + * 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] + * + * \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 The passed in buffer + */ + +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/frontends/windows/findfile.h b/frontends/windows/findfile.h new file mode 100644 index 000000000..808adc8ef --- /dev/null +++ b/frontends/windows/findfile.h @@ -0,0 +1,26 @@ +/* + * 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_ + +extern char *nsws_find_resource(char *buf, const char *filename, const char *def); + +char **nsws_init_resource(const char *resource_path); + +#endif /* _NETSURF_WINDOWS_FINDFILE_H_ */ diff --git a/frontends/windows/font.c b/frontends/windows/font.c new file mode 100644 index 000000000..f67205a6f --- /dev/null +++ b/frontends/windows/font.c @@ -0,0 +1,298 @@ +/* + * Copyright 2009 - 2014 Vincent Sanders + * Copyright 2009 - 2013 Michael Drake + * + * 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 . + */ + +/** + * \file + * Windows font handling implementation. + */ + +#include "utils/config.h" +#include +#include +#include + +#include "utils/log.h" +#include "utils/nsoption.h" +#include "utils/utf8.h" +#include "desktop/gui_layout.h" +#include "desktop/gui_utf8.h" + +#include "windows/font.h" + +HWND font_hwnd; + +nserror 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); +} + +static nserror utf8_to_local_encoding(const char *string, + size_t len, + char **result) +{ + return utf8_to_enc(string, "UCS-2", len, result); +} + +static nserror utf8_from_local_encoding(const char *string, size_t len, + char **result) +{ + assert(string && result); + + if (len == 0) + len = strlen(string); + + *result = strndup(string, len); + if (!(*result)) + return NSERROR_NOMEM; + + return NSERROR_OK; +} + +HFONT get_font(const plot_font_style_t *style) +{ + char *face = NULL; + DWORD family; + switch(style->family) { + case PLOT_FONT_FAMILY_SERIF: + face = strdup(nsoption_charp(font_serif)); + family = FF_ROMAN | DEFAULT_PITCH; + break; + case PLOT_FONT_FAMILY_MONOSPACE: + face = strdup(nsoption_charp(font_mono)); + family = FF_MODERN | DEFAULT_PITCH; + break; + case PLOT_FONT_FAMILY_CURSIVE: + face = strdup(nsoption_charp(font_cursive)); + family = FF_SCRIPT | DEFAULT_PITCH; + break; + case PLOT_FONT_FAMILY_FANTASY: + face = strdup(nsoption_charp(font_fantasy)); + family = FF_DECORATIVE | DEFAULT_PITCH; + break; + case PLOT_FONT_FAMILY_SANS_SERIF: + default: + face = strdup(nsoption_charp(font_sans)); + family = FF_SWISS | DEFAULT_PITCH; + break; + } + + int nHeight = -10; + + HDC hdc = GetDC(font_hwnd); + nHeight = -MulDiv(style->size, GetDeviceCaps(hdc, LOGPIXELSY), 72 * FONT_SIZE_SCALE); + ReleaseDC(font_hwnd, hdc); + + HFONT font = CreateFont( + nHeight, /* height */ + 0, /* width */ + 0, /* escapement*/ + 0, /* orientation */ + style->weight, + (style->flags & FONTF_ITALIC) ? TRUE : FALSE, + FALSE, /* underline */ + FALSE, /* strike */ + DEFAULT_CHARSET, /* for locale */ + OUT_DEFAULT_PRECIS, /* general 'best match' */ + CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, + family, + face /* name of font face */ + ); + if (face != NULL) + 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; +} + +/** + * Measure the width of a string. + * + * \param[in] style plot style for this text + * \param[in] string UTF-8 string to measure + * \param[in] length length of string, in bytes + * \param[out] width updated to width of string[0..length) + * \return true on success and width updated else false + */ +static nserror +win32_font_width(const plot_font_style_t *style, + const char *string, + size_t length, + int *width) +{ + HDC hdc; + HFONT font; + HFONT fontbak; + SIZE s; + bool ret = true; + + if (length == 0) { + *width = 0; + } else { + hdc = GetDC(NULL); + font = get_font(style); + fontbak = SelectObject(hdc, font); + + /* may well need to convert utf-8 to lpctstr */ + if (GetTextExtentPoint32A(hdc, string, length, &s) != 0) { + *width = s.cx; + } else { + ret = false; + } + font = SelectObject(hdc, fontbak); + DeleteObject(font); + ReleaseDC(NULL, hdc); + } + return ret; +} + + +/** + * 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 nserror +win32_font_position(const plot_font_style_t *style, + const char *string, + size_t length, + int x, + size_t *char_offset, + int *actual_x) +{ + HDC hdc; + HFONT font; + HFONT fontbak; + SIZE s; + int offset; + bool ret = true; + + if ((length == 0) || (x < 1)) { + *char_offset = 0; + *actual_x = 0; + } else { + hdc = GetDC(NULL); + font = get_font(style); + fontbak = SelectObject(hdc, font); + + if ((GetTextExtentExPointA(hdc, string, length, x, &offset, NULL,&s) != 0) && + (GetTextExtentPoint32A(hdc, string, offset, &s) != 0)) { + *char_offset = (size_t)offset; + *actual_x = s.cx; + } else { + ret = false; + } + font = SelectObject(hdc, fontbak); + DeleteObject(font); + ReleaseDC(NULL, hdc); + } + + return ret; +} + + +/** + * 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 nserror +win32_font_split(const plot_font_style_t *style, + const char *string, + size_t length, + int x, + size_t *char_offset, + int *actual_x) +{ + int c_off; + bool ret = false; + + if (win32_font_position(style, string, length, x, char_offset, actual_x)) { + c_off = *char_offset; + if (*char_offset == length) { + ret = true; + } else { + while ((string[*char_offset] != ' ') && + (*char_offset > 0)) { + (*char_offset)--; + } + + if (*char_offset == 0) { + *char_offset = c_off; + while ((*char_offset < length) && + (string[*char_offset] != ' ')) { + (*char_offset)++; + } + } + + ret = win32_font_width(style, string, *char_offset, actual_x); + } + } + +/* + LOG("ret %d Split %u chars at %ipx: Split at char %i (%ipx) - %.*s", + ret, length, x, *char_offset, *actual_x, *char_offset, string); +*/ + return ret; +} + + +static struct gui_layout_table layout_table = { + .width = win32_font_width, + .position = win32_font_position, + .split = win32_font_split, +}; + +struct gui_layout_table *win32_layout_table = &layout_table; + + +static struct gui_utf8_table utf8_table = { + .utf8_to_local = utf8_to_local_encoding, + .local_to_utf8 = utf8_from_local_encoding, +}; + +struct gui_utf8_table *win32_utf8_table = &utf8_table; diff --git a/frontends/windows/font.h b/frontends/windows/font.h new file mode 100644 index 000000000..f2128afc5 --- /dev/null +++ b/frontends/windows/font.h @@ -0,0 +1,53 @@ +/* + * 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 . + */ + +/** + * \file + * The interface to the win32 font and utf8 handling. + */ + +#ifndef _NETSURF_WINDOWS_FONT_H_ +#define _NETSURF_WINDOWS_FONT_H_ + +extern HWND font_hwnd; + +struct font_desc { + const char *name; + int width, height; + const char *encoding; +}; + +struct gui_layout_table *win32_layout_table; +struct gui_utf8_table *win32_utf8_table; + +extern nserror utf8_to_font_encoding(const struct font_desc* font, + const char *string, + size_t len, + char **result); + +/** + * generate a win32 font handle from a generic font style + * + * \param style The font style. + * \return The win32 font handle + */ +HFONT get_font(const plot_font_style_t *style); + +#endif /* NETSURF_WINDOWS_FONT_H */ + diff --git a/frontends/windows/gui.c b/frontends/windows/gui.c new file mode 100644 index 000000000..9923ecfaa --- /dev/null +++ b/frontends/windows/gui.c @@ -0,0 +1,170 @@ +/* + * 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 "utils/errors.h" +#include "utils/nsurl.h" +#include "utils/log.h" +#include "utils/utils.h" +#include "utils/corestrings.h" +#include "utils/url.h" +#include "utils/file.h" +#include "utils/messages.h" +#include "desktop/browser.h" +#include "desktop/gui_clipboard.h" + +#include "windows/schedule.h" +#include "windows/window.h" +#include "windows/filetype.h" +#include "windows/gui.h" + +static bool win32_quit = false; + +HINSTANCE hInstance; /** win32 application instance handle. */ + + +void win32_set_quit(bool q) +{ + win32_quit = q; +} + +/* exported interface documented in gui.h */ +void win32_run(void) +{ + MSG Msg; /* message from system */ + BOOL bRet; /* message fetch result */ + int timeout; /* timeout in miliseconds */ + UINT timer_id = 0; + + LOG("Starting messgae dispatcher"); + + while (!win32_quit) { + /* run the scheduler and discover how long to wait for + * the next event. + */ + timeout = schedule_run(); + + if (timeout == 0) { + bRet = PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE); + } else { + if (timeout > 0) { + /* set up a timer to ensure we get woken */ + timer_id = SetTimer(NULL, 0, timeout, NULL); + } + + /* wait for a message */ + bRet = GetMessage(&Msg, NULL, 0, 0); + + /* if a timer was sucessfully created remove it */ + if (timer_id != 0) { + KillTimer(NULL, timer_id); + timer_id = 0; + } + } + + if (bRet > 0) { + TranslateMessage(&Msg); + DispatchMessage(&Msg); + } + } +} + + +/* exported function documented in windows/gui.h */ +nserror win32_warning(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); + + return NSERROR_OK; +} + + +/** + * Core asks front end for clipboard contents. + * + * \param buffer UTF-8 text, allocated by front end, ownership yeilded to core + * \param length Byte length of UTF-8 text in buffer + */ +static void gui_get_clipboard(char **buffer, size_t *length) +{ + /* TODO: Implement this */ + 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); + } +} + + +/** + * Core tells front end to put given text in clipboard + * + * \param buffer UTF-8 text, owned by core + * \param length Byte length of UTF-8 text in buffer + * \param styles Array of styles given to text runs, owned by core, or NULL + * \param n_styles Number of text run styles in array + */ +static void gui_set_clipboard(const char *buffer, size_t length, + nsclipboard_styles styles[], int n_styles) +{ + /* TODO: Implement this */ + HANDLE hnew; + char *new, *original; + HANDLE h = GetClipboardData(CF_TEXT); + if (h == NULL) + original = (char *)""; + else + original = GlobalLock(h); + + size_t len = strlen(original) + 1; + hnew = GlobalAlloc(GHND, length + len); + new = (char *)GlobalLock(hnew); + snprintf(new, length + len, "%s%s", original, buffer); + + if (h != NULL) { + GlobalUnlock(h); + EmptyClipboard(); + } + GlobalUnlock(hnew); + SetClipboardData(CF_TEXT, hnew); +} + + + +static struct gui_clipboard_table clipboard_table = { + .get = gui_get_clipboard, + .set = gui_set_clipboard, +}; + +struct gui_clipboard_table *win32_clipboard_table = &clipboard_table; + + diff --git a/frontends/windows/gui.h b/frontends/windows/gui.h new file mode 100644 index 000000000..4c3f360b1 --- /dev/null +++ b/frontends/windows/gui.h @@ -0,0 +1,58 @@ +/* + * 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_ + +struct gui_window; +struct gui_clipboard_table *win32_clipboard_table; + +extern HINSTANCE hInstance; + +extern char *options_file_location; + +/* bounding box */ +typedef struct bbox_s { + int x0; + int y0; + int x1; + int y1; +} bbox_t; + +/** + * Run the win32 message loop with scheduling + */ +void win32_run(void); + +/** + * cause the main message loop to exit + */ +void win32_set_quit(bool q); + +/** + * Warn the user of an event. + * + * \param[in] message A warning looked up in the message translation table + * \param[in] detail Additional text to be displayed or NULL. + * \return NSERROR_OK on success or error code if there was a + * faliure displaying the message to the user. + */ +nserror win32_warning(const char *warning, const char *detail); + +#endif diff --git a/frontends/windows/localhistory.c b/frontends/windows/localhistory.c new file mode 100644 index 000000000..674f198a0 --- /dev/null +++ b/frontends/windows/localhistory.c @@ -0,0 +1,401 @@ +/* + * 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 "utils/config.h" + +#include +#include +#include + +#include "desktop/browser_history.h" +#include "desktop/plotters.h" +#include "utils/utils.h" +#include "utils/log.h" +#include "utils/messages.h" + +#include "windows/window.h" +#include "windows/localhistory.h" +#include "windows/gui.h" +#include "windows/plot.h" +#include "windows/resourceid.h" +#include "windows/windbg.h" + +static const char windowclassname_localhistory[] = "nswslocalhistorywindow"; + +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 void nsws_localhistory_scroll_check(struct nsws_localhistory *l, struct gui_window *gw) +{ + SCROLLINFO si; + + if ((gw->bw == NULL) || (l->hwnd == NULL)) + return; + + browser_window_history_size(gw->bw, &(l->width), &(l->height)); + + si.cbSize = sizeof(si); + si.fMask = SIF_ALL; + si.nMin = 0; + si.nMax = l->height; + si.nPage = l->guiheight; + si.nPos = 0; + SetScrollInfo(l->hwnd, SB_VERT, &si, TRUE); + + si.nMax = l->width; + si.nPage = l->guiwidth; + SetScrollInfo(l->hwnd, SB_HORZ, &si, TRUE); + if (l->guiheight >= l->height) + l->vscroll = 0; + if (l->guiwidth >= l->width) + l->hscroll = 0; + SendMessage(l->hwnd, WM_PAINT, 0, 0); +} + + + +static void nsws_localhistory_up(struct nsws_localhistory *l, struct gui_window *gw) +{ + HDC tmp_hdc; + struct redraw_context ctx = { + .interactive = true, + .background_images = true, + .plot = &win_plotters + }; + + LOG("gui window %p", gw); + + l->vscroll = 0; + l->hscroll = 0; + + if (gw->bw != NULL) { + /* set global HDC for the plotters */ + tmp_hdc = plot_hdc; + plot_hdc = GetDC(l->hwnd); + + browser_window_history_redraw(gw->bw, &ctx); + + ReleaseDC(l->hwnd, plot_hdc); + + plot_hdc = tmp_hdc; + } + + nsws_localhistory_scroll_check(l, gw); +} + + +void nsws_localhistory_close(struct gui_window *w) +{ + struct nsws_localhistory *l = gui_window_localhistory(w); + if (l != NULL) + CloseWindow(l->hwnd); +} + +static LRESULT CALLBACK +nsws_localhistory_event_callback(HWND hwnd, UINT msg, + WPARAM wparam, LPARAM lparam) +{ + int x,y; + struct gui_window *gw; + + LOG_WIN_MSG(hwnd, msg, wparam, lparam); + + gw = nsws_get_gui_window(hwnd); + if (gw == NULL) { + LOG("Unable to find gui window structure for hwnd %p", hwnd); + return DefWindowProc(hwnd, msg, wparam, lparam); + } + + switch(msg) { + + case WM_CREATE: + nsws_localhistory_scroll_check(gw->localhistory, gw); + break; + + case WM_SIZE: + gw->localhistory->guiheight = HIWORD(lparam); + gw->localhistory->guiwidth = LOWORD(lparam); + nsws_localhistory_scroll_check(gw->localhistory, gw); + break; + + case WM_LBUTTONUP: + if (gw->bw == NULL) + break; + + x = GET_X_LPARAM(lparam); + y = GET_Y_LPARAM(lparam); + + if (browser_window_history_click(gw->bw, + gw->localhistory->hscroll + x, + gw->localhistory->vscroll + y, + false)) { + DestroyWindow(hwnd); + } + + break; + + case WM_MOUSEMOVE: + x = GET_X_LPARAM(lparam); + y = GET_Y_LPARAM(lparam); + return DefWindowProc(hwnd, msg, wparam, lparam); + break; + + + case WM_VSCROLL: + { + 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 -= gw->localhistory->guiheight; + break; + case SB_PAGEDOWN: + si.nPos += gw->localhistory->guiheight; + break; + case SB_THUMBTRACK: + si.nPos = si.nTrackPos; + break; + default: + break; + } + si.nPos = min(si.nPos, gw->localhistory->height); + si.nPos = min(si.nPos, 0); + si.fMask = SIF_POS; + SetScrollInfo(hwnd, SB_VERT, &si, TRUE); + GetScrollInfo(hwnd, SB_VERT, &si); + if (si.nPos != mem) { + gw->localhistory->vscroll += si.nPos - mem; + ScrollWindowEx(hwnd, 0, -(si.nPos - mem), NULL, NULL, NULL, NULL, SW_ERASE | SW_INVALIDATE); + } + break; + } + + case WM_HSCROLL: + { + 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 -= gw->localhistory->guiwidth; + break; + case SB_PAGERIGHT: + si.nPos += gw->localhistory->guiwidth; + break; + case SB_THUMBTRACK: + si.nPos = si.nTrackPos; + break; + default: + break; + } + si.nPos = min(si.nPos, gw->localhistory->width); + 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) { + gw->localhistory->hscroll += si.nPos - mem; + ScrollWindowEx(hwnd, -(si.nPos - mem), 0, NULL, NULL, NULL, NULL, SW_ERASE | SW_INVALIDATE); + } + break; + } + + case WM_PAINT: { + PAINTSTRUCT ps; + HDC hdc, tmp_hdc; + struct redraw_context ctx = { + .interactive = true, + .background_images = true, + .plot = &win_plotters + }; + + hdc = BeginPaint(hwnd, &ps); + if (gw->bw != NULL) { + /* set global HDC for the plotters */ + tmp_hdc = plot_hdc; + plot_hdc = hdc; + + browser_window_history_redraw_rectangle(gw->bw, + gw->localhistory->hscroll + ps.rcPaint.left, + gw->localhistory->vscroll + ps.rcPaint.top, + gw->localhistory->hscroll + (ps.rcPaint.right - ps.rcPaint.left), + gw->localhistory->vscroll + (ps.rcPaint.bottom - ps.rcPaint.top), + ps.rcPaint.left, + ps.rcPaint.top, &ctx); + + plot_hdc = tmp_hdc; + + } + EndPaint(hwnd, &ps); + + break; + } + + case WM_CLOSE: + DestroyWindow(hwnd); + return 1; + + case WM_DESTROY: + free(gw->localhistory); + gw->localhistory = NULL; + break; + + default: + return DefWindowProc(hwnd, msg, wparam, lparam); + + } + return 0; +} + +/* exported method documented in windows/localhistory.h */ +struct nsws_localhistory *nsws_window_create_localhistory(struct gui_window *gw) +{ + struct nsws_localhistory *localhistory; + INITCOMMONCONTROLSEX icc; + int margin = 50; + RECT r; + + LOG("gui window %p", gw); + + /* if we already have a window, just update and re-show it */ + if (gw->localhistory != NULL) { + nsws_localhistory_up(gw->localhistory, gw); + UpdateWindow(gw->localhistory->hwnd); + ShowWindow(gw->localhistory->hwnd, SW_SHOWNORMAL); + return gw->localhistory; + } + + localhistory = calloc(1, sizeof(struct nsws_localhistory)); + + if (localhistory == NULL) { + return NULL; + } + gw->localhistory = localhistory; + + localhistory->width = 0; + localhistory->height = 0; + + if (gw->bw != NULL) { + browser_window_history_size(gw->bw, + &(localhistory->width), + &(localhistory->height)); + } + + GetWindowRect(gw->main, &r); + SetWindowPos(gw->main, 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); + + + LOG("creating local history window for hInstance %p", hInstance); + localhistory->hwnd = CreateWindow(windowclassname_localhistory, + "NetSurf History", + WS_THICKFRAME | WS_HSCROLL | + WS_VSCROLL | WS_CLIPCHILDREN | + WS_CLIPSIBLINGS | WS_SYSMENU | CS_DBLCLKS, + r.left + margin/2, + r.top + margin/2, + localhistory->guiwidth, + localhistory->guiheight, + NULL, NULL, hInstance, NULL); + + /* set the gui window associated with this browser */ + SetProp(localhistory->hwnd, TEXT("GuiWnd"), (HANDLE)gw); + + LOG("gui_window %p width %d height %d hwnd %p", gw, localhistory->guiwidth, localhistory->guiheight, localhistory->hwnd); + + nsws_localhistory_up(localhistory, gw); + UpdateWindow(localhistory->hwnd); + ShowWindow(localhistory->hwnd, SW_SHOWNORMAL); + + return localhistory; +} + +/* exported method documented in windows/localhistory.h */ +nserror +nsws_create_localhistory_class(HINSTANCE hinstance) { + nserror ret = NSERROR_OK; + WNDCLASSEX w; + + /* localhistory window */ + w.cbSize = sizeof(WNDCLASSEX); + w.style = 0; + w.lpfnWndProc = nsws_localhistory_event_callback; + w.cbClsExtra = 0; + w.cbWndExtra = 0; + w.hInstance = hinstance; + w.hIcon = LoadIcon(hinstance, MAKEINTRESOURCE(IDR_NETSURF_ICON)); + w.hCursor = LoadCursor(NULL, IDC_ARROW); + w.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + w.lpszMenuName = NULL; + w.lpszClassName = windowclassname_localhistory; + w.hIconSm = LoadIcon(hinstance, MAKEINTRESOURCE(IDR_NETSURF_ICON)); + + if (RegisterClassEx(&w) == 0) { + win_perror("DrawableClass"); + ret = NSERROR_INIT_FAILED; + } + + return ret; +} diff --git a/frontends/windows/localhistory.h b/frontends/windows/localhistory.h new file mode 100644 index 000000000..b0ad07491 --- /dev/null +++ b/frontends/windows/localhistory.h @@ -0,0 +1,32 @@ +/* +* 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_ + +struct nsws_localhistory; + +void nsws_localhistory_open(struct gui_window *gw); +void nsws_localhistory_close(struct gui_window *gw); + +/* creates localhistory window */ +struct nsws_localhistory *nsws_window_create_localhistory(struct gui_window *gw); + +nserror nsws_create_localhistory_class(HINSTANCE hinstance); + +#endif diff --git a/frontends/windows/main.c b/frontends/windows/main.c new file mode 100644 index 000000000..df64e487d --- /dev/null +++ b/frontends/windows/main.c @@ -0,0 +1,271 @@ +/* + * Copyright 2011 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 "utils/config.h" + +#include +#include +#include +#include + +#include "utils/utils.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/filepath.h" +#include "utils/file.h" +#include "utils/nsurl.h" +#include "utils/nsoption.h" +#include "desktop/browser.h" +#include "desktop/gui_fetch.h" +#include "desktop/gui_misc.h" +#include "desktop/netsurf.h" + +#include "windows/findfile.h" +#include "windows/file.h" +#include "windows/drawable.h" +#include "windows/download.h" +#include "windows/localhistory.h" +#include "windows/window.h" +#include "windows/schedule.h" +#include "windows/font.h" +#include "windows/filetype.h" +#include "windows/pointers.h" +#include "windows/bitmap.h" +#include "windows/gui.h" + +static char **respaths; /** resource search path vector. */ + +char *options_file_location; + +/** + * Cause an abnormal program termination. + * + * \note This never returns and is intended to terminate without any cleanup. + * + * \param error The message to display to the user. + */ +static void die(const char *error) +{ + exit(1); +} + + +static nsurl *gui_get_resource_url(const char *path) +{ + char buf[PATH_MAX]; + nsurl *url = NULL; + + netsurf_path_to_nsurl(filepath_sfind(respaths, buf, path), &url); + + return url; +} + +/** + * Ensures output logging stream is available + */ +static bool nslog_ensure(FILE *fptr) +{ + /* mwindows compile flag normally invalidates standard io unless + * already redirected + */ + if (_get_osfhandle(fileno(fptr)) == -1) { + AllocConsole(); + freopen("CONOUT$", "w", fptr); + } + return true; +} + +/** + * Set option defaults for windows frontend + * + * @param defaults The option table to update. + * @return error status. + */ +static nserror set_defaults(struct nsoption_s *defaults) +{ + /* Set defaults for absent option strings */ + + /* locate CA bundle and set as default, cannot rely on curl + * compiled in default on windows. + */ + DWORD res_len; + DWORD buf_tchar_size = PATH_MAX + 1; + DWORD buf_bytes_size = sizeof(TCHAR) * buf_tchar_size; + char *ptr = NULL; + + char *buf; + + buf = malloc(buf_bytes_size); + if (buf== NULL) { + return NSERROR_NOMEM; + } + buf[0] = '\0'; + + res_len = SearchPathA(NULL, + "ca-bundle.crt", + NULL, + buf_tchar_size, + buf, + &ptr); + if (res_len > 0) { + nsoption_setnull_charp(ca_bundle, strdup(buf)); + } + free(buf); + + /* ensure homepage option has a default */ + nsoption_setnull_charp(homepage_url, strdup(NETSURF_HOMEPAGE)); + + return NSERROR_OK; +} + + +static struct gui_misc_table win32_misc_table = { + .schedule = win32_schedule, + .warning = win32_warning, +}; + + +/** + * Entry point from windows + **/ +int WINAPI +WinMain(HINSTANCE hInstance, HINSTANCE hLastInstance, LPSTR lpcli, int ncmd) +{ + char **argv = NULL; + int argc = 0, argctemp = 0; + size_t len; + LPWSTR *argvw; + char *messages; + nserror ret; + const char *addr; + nsurl *url; + struct netsurf_table win32_table = { + .misc = &win32_misc_table, + .window = win32_window_table, + .clipboard = win32_clipboard_table, + .download = win32_download_table, + .fetch = win32_fetch_table, + .file = win32_file_table, + .utf8 = win32_utf8_table, + .bitmap = win32_bitmap_table, + .layout = win32_layout_table, + }; + win32_fetch_table->get_resource_url = gui_get_resource_url; + + ret = netsurf_register(&win32_table); + if (ret != NSERROR_OK) { + die("NetSurf operation table registration failed"); + } + + if (SLEN(lpcli) > 0) { + argvw = CommandLineToArgvW(GetCommandLineW(), &argc); + } + + 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 + * hyphen flags. + */ + if (argv[argctemp][0] == '/') + argv[argctemp][0] = '-'; + } + argctemp++; + } + + respaths = nsws_init_resource("${APPDATA}\\NetSurf:${HOME}\\.netsurf:${NETSURFRES}:${PROGRAMFILES}\\NetSurf\\NetSurf\\:"NETSURF_WINDOWS_RESPATH); + + + options_file_location = filepath_find(respaths, "preferences"); + + /* initialise logging - not fatal if it fails but not much we + * can do about it + */ + nslog_init(nslog_ensure, &argc, argv); + + /* user options setup */ + ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default); + if (ret != NSERROR_OK) { + die("Options failed to initialise"); + } + nsoption_read(options_file_location, NULL); + nsoption_commandline(&argc, argv, NULL); + + /* message init */ + messages = filepath_find(respaths, "messages"); + messages_add_from_file(messages); + free(messages); + + /* common initialisation */ + ret = netsurf_init(NULL); + if (ret != NSERROR_OK) { + free(options_file_location); + LOG("NetSurf failed to initialise"); + return 1; + } + + ret = nsws_create_main_class(hInstance); + ret = nsws_create_drawable_class(hInstance); + ret = nsws_create_localhistory_class(hInstance); + + nsoption_set_bool(target_blank, false); + + nsws_window_init_pointers(hInstance); + + /* If there is a url specified on the command line use it */ + if (argc > 1) { + addr = argv[1]; + } else if (nsoption_charp(homepage_url) != NULL) { + addr = nsoption_charp(homepage_url); + } else { + addr = NETSURF_HOMEPAGE; + } + + LOG("calling browser_window_create"); + + ret = nsurl_create(addr, &url); + if (ret == NSERROR_OK) { + ret = browser_window_create(BW_CREATE_HISTORY, + url, + NULL, + NULL, + NULL); + nsurl_unref(url); + + } + if (ret != NSERROR_OK) { + win32_warning(messages_get_errorcode(ret), 0); + } else { + win32_run(); + } + + netsurf_exit(); + + free(options_file_location); + + return 0; +} diff --git a/frontends/windows/plot.c b/frontends/windows/plot.c new file mode 100644 index 000000000..86870ea4e --- /dev/null +++ b/frontends/windows/plot.c @@ -0,0 +1,868 @@ +/* + * 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 "utils/config.h" +#include +#include +#include +#include +#include +#include + +#include "utils/log.h" +#include "utils/utf8.h" +#include "utils/utils.h" +#include "desktop/mouse.h" +#include "desktop/gui_window.h" +#include "desktop/plotters.h" + +#include "windows/bitmap.h" +#include "windows/font.h" +#include "windows/gui.h" +#include "windows/plot.h" + + +/* set NSWS_PLOT_DEBUG to 0 for no debugging, 1 for debugging */ +/* #define NSWS_PLOT_DEBUG */ + +#ifdef NSWS_PLOT_DEBUG +#define PLOT_LOG(x...) LOG(x) +#else +#define PLOT_LOG(x...) ((void) 0) +#endif + +HDC plot_hdc; + +static RECT plot_clip; /* currently set clipping rectangle */ + +static bool clip(const struct rect *clip) +{ + PLOT_LOG("clip %d,%d to %d,%d", clip->x0, clip->y0, clip->x1, clip->y1); + + plot_clip.left = clip->x0; + plot_clip.top = clip->y0; + plot_clip.right = clip->x1 + 1; /* co-ordinates are exclusive */ + plot_clip.bottom = clip->y1 + 1; /* co-ordinates are exclusive */ + + return true; +} + +static bool line(int x0, int y0, int x1, int y1, const plot_style_t *style) +{ + PLOT_LOG("from %d,%d to %d,%d", x0, y0, x1, y1); + + /* ensure the plot HDC is set */ + if (plot_hdc == NULL) { + LOG("HDC not set on call to plotters"); + return false; + } + + HRGN clipregion = CreateRectRgnIndirect(&plot_clip); + if (clipregion == NULL) { + 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); + return false; + } + HGDIOBJ bak = SelectObject(plot_hdc, (HGDIOBJ) pen); + if (bak == NULL) { + DeleteObject(pen); + DeleteObject(clipregion); + return false; + } +/* + RECT r; + r.left = x0; + r.top = y0; + r.right = x1; + r.bottom = y1; +*/ + SelectClipRgn(plot_hdc, clipregion); + + MoveToEx(plot_hdc, x0, y0, (LPPOINT) NULL); + + LineTo(plot_hdc, x1, y1); + + SelectClipRgn(plot_hdc, NULL); + pen = SelectObject(plot_hdc, bak); + + DeleteObject(pen); + DeleteObject(clipregion); + + return true; +} + +static bool rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style) +{ + PLOT_LOG("rectangle from %d,%d to %d,%d", x0, y0, x1, y1); + + /* ensure the plot HDC is set */ + if (plot_hdc == NULL) { + LOG("HDC not set on call to plotters"); + return false; + } + + HRGN clipregion = CreateRectRgnIndirect(&plot_clip); + if (clipregion == NULL) { + return false; + } + + x1++; + y1++; + + 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) { + return false; + } + HGDIOBJ penbak = SelectObject(plot_hdc, (HGDIOBJ) pen); + if (penbak == NULL) { + DeleteObject(pen); + return false; + } + HBRUSH brush = CreateBrushIndirect(&lb1); + if (brush == NULL) { + SelectObject(plot_hdc, penbak); + DeleteObject(pen); + return false; + } + HGDIOBJ brushbak = SelectObject(plot_hdc, (HGDIOBJ) brush); + if (brushbak == NULL) { + SelectObject(plot_hdc, penbak); + DeleteObject(pen); + DeleteObject(brush); + return false; + } + + SelectClipRgn(plot_hdc, clipregion); + + Rectangle(plot_hdc, x0, y0, x1, y1); + + pen = SelectObject(plot_hdc, penbak); + brush = SelectObject(plot_hdc, brushbak); + SelectClipRgn(plot_hdc, NULL); + DeleteObject(pen); + DeleteObject(brush); + DeleteObject(clipregion); + + return true; +} + + +static bool polygon(const int *p, unsigned int n, const plot_style_t *style) +{ + PLOT_LOG("polygon %d points", n); + + /* ensure the plot HDC is set */ + if (plot_hdc == NULL) { + LOG("HDC not set on call to plotters"); + return false; + } + + POINT points[n]; + unsigned int i; + HRGN clipregion = CreateRectRgnIndirect(&plot_clip); + if (clipregion == NULL) { + 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); + return false; + } + HPEN penbak = SelectObject(plot_hdc, pen); + if (penbak == NULL) { + DeleteObject(clipregion); + DeleteObject(pen); + return false; + } + HBRUSH brush = CreateSolidBrush(brushcol); + if (brush == NULL) { + DeleteObject(clipregion); + SelectObject(plot_hdc, penbak); + DeleteObject(pen); + return false; + } + HBRUSH brushbak = SelectObject(plot_hdc, brush); + if (brushbak == NULL) { + DeleteObject(clipregion); + SelectObject(plot_hdc, penbak); + DeleteObject(pen); + DeleteObject(brush); + return false; + } + SetPolyFillMode(plot_hdc, WINDING); + for (i = 0; i < n; i++) { + points[i].x = (long) p[2 * i]; + points[i].y = (long) p[2 * i + 1]; + + PLOT_LOG("%ld,%ld ", points[i].x, points[i].y); + } + + SelectClipRgn(plot_hdc, clipregion); + + if (n >= 2) + Polygon(plot_hdc, points, n); + + SelectClipRgn(plot_hdc, NULL); + + pen = SelectObject(plot_hdc, penbak); + brush = SelectObject(plot_hdc, brushbak); + DeleteObject(clipregion); + DeleteObject(pen); + DeleteObject(brush); + + return true; +} + + +static bool text(int x, int y, const char *text, size_t length, + const plot_font_style_t *style) +{ + PLOT_LOG("words %s at %d,%d", text, x, y); + + /* ensure the plot HDC is set */ + if (plot_hdc == NULL) { + LOG("HDC not set on call to plotters"); + return false; + } + + HRGN clipregion = CreateRectRgnIndirect(&plot_clip); + if (clipregion == NULL) { + return false; + } + + HFONT fontbak, font = get_font(style); + if (font == NULL) { + DeleteObject(clipregion); + return false; + } + int wlen; + SIZE s; + LPWSTR wstring; + fontbak = (HFONT) SelectObject(plot_hdc, font); + GetTextExtentPoint(plot_hdc, text, length, &s); + +/* + RECT r; + r.left = x; + r.top = y - (3 * s.cy) / 4; + r.right = x + s.cx; + r.bottom = y + s.cy / 4; +*/ + SelectClipRgn(plot_hdc, clipregion); + + SetTextAlign(plot_hdc, TA_BASELINE | TA_LEFT); + if ((style->background & 0xFF000000) != 0x01000000) + /* 100% alpha */ + SetBkColor(plot_hdc, (DWORD) (style->background & 0x00FFFFFF)); + SetBkMode(plot_hdc, TRANSPARENT); + SetTextColor(plot_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(plot_hdc, x, y, wstring, wlen); + + SelectClipRgn(plot_hdc, NULL); + free(wstring); + font = SelectObject(plot_hdc, fontbak); + DeleteObject(clipregion); + DeleteObject(font); + + return true; +} + +static bool disc(int x, int y, int radius, const plot_style_t *style) +{ + PLOT_LOG("disc at %d,%d radius %d", x, y, radius); + + /* ensure the plot HDC is set */ + if (plot_hdc == NULL) { + LOG("HDC not set on call to plotters"); + return false; + } + + HRGN clipregion = CreateRectRgnIndirect(&plot_clip); + if (clipregion == NULL) { + 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); + return false; + } + HGDIOBJ penbak = SelectObject(plot_hdc, (HGDIOBJ) pen); + if (penbak == NULL) { + DeleteObject(clipregion); + DeleteObject(pen); + return false; + } + HBRUSH brush = CreateSolidBrush(col); + if (brush == NULL) { + DeleteObject(clipregion); + SelectObject(plot_hdc, penbak); + DeleteObject(pen); + return false; + } + HGDIOBJ brushbak = SelectObject(plot_hdc, (HGDIOBJ) brush); + if (brushbak == NULL) { + DeleteObject(clipregion); + SelectObject(plot_hdc, penbak); + DeleteObject(pen); + DeleteObject(brush); + return false; + } +/* + RECT r; + r.left = x - radius; + r.top = y - radius; + r.right = x + radius; + r.bottom = y + radius; +*/ + SelectClipRgn(plot_hdc, clipregion); + + if (style->fill_type == PLOT_OP_TYPE_NONE) + Arc(plot_hdc, x - radius, y - radius, x + radius, y + radius, + x - radius, y - radius, + x - radius, y - radius); + else + Ellipse(plot_hdc, x - radius, y - radius, x + radius, y + radius); + + SelectClipRgn(plot_hdc, NULL); + pen = SelectObject(plot_hdc, penbak); + brush = SelectObject(plot_hdc, brushbak); + DeleteObject(clipregion); + DeleteObject(pen); + DeleteObject(brush); + + return true; +} + +static bool arc(int x, int y, int radius, int angle1, int angle2, + const plot_style_t *style) +{ + PLOT_LOG("arc centre %d,%d radius %d from %d to %d", x, y, radius, + angle1, angle2); + + /* ensure the plot HDC is set */ + if (plot_hdc == NULL) { + LOG("HDC not set on call to plotters"); + return false; + } + + HRGN clipregion = CreateRectRgnIndirect(&plot_clip); + if (clipregion == NULL) { + return false; + } + + COLORREF col = (DWORD)(style->stroke_colour & 0x00FFFFFF); + HPEN pen = CreatePen(PS_GEOMETRIC | PS_SOLID, 1, col); + if (pen == NULL) { + DeleteObject(clipregion); + return false; + } + HGDIOBJ penbak = SelectObject(plot_hdc, (HGDIOBJ) pen); + if (penbak == NULL) { + DeleteObject(clipregion); + DeleteObject(pen); + return false; + } + + 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; + } + +/* + RECT r; + r.left = x - radius; + r.top = y - radius; + r.right = x + radius; + r.bottom = y + radius; +*/ + SelectClipRgn(plot_hdc, clipregion); + + Arc(plot_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(plot_hdc, NULL); + pen = SelectObject(plot_hdc, penbak); + DeleteObject(clipregion); + DeleteObject(pen); + + return true; +} + +static bool +plot_block(COLORREF col, int x, int y, int width, int height) +{ + HRGN clipregion; + HGDIOBJ original = NULL; + + /* Bail early if we can */ + if ((x >= plot_clip.right) || + ((x + width) < plot_clip.left) || + (y >= plot_clip.bottom) || + ((y + height) < plot_clip.top)) { + /* Image completely outside clip region */ + return true; + } + + /* ensure the plot HDC is set */ + if (plot_hdc == NULL) { + LOG("HDC not set on call to plotters"); + return false; + } + + clipregion = CreateRectRgnIndirect(&plot_clip); + if (clipregion == NULL) { + return false; + } + + SelectClipRgn(plot_hdc, clipregion); + + /* Saving the original pen object */ + original = SelectObject(plot_hdc,GetStockObject(DC_PEN)); + + SelectObject(plot_hdc, GetStockObject(DC_PEN)); + SelectObject(plot_hdc, GetStockObject(DC_BRUSH)); + SetDCPenColor(plot_hdc, col); + SetDCBrushColor(plot_hdc, col); + Rectangle(plot_hdc, x, y, width, height); + + SelectObject(plot_hdc,original); /* Restoring the original pen object */ + + DeleteObject(clipregion); + + return true; + +} + +/* blunt force truma way of achiving alpha blended plotting */ +static bool +plot_alpha_bitmap(HDC hdc, + struct bitmap *bitmap, + int x, int y, + int width, int height) +{ +#ifdef WINDOWS_GDI_ALPHA_WORKED + BLENDFUNCTION blnd = { AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA }; + HDC bmihdc; + bool bltres; + bmihdc = CreateCompatibleDC(hdc); + SelectObject(bmihdc, bitmap->windib); + bltres = AlphaBlend(hdc, + x, y, + width, height, + bmihdc, + 0, 0, + bitmap->width, bitmap->height, + blnd); + DeleteDC(bmihdc); + return bltres; +#else + HDC Memhdc; + BITMAPINFOHEADER bmih; + int v, vv, vi, h, hh, width4, transparency; + unsigned char alpha; + bool isscaled = false; /* set if the scaled bitmap requires freeing */ + BITMAP MemBM; + BITMAPINFO *bmi; + HBITMAP MemBMh; + + PLOT_LOG("%p bitmap %d,%d width %d height %d", bitmap, x, y, width, height); + PLOT_LOG("clipped %ld,%ld to %ld,%ld",plot_clip.left, plot_clip.top, plot_clip.right, plot_clip.bottom); + + Memhdc = CreateCompatibleDC(hdc); + if (Memhdc == NULL) { + return false; + } + + if ((bitmap->width != width) || + (bitmap->height != height)) { + PLOT_LOG("scaling from %d,%d to %d,%d", + bitmap->width, bitmap->height, width, height); + bitmap = bitmap_scale(bitmap, width, height); + if (bitmap == NULL) + return false; + isscaled = true; + } + + bmi = (BITMAPINFO *) malloc(sizeof(BITMAPINFOHEADER) + + (bitmap->width * bitmap->height * 4)); + if (bmi == NULL) { + DeleteDC(Memhdc); + return false; + } + + MemBMh = CreateCompatibleBitmap(hdc, bitmap->width, bitmap->height); + if (MemBMh == NULL){ + free(bmi); + DeleteDC(Memhdc); + 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; + } + } + } + SetDIBitsToDevice(hdc, x, y, bitmap->width, bitmap->height, + 0, 0, 0, bitmap->height, + (const void *) bmi->bmiColors, + bmi, DIB_RGB_COLORS); + + if (isscaled && bitmap && bitmap->pixdata) { + free(bitmap->pixdata); + free(bitmap); + } + + free(bmi); + DeleteObject(MemBMh); + DeleteDC(Memhdc); + return true; +#endif +} + + +static bool +plot_bitmap(struct bitmap *bitmap, int x, int y, int width, int height) +{ + int bltres; + HRGN clipregion; + + /* Bail early if we can */ + if ((x >= plot_clip.right) || + ((x + width) < plot_clip.left) || + (y >= plot_clip.bottom) || + ((y + height) < plot_clip.top)) { + /* Image completely outside clip region */ + return true; + } + + /* ensure the plot HDC is set */ + if (plot_hdc == NULL) { + LOG("HDC not set on call to plotters"); + return false; + } + + clipregion = CreateRectRgnIndirect(&plot_clip); + if (clipregion == NULL) { + return false; + } + + SelectClipRgn(plot_hdc, clipregion); + + if (bitmap->opaque) { + /* opaque bitmap */ + if ((bitmap->width == width) && + (bitmap->height == height)) { + /* unscaled */ + bltres = SetDIBitsToDevice(plot_hdc, + x, y, + width, height, + 0, 0, + 0, + height, + bitmap->pixdata, + (BITMAPINFO *)bitmap->pbmi, + DIB_RGB_COLORS); + } else { + /* scaled */ + SetStretchBltMode(plot_hdc, COLORONCOLOR); + bltres = StretchDIBits(plot_hdc, + x, y, + width, height, + 0, 0, + bitmap->width, bitmap->height, + bitmap->pixdata, + (BITMAPINFO *)bitmap->pbmi, + DIB_RGB_COLORS, + SRCCOPY); + + + } + } else { + /* Bitmap with alpha.*/ + bltres = plot_alpha_bitmap(plot_hdc, bitmap, x, y, width, height); + } + + PLOT_LOG("bltres = %d", bltres); + + DeleteObject(clipregion); + + return true; + +} + +static bool +windows_plot_bitmap(int x, int y, + int width, int height, + struct bitmap *bitmap, colour bg, + bitmap_flags_t flags) +{ + int xf,yf; + bool repeat_x = (flags & BITMAPF_REPEAT_X); + bool repeat_y = (flags & BITMAPF_REPEAT_Y); + + /* Bail early if we can */ + + PLOT_LOG("Plotting %p at %d,%d by %d,%d",bitmap, x,y,width,height); + + if (bitmap == NULL) { + LOG("Passed null bitmap!"); + return true; + } + + /* check if nothing to plot */ + if (width == 0 || height == 0) + return true; + + /* x and y define coordinate of top left of of the initial explicitly + * placed tile. The width and height are the image scaling and the + * bounding box defines the extent of the repeat (which may go in all + * four directions from the initial tile). + */ + + if (!(repeat_x || repeat_y)) { + /* Not repeating at all, so just plot it */ + if ((bitmap->width == 1) && (bitmap->height == 1)) { + if ((*(bitmap->pixdata + 3) & 0xff) == 0) { + return true; + } + return plot_block((*(COLORREF *)bitmap->pixdata) & 0xffffff, x, y, x + width, y + height); + + } else { + return plot_bitmap(bitmap, x, y, width, height); + } + } + + /* Optimise tiled plots of 1x1 bitmaps by replacing with a flat fill + * of the area. Can only be done when image is fully opaque. */ + if ((bitmap->width == 1) && (bitmap->height == 1)) { + if ((*(COLORREF *)bitmap->pixdata & 0xff000000) != 0) { + return plot_block((*(COLORREF *)bitmap->pixdata) & 0xffffff, + plot_clip.left, + plot_clip.top, + plot_clip.right, + plot_clip.bottom); + } + } + + /* Optimise tiled plots of bitmaps scaled to 1x1 by replacing with + * a flat fill of the area. Can only be done when image is fully + * opaque. */ + if ((width == 1) && (height == 1)) { + if (bitmap->opaque) { + /** TODO: Currently using top left pixel. Maybe centre + * pixel or average value would be better. */ + return plot_block((*(COLORREF *)bitmap->pixdata) & 0xffffff, + plot_clip.left, + plot_clip.top, + plot_clip.right, + plot_clip.bottom); + } + } + + PLOT_LOG("Tiled plotting %d,%d by %d,%d",x,y,width,height); + PLOT_LOG("clipped %ld,%ld to %ld,%ld",plot_clip.left, plot_clip.top, plot_clip.right, plot_clip.bottom); + + /* get left most tile position */ + if (repeat_x) + for (; x > plot_clip.left; x -= width); + + /* get top most tile position */ + if (repeat_y) + for (; y > plot_clip.top; y -= height); + + PLOT_LOG("repeat from %d,%d to %ld,%ld", x, y, plot_clip.right, plot_clip.bottom); + + /* tile down and across to extents */ + for (xf = x; xf < plot_clip.right; xf += width) { + for (yf = y; yf < plot_clip.bottom; yf += height) { + + plot_bitmap(bitmap, xf, yf, width, height); + if (!repeat_y) + break; + } + if (!repeat_x) + break; + } + return true; +} + + +static bool flush(void) +{ + PLOT_LOG("flush unimplemented"); + return true; +} + +static bool path(const float *p, unsigned int n, colour fill, float width, + colour c, const float transform[6]) +{ + PLOT_LOG("path unimplemented"); + return true; +} + +const struct plotter_table win_plotters = { + .rectangle = rectangle, + .line = line, + .polygon = polygon, + .clip = clip, + .text = text, + .disc = disc, + .arc = arc, + .bitmap = windows_plot_bitmap, + .flush = flush, + .path = path, + .option_knockout = true, +}; diff --git a/frontends/windows/plot.h b/frontends/windows/plot.h new file mode 100644 index 000000000..d69650d2a --- /dev/null +++ b/frontends/windows/plot.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 . + */ + +#include + +extern const struct plotter_table win_plotters; + +extern HDC plot_hdc; + diff --git a/frontends/windows/pointers.c b/frontends/windows/pointers.c new file mode 100644 index 000000000..b5b74545d --- /dev/null +++ b/frontends/windows/pointers.c @@ -0,0 +1,128 @@ +/* + * Copyright 2015 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 "utils/errors.h" +#include "utils/nsurl.h" +#include "utils/log.h" +#include "utils/utils.h" +#include "utils/corestrings.h" +#include "utils/url.h" +#include "utils/file.h" +#include "desktop/browser.h" +#include "desktop/gui_clipboard.h" + +#include "windows/schedule.h" +#include "windows/window.h" +#include "windows/filetype.h" +#include "windows/pointers.h" + +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; +}; + +/** pre loaded pointer cursors */ +static struct nsws_pointers nsws_pointer; + +/* exported interface documented in windows/pointers.h */ +void nsws_window_init_pointers(HINSTANCE hinstance) +{ + 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); +} + +/* exported interface documented in windows/pointers.h */ +HCURSOR nsws_get_pointer(gui_pointer_shape shape) +{ + switch (shape) { + case GUI_POINTER_POINT: /* link */ + case GUI_POINTER_MENU: + return nsws_pointer.hand; + + case GUI_POINTER_CARET: /* input */ + return nsws_pointer.ibeam; + + case GUI_POINTER_CROSS: + return nsws_pointer.cross; + + case GUI_POINTER_MOVE: + return nsws_pointer.sizeall; + + case GUI_POINTER_RIGHT: + case GUI_POINTER_LEFT: + return nsws_pointer.sizewe; + + case GUI_POINTER_UP: + case GUI_POINTER_DOWN: + return nsws_pointer.sizens; + + case GUI_POINTER_RU: + case GUI_POINTER_LD: + return nsws_pointer.sizenesw; + + case GUI_POINTER_RD: + case GUI_POINTER_LU: + return nsws_pointer.sizenwse; + + case GUI_POINTER_WAIT: + return nsws_pointer.wait; + + case GUI_POINTER_PROGRESS: + return nsws_pointer.appstarting; + + case GUI_POINTER_NO_DROP: + case GUI_POINTER_NOT_ALLOWED: + return nsws_pointer.no; + + case GUI_POINTER_HELP: + return nsws_pointer.help; + + default: + break; + } + + return nsws_pointer.arrow; +} diff --git a/frontends/windows/pointers.h b/frontends/windows/pointers.h new file mode 100644 index 000000000..cf91de993 --- /dev/null +++ b/frontends/windows/pointers.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 . + */ + +/** + * \file + * Windows mouse cursor interface. + */ + +#ifndef _NETSURF_WINDOWS_POINTERS_H_ +#define _NETSURF_WINDOWS_POINTERS_H_ + + +/** + * initialise the list of mouse cursors + */ +void nsws_window_init_pointers(HINSTANCE hinstance); + +/** + * get a win32 cursor handle for a pointer shape + */ +HCURSOR nsws_get_pointer(gui_pointer_shape shape); + + +#endif diff --git a/frontends/windows/prefs.c b/frontends/windows/prefs.c new file mode 100644 index 000000000..adc0101a7 --- /dev/null +++ b/frontends/windows/prefs.c @@ -0,0 +1,680 @@ +/* + * 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 "utils/config.h" + +#include +#include + +#include "utils/nsoption.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" +#include "windows/windbg.h" + +#define NSWS_PREFS_WINDOW_WIDTH 600 +#define NSWS_PREFS_WINDOW_HEIGHT 400 + +static CHOOSEFONT *nsws_prefs_font_prepare(int fontfamily, HWND parent) +{ + CHOOSEFONT *cf = malloc(sizeof(CHOOSEFONT)); + if (cf == NULL) { + win32_warning(messages_get("NoMemory"),0); + return NULL; + } + LOGFONT *lf = malloc(sizeof(LOGFONT)); + if (lf == NULL) { + win32_warning(messages_get("NoMemory"),0); + free(cf); + return NULL; + } + switch(fontfamily) { + case FF_ROMAN: + snprintf(lf->lfFaceName, LF_FACESIZE, "%s", + nsoption_charp(font_serif)); + break; + case FF_MODERN: + snprintf(lf->lfFaceName, LF_FACESIZE, "%s", + nsoption_charp(font_mono)); + break; + case FF_SCRIPT: + snprintf(lf->lfFaceName, LF_FACESIZE, "%s", + nsoption_charp(font_cursive)); + break; + case FF_DECORATIVE: + snprintf(lf->lfFaceName, LF_FACESIZE, "%s", + nsoption_charp(font_fantasy)); + break; + case FF_SWISS: + default: + snprintf(lf->lfFaceName, LF_FACESIZE, "%s", + nsoption_charp(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; +} + +static void change_spinner(HWND sub, double change, double minval, double maxval) +{ + char *temp, number[6]; + int len; + double value = 0; + + len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0); + temp = malloc(len + 1); + + if (temp == NULL) + return; + + SendMessage(sub, WM_GETTEXT, (WPARAM)(len + 1), (LPARAM) temp); + + value = strtod(temp, NULL) - change; + + free(temp); + value = max(value, minval); + value = min(value, maxval); + + if ((change == 1.0) || (change == -1.0)) + snprintf(number, 6, "%.0f", value); + else + snprintf(number, 6, "%.1f", value); + + SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number); +} + + +static BOOL CALLBACK options_appearance_dialog_handler(HWND hwnd, + UINT msg, WPARAM wparam, LPARAM lParam) +{ + int len; + char *temp, number[6]; + HWND sub; + + LOG_WIN_MSG(hwnd, msg, wparam, lParam); + + switch (msg) { + case WM_INITDIALOG: + sub = GetDlgItem(hwnd, IDC_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) (nsoption_int(font_default) - 1), 0); + + if ((nsoption_charp(font_sans) != NULL) && + (nsoption_charp(font_sans)[0] != '\0')) { + sub = GetDlgItem(hwnd, IDC_PREFS_SANS); + SendMessage(sub, WM_SETTEXT, 0, + (LPARAM)nsoption_charp(font_sans)); + } + if ((nsoption_charp(font_serif) != NULL) && + (nsoption_charp(font_serif)[0] != '\0')) { + sub = GetDlgItem(hwnd, IDC_PREFS_SERIF); + SendMessage(sub, WM_SETTEXT, 0, + (LPARAM)nsoption_charp(font_serif)); + } + if ((nsoption_charp(font_mono) != NULL) && + (nsoption_charp(font_mono)[0] != '\0')) { + sub = GetDlgItem(hwnd, IDC_PREFS_MONO); + SendMessage(sub, WM_SETTEXT, 0, + (LPARAM)nsoption_charp(font_mono)); + } + if ((nsoption_charp(font_cursive) != NULL) && + (nsoption_charp(font_cursive)[0] != '\0')) { + sub = GetDlgItem(hwnd, IDC_PREFS_CURSIVE); + SendMessage(sub, WM_SETTEXT, 0, + (LPARAM)nsoption_charp(font_cursive)); + } + if ((nsoption_charp(font_fantasy) != NULL) && + (nsoption_charp(font_fantasy)[0] != '\0')) { + sub = GetDlgItem(hwnd, IDC_PREFS_FANTASY); + SendMessage(sub, WM_SETTEXT, 0, + (LPARAM)nsoption_charp(font_fantasy)); + } + if (nsoption_int(font_min_size) != 0) { + sub = GetDlgItem(hwnd, IDC_PREFS_FONT_MINSIZE); + snprintf(number, 6, "%.1f", nsoption_int(font_min_size) / 10.0); + SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number); + } + if (nsoption_int(font_size) != 0) { + sub = GetDlgItem(hwnd, IDC_PREFS_FONT_SIZE); + snprintf(number, 6, "%.1f", nsoption_int(font_size) / 10.0); + SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number); + } + if (nsoption_int(max_fetchers) != 0) { + sub = GetDlgItem(hwnd, IDC_PREFS_FETCHERS); + snprintf(number, 6, "%d", nsoption_int(max_fetchers)); + SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number); + } + if (nsoption_int(max_fetchers_per_host) != 0) { + sub = GetDlgItem(hwnd, IDC_PREFS_FETCH_HOST); + snprintf(number, 6, "%d", + nsoption_int(max_fetchers_per_host)); + SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number); + } + if (nsoption_int(max_cached_fetch_handles) != 0) { + sub = GetDlgItem(hwnd, IDC_PREFS_FETCH_HANDLES); + snprintf(number, 6, "%d", + nsoption_int(max_cached_fetch_handles)); + SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number); + } + + + /* animation */ + sub = GetDlgItem(hwnd, IDC_PREFS_NOANIMATION); + SendMessage(sub, BM_SETCHECK, (WPARAM)((nsoption_bool(animate_images)) + ? BST_UNCHECKED : BST_CHECKED), 0); + + if (nsoption_int(minimum_gif_delay) != 0) { + sub = GetDlgItem(hwnd, IDC_PREFS_ANIMATIONDELAY); + snprintf(number, 6, "%.1f", nsoption_int(minimum_gif_delay) / + 100.0); + SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number); + } + break; + + case WM_NOTIFY: + switch (((NMHDR FAR *)lParam)->code) { + case PSN_APPLY: + sub = GetDlgItem(hwnd, IDC_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); + nsoption_int(font_size) = (int) + (10 * strtod(temp, NULL)); + free(temp); + } + + sub = GetDlgItem(hwnd, IDC_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); + nsoption_set_int(font_min_size, + (int)(10 * strtod(temp, NULL))); + free(temp); + } + + /* animation */ + nsoption_set_bool(animate_images, + (IsDlgButtonChecked(hwnd, IDC_PREFS_NOANIMATION) == BST_CHECKED) ? true : false); + + + sub = GetDlgItem(hwnd, IDC_PREFS_ANIMATIONDELAY); + len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0); + temp = malloc(len + 1); + if (temp != NULL) { + SendMessage(sub, WM_GETTEXT, (WPARAM) + (len + 1), (LPARAM) temp); + nsoption_set_int(minimum_gif_delay, + (int)(100 * strtod(temp, NULL))); + free(temp); + } + + break; + + case UDN_DELTAPOS: { + NMUPDOWN *ud = (NMUPDOWN *)lParam; + switch(((NMHDR *)lParam)->idFrom) { + case IDC_PREFS_FONT_SIZE_SPIN: + change_spinner(GetDlgItem(hwnd, IDC_PREFS_FONT_SIZE), 0.1 * ud->iDelta, 1.0, 50.0); + return TRUE; + + case IDC_PREFS_FONT_MINSIZE_SPIN: + change_spinner(GetDlgItem(hwnd, IDC_PREFS_FONT_MINSIZE), 0.1 * ud->iDelta, 1.0, 50.0); + return TRUE; + + case IDC_PREFS_ANIMATIONDELAY_SPIN: + change_spinner(GetDlgItem(hwnd, IDC_PREFS_ANIMATIONDELAY), 0.1 * ud->iDelta, 0.1, 100.0); + return TRUE; + + } + } + break; + } + + + case WM_COMMAND: + LOG("WM_COMMAND Identifier 0x%x",LOWORD(wparam)); + + switch(LOWORD(wparam)) { + case IDC_PREFS_PROXYTYPE: + sub = GetDlgItem(hwnd, IDC_PREFS_PROXYTYPE); + nsoption_set_int(http_proxy_auth, + SendMessage(sub, CB_GETCURSEL, 0, 0) - 1); + nsoption_set_bool(http_proxy, + (nsoption_int(http_proxy_auth) != -1)); + nsoption_set_int(http_proxy_auth, + nsoption_int(http_proxy_auth) + + (nsoption_bool(http_proxy)) ? 0 : 1); + break; + + case IDC_PREFS_SANS: { + CHOOSEFONT *cf = nsws_prefs_font_prepare(FF_SWISS, hwnd); + if (cf == NULL) { + break; + } + + if (ChooseFont(cf) == TRUE) { + nsoption_set_charp(font_sans, + strdup(cf->lpLogFont->lfFaceName)); + } + + free(cf->lpLogFont); + free(cf); + if ((nsoption_charp(font_sans) != NULL) && + (nsoption_charp(font_sans)[0] != '\0')) { + sub = GetDlgItem(hwnd, IDC_PREFS_SANS); + SendMessage(sub, WM_SETTEXT, 0, + (LPARAM)nsoption_charp(font_sans)); + } + break; + } + + case IDC_PREFS_SERIF: { + CHOOSEFONT *cf = nsws_prefs_font_prepare(FF_ROMAN, hwnd); + if (cf == NULL) { + break; + } + + if (ChooseFont(cf) == TRUE) { + nsoption_set_charp(font_serif, + strdup(cf->lpLogFont->lfFaceName)); + } + + free(cf->lpLogFont); + free(cf); + if ((nsoption_charp(font_serif) != NULL) && + (nsoption_charp(font_serif)[0] != '\0')) { + sub = GetDlgItem(hwnd, IDC_PREFS_SERIF); + SendMessage(sub, WM_SETTEXT, 0, + (LPARAM)nsoption_charp(font_serif)); + } + break; + } + + case IDC_PREFS_MONO: { + CHOOSEFONT *cf = nsws_prefs_font_prepare(FF_MODERN, hwnd); + if (cf == NULL) { + break; + } + + if (ChooseFont(cf) == TRUE) { + nsoption_set_charp(font_mono, + strdup(cf->lpLogFont->lfFaceName)); + } + + free(cf->lpLogFont); + free(cf); + + if ((nsoption_charp(font_mono) != NULL) && + (nsoption_charp(font_mono)[0] != '\0')) { + sub = GetDlgItem(hwnd, IDC_PREFS_MONO); + SendMessage(sub, WM_SETTEXT, 0, + (LPARAM)nsoption_charp(font_mono)); + } + break; + } + + case IDC_PREFS_CURSIVE: { + CHOOSEFONT *cf = nsws_prefs_font_prepare(FF_SCRIPT, hwnd); + if (cf == NULL) { + break; + } + + if (ChooseFont(cf) == TRUE) { + nsoption_set_charp(font_cursive, + strdup(cf->lpLogFont->lfFaceName)); + } + free(cf->lpLogFont); + free(cf); + if ((nsoption_charp(font_cursive) != NULL) && + (nsoption_charp(font_cursive)[0] != '\0')) { + sub = GetDlgItem(hwnd, IDC_PREFS_CURSIVE); + SendMessage(sub, WM_SETTEXT, 0, + (LPARAM)nsoption_charp(font_cursive)); + } + break; + } + + case IDC_PREFS_FANTASY: { + CHOOSEFONT *cf = nsws_prefs_font_prepare(FF_DECORATIVE, hwnd); + if (cf == NULL) { + break; + } + + if (ChooseFont(cf) == TRUE) { + nsoption_set_charp(font_fantasy, + strdup(cf->lpLogFont->lfFaceName)); + } + free(cf->lpLogFont); + free(cf); + if ((nsoption_charp(font_fantasy) != NULL) && + (nsoption_charp(font_fantasy)[0] != '\0')) { + sub = GetDlgItem(hwnd, IDC_PREFS_FANTASY); + SendMessage(sub, WM_SETTEXT, 0, + (LPARAM)nsoption_charp(font_fantasy)); + } + break; + } + + case IDC_PREFS_FONTDEF: + sub = GetDlgItem(hwnd, IDC_PREFS_FONTDEF); + nsoption_set_int(font_default, + SendMessage(sub, CB_GETCURSEL, 0, 0) + 1); + break; + + } + break; + + } + return FALSE; +} + +static BOOL CALLBACK options_connections_dialog_handler(HWND hwnd, + UINT msg, WPARAM wparam, LPARAM lParam) +{ + int len; + char *temp, number[6]; + HWND sub; + + LOG_WIN_MSG(hwnd, msg, wparam, lParam); + + switch (msg) { + case WM_INITDIALOG: + sub = GetDlgItem(hwnd, IDC_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 (nsoption_bool(http_proxy)) { + SendMessage(sub, CB_SETCURSEL, (WPARAM) + (nsoption_int(http_proxy_auth) + 1), 0); + } else { + SendMessage(sub, CB_SETCURSEL, 0, 0); + } + + sub = GetDlgItem(hwnd, IDC_PREFS_PROXYHOST); + if ((nsoption_charp(http_proxy_host) != NULL) && + (nsoption_charp(http_proxy_host)[0] != '\0')) + SendMessage(sub, WM_SETTEXT, 0, + (LPARAM)nsoption_charp(http_proxy_host)); + + sub = GetDlgItem(hwnd, IDC_PREFS_PROXYPORT); + if (nsoption_int(http_proxy_port) != 0) { + snprintf(number, 6, "%d", nsoption_int(http_proxy_port)); + SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number); + } + + sub = GetDlgItem(hwnd, IDC_PREFS_PROXYNAME); + if ((nsoption_charp(http_proxy_auth_user) != NULL) && + (nsoption_charp(http_proxy_auth_user)[0] != '\0')) + SendMessage(sub, WM_SETTEXT, 0, + (LPARAM)nsoption_charp(http_proxy_auth_user)); + + sub = GetDlgItem(hwnd, IDC_PREFS_PROXYPASS); + if ((nsoption_charp(http_proxy_auth_pass) != NULL) && + (nsoption_charp(http_proxy_auth_pass)[0] != '\0')) + SendMessage(sub, WM_SETTEXT, 0, + (LPARAM)nsoption_charp(http_proxy_auth_pass)); + + sub = GetDlgItem(hwnd, IDC_PREFS_FETCHERS); + snprintf(number, 6, "%d", nsoption_int(max_fetchers)); + SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number); + + sub = GetDlgItem(hwnd, IDC_PREFS_FETCH_HOST); + snprintf(number, 6, "%d", nsoption_int(max_fetchers_per_host)); + SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number); + + sub = GetDlgItem(hwnd, IDC_PREFS_FETCH_HANDLES); + snprintf(number, 6, "%d", nsoption_int(max_cached_fetch_handles)); + SendMessage(sub, WM_SETTEXT, 0, (LPARAM)number); + + break; + + case WM_NOTIFY: + switch (((NMHDR FAR *)lParam)->code) { + case PSN_APPLY: + sub = GetDlgItem(hwnd, IDC_PREFS_PROXYHOST); + len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0); + temp = malloc(len + 1); + if (temp != NULL) { + SendMessage(sub, WM_GETTEXT, (WPARAM)(len + 1), + (LPARAM)temp); + nsoption_set_charp(http_proxy_host, strdup(temp)); + free(temp); + } + + sub = GetDlgItem(hwnd, IDC_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); + nsoption_set_int(http_proxy_port, atoi(temp)); + free(temp); + } + + sub = GetDlgItem(hwnd, IDC_PREFS_PROXYNAME); + len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0); + temp = malloc(len + 1); + if (temp != NULL) { + SendMessage(sub, WM_GETTEXT, (WPARAM)(len + 1), + (LPARAM)temp); + nsoption_set_charp(http_proxy_auth_user, strdup(temp)); + free(temp); + } + + sub = GetDlgItem(hwnd, IDC_PREFS_PROXYPASS); + len = SendMessage(sub, WM_GETTEXTLENGTH, 0, 0); + temp = malloc(len + 1); + if (temp != NULL) { + SendMessage(sub, WM_GETTEXT, (WPARAM)(len + 1), + (LPARAM)temp); + nsoption_set_charp(http_proxy_auth_pass, strdup(temp)); + free(temp); + } + + /* fetchers */ + sub = GetDlgItem(hwnd, IDC_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); + nsoption_set_int(max_fetchers, atoi(temp)); + free(temp); + } + + sub = GetDlgItem(hwnd, IDC_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); + nsoption_set_int(max_fetchers_per_host, atoi(temp)); + free(temp); + } + + sub = GetDlgItem(hwnd, IDC_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); + nsoption_set_int(max_cached_fetch_handles, atoi(temp)); + free(temp); + } + break; + + case UDN_DELTAPOS: { + NMUPDOWN *ud = (NMUPDOWN *)lParam; + switch(((NMHDR *)lParam)->idFrom) { + case IDC_PREFS_FETCHERS_SPIN: + change_spinner(GetDlgItem(hwnd, IDC_PREFS_FETCHERS), 1.0 * ud->iDelta, 1.0, 100.0); + return TRUE; + + case IDC_PREFS_FETCH_HOST_SPIN: + change_spinner(GetDlgItem(hwnd, IDC_PREFS_FETCH_HOST), 1.0 * ud->iDelta, 1.0, 100.0); + return TRUE; + + case IDC_PREFS_FETCH_HANDLES_SPIN: + change_spinner(GetDlgItem(hwnd, IDC_PREFS_FETCH_HANDLES), 1.0 * ud->iDelta, 1.0, 100.0); + return TRUE; + + } + } + break; + } + } + return FALSE; +} + +static BOOL CALLBACK options_general_dialog_handler(HWND hwnd, + UINT msg, WPARAM wparam, LPARAM lParam) +{ + HWND sub; + + LOG_WIN_MSG(hwnd, msg, wparam, lParam); + + switch (msg) { + case WM_INITDIALOG: + /* homepage url */ + sub = GetDlgItem(hwnd, IDC_PREFS_HOMEPAGE); + SendMessage(sub, WM_SETTEXT, 0, (LPARAM)nsoption_charp(homepage_url)); + + /* Display images */ + sub = GetDlgItem(hwnd, IDC_PREFS_IMAGES); + SendMessage(sub, BM_SETCHECK, + (WPARAM) ((nsoption_bool(suppress_images)) ? + BST_CHECKED : BST_UNCHECKED), 0); + + /* advert blocking */ + sub = GetDlgItem(hwnd, IDC_PREFS_ADVERTS); + SendMessage(sub, BM_SETCHECK, + (WPARAM) ((nsoption_bool(block_advertisements)) ? + BST_CHECKED : BST_UNCHECKED), 0); + + /* Referrer sending */ + sub = GetDlgItem(hwnd, IDC_PREFS_REFERER); + SendMessage(sub, BM_SETCHECK, + (WPARAM)((nsoption_bool(send_referer)) ? + BST_CHECKED : BST_UNCHECKED), 0); + break; + + case WM_NOTIFY: + switch (((NMHDR FAR *)lParam)->code) { + case PSN_APPLY: + /* homepage */ + sub = GetDlgItem(hwnd, IDC_PREFS_HOMEPAGE); + if (sub != NULL) { + int text_length; + char *text; + text_length = SendMessage(sub, + WM_GETTEXTLENGTH, 0, 0); + text = malloc(text_length + 1); + if (text != NULL) { + SendMessage(sub, WM_GETTEXT, + (WPARAM)text_length + 1, + (LPARAM)text); + nsoption_set_charp(homepage_url, text); + } + } + + nsoption_set_bool(suppress_images, + (IsDlgButtonChecked(hwnd, IDC_PREFS_IMAGES) == BST_CHECKED) ? true : false); + + nsoption_set_bool(block_advertisements, (IsDlgButtonChecked(hwnd, + IDC_PREFS_ADVERTS) == BST_CHECKED) ? true : false); + + nsoption_set_bool(send_referer, (IsDlgButtonChecked(hwnd, + IDC_PREFS_REFERER) == BST_CHECKED) ? true : false); + + break; + + } + } + return FALSE; +} + +void nsws_prefs_dialog_init(HINSTANCE hinst, HWND parent) +{ + int ret; + PROPSHEETPAGE psp[3]; + PROPSHEETHEADER psh; + + psp[0].dwSize = sizeof(PROPSHEETPAGE); + psp[0].dwFlags = 0;/*PSP_USEICONID*/ + psp[0].hInstance = hinst; + psp[0].pszTemplate = MAKEINTRESOURCE(IDD_DLG_OPTIONS_GENERAL); + psp[0].pfnDlgProc = options_general_dialog_handler; + psp[0].lParam = 0; + psp[0].pfnCallback = NULL; + + psp[1].dwSize = sizeof(PROPSHEETPAGE); + psp[1].dwFlags = 0;/*PSP_USEICONID*/ + psp[1].hInstance = hinst; + psp[1].pszTemplate = MAKEINTRESOURCE(IDD_DLG_OPTIONS_CONNECTIONS); + psp[1].pfnDlgProc = options_connections_dialog_handler; + psp[1].lParam = 0; + psp[1].pfnCallback = NULL; + + psp[2].dwSize = sizeof(PROPSHEETPAGE); + psp[2].dwFlags = 0;/*PSP_USEICONID*/ + psp[2].hInstance = hinst; + psp[2].pszTemplate = MAKEINTRESOURCE(IDD_DLG_OPTIONS_APPERANCE); + psp[2].pfnDlgProc = options_appearance_dialog_handler; + psp[2].lParam = 0; + psp[2].pfnCallback = NULL; + + + psh.dwSize = sizeof(PROPSHEETHEADER); + psh.dwFlags = PSH_NOAPPLYNOW | PSH_USEICONID | PSH_PROPSHEETPAGE; + psh.hwndParent = parent; + psh.hInstance = hinst; + psh.pszIcon = MAKEINTRESOURCE(IDR_NETSURF_ICON); + psh.pszCaption = (LPSTR) "NetSurf Options"; + psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE); + psh.nStartPage = 0; + psh.ppsp = (LPCPROPSHEETPAGE) &psp; + psh.pfnCallback = NULL; + + ret = PropertySheet(&psh); + if (ret == -1) { + win_perror("PropertySheet"); + } else if (ret > 0) { + /* user saved changes */ + nsoption_write(options_file_location, NULL, NULL); + } +} diff --git a/frontends/windows/prefs.h b/frontends/windows/prefs.h new file mode 100644 index 000000000..dec004b60 --- /dev/null +++ b/frontends/windows/prefs.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_PREFS_H_ +#define _NETSURF_WINDOWS_PREFS_H_ + +void nsws_prefs_dialog_init(HINSTANCE hinst, HWND parent); + +#endif diff --git a/frontends/windows/res/NetSurf.ico b/frontends/windows/res/NetSurf.ico new file mode 100644 index 000000000..e0c3d01e6 Binary files /dev/null and b/frontends/windows/res/NetSurf.ico differ diff --git a/frontends/windows/res/adblock.css b/frontends/windows/res/adblock.css new file mode 120000 index 000000000..ff2485622 --- /dev/null +++ b/frontends/windows/res/adblock.css @@ -0,0 +1 @@ +../../../!NetSurf/Resources/AdBlock,f79 \ No newline at end of file diff --git a/frontends/windows/res/banner.bmp b/frontends/windows/res/banner.bmp new file mode 100644 index 000000000..49525f83d Binary files /dev/null and b/frontends/windows/res/banner.bmp differ diff --git a/frontends/windows/res/ca-bundle.crt b/frontends/windows/res/ca-bundle.crt new file mode 120000 index 000000000..0b0e416ad --- /dev/null +++ b/frontends/windows/res/ca-bundle.crt @@ -0,0 +1 @@ +../../../!NetSurf/Resources/ca-bundle \ No newline at end of file diff --git a/frontends/windows/res/credits.html b/frontends/windows/res/credits.html new file mode 120000 index 000000000..1ba17392b --- /dev/null +++ b/frontends/windows/res/credits.html @@ -0,0 +1 @@ +../../../!NetSurf/Resources/en/credits.html,faf \ No newline at end of file diff --git a/frontends/windows/res/default.css b/frontends/windows/res/default.css new file mode 120000 index 000000000..a8579eb7c --- /dev/null +++ b/frontends/windows/res/default.css @@ -0,0 +1 @@ +../../../!NetSurf/Resources/CSS,f79 \ No newline at end of file diff --git a/frontends/windows/res/home.bmp b/frontends/windows/res/home.bmp new file mode 100644 index 000000000..1f595ff4c Binary files /dev/null and b/frontends/windows/res/home.bmp differ diff --git a/frontends/windows/res/icons/back.png b/frontends/windows/res/icons/back.png new file mode 100644 index 000000000..f219fd807 Binary files /dev/null and b/frontends/windows/res/icons/back.png differ diff --git a/frontends/windows/res/icons/back_g.png b/frontends/windows/res/icons/back_g.png new file mode 100644 index 000000000..0796bbbbf Binary files /dev/null and b/frontends/windows/res/icons/back_g.png differ diff --git a/frontends/windows/res/icons/back_h.png b/frontends/windows/res/icons/back_h.png new file mode 100644 index 000000000..35e31386a Binary files /dev/null and b/frontends/windows/res/icons/back_h.png differ diff --git a/frontends/windows/res/icons/forward.png b/frontends/windows/res/icons/forward.png new file mode 100644 index 000000000..f20c0cdf5 Binary files /dev/null and b/frontends/windows/res/icons/forward.png differ diff --git a/frontends/windows/res/icons/forward_g.png b/frontends/windows/res/icons/forward_g.png new file mode 100644 index 000000000..d847543f3 Binary files /dev/null and b/frontends/windows/res/icons/forward_g.png differ diff --git a/frontends/windows/res/icons/forward_h.png b/frontends/windows/res/icons/forward_h.png new file mode 100644 index 000000000..90c0fe2c7 Binary files /dev/null and b/frontends/windows/res/icons/forward_h.png differ diff --git a/frontends/windows/res/icons/home.png b/frontends/windows/res/icons/home.png new file mode 100644 index 000000000..604796025 Binary files /dev/null and b/frontends/windows/res/icons/home.png differ diff --git a/frontends/windows/res/icons/home_g.png b/frontends/windows/res/icons/home_g.png new file mode 100644 index 000000000..a644b0b03 Binary files /dev/null and b/frontends/windows/res/icons/home_g.png differ diff --git a/frontends/windows/res/icons/home_h.png b/frontends/windows/res/icons/home_h.png new file mode 100644 index 000000000..2d6be5f34 Binary files /dev/null and b/frontends/windows/res/icons/home_h.png differ diff --git a/frontends/windows/res/icons/reload.png b/frontends/windows/res/icons/reload.png new file mode 100644 index 000000000..a81f650b0 Binary files /dev/null and b/frontends/windows/res/icons/reload.png differ diff --git a/frontends/windows/res/icons/reload_g.png b/frontends/windows/res/icons/reload_g.png new file mode 100644 index 000000000..5251f206c Binary files /dev/null and b/frontends/windows/res/icons/reload_g.png differ diff --git a/frontends/windows/res/icons/reload_h.png b/frontends/windows/res/icons/reload_h.png new file mode 100644 index 000000000..76e554e49 Binary files /dev/null and b/frontends/windows/res/icons/reload_h.png differ diff --git a/frontends/windows/res/icons/stop.png b/frontends/windows/res/icons/stop.png new file mode 100644 index 000000000..df64c5747 Binary files /dev/null and b/frontends/windows/res/icons/stop.png differ diff --git a/frontends/windows/res/icons/stop_g.png b/frontends/windows/res/icons/stop_g.png new file mode 100644 index 000000000..a2efa9e3d Binary files /dev/null and b/frontends/windows/res/icons/stop_g.png differ diff --git a/frontends/windows/res/icons/stop_h.png b/frontends/windows/res/icons/stop_h.png new file mode 100644 index 000000000..3c3377cdf Binary files /dev/null and b/frontends/windows/res/icons/stop_h.png differ diff --git a/frontends/windows/res/installer.nsi b/frontends/windows/res/installer.nsi new file mode 100644 index 000000000..0c733db2e --- /dev/null +++ b/frontends/windows/res/installer.nsi @@ -0,0 +1,141 @@ +# This installs NetSurf execuatables and resources, creates a start menu shortcut, builds an uninstaller, and +# adds uninstall information to the registry for Add/Remove Programs + +# show up in a few places. +# All the other settings can be tweaked by editing the !defines at the top of this script +!define APPNAME "NetSurf" +!define COMPANYNAME "NetSurf" +!define DESCRIPTION "Web Browser" +# These three must be integers +!define VERSIONMAJOR 3 +!define VERSIONMINOR 6 +!define VERSIONBUILD 1 +# These will be displayed by the "Click here for support information" link in "Add/Remove Programs" +# It is possible to use "mailto:" links in here to open the email client +!define HELPURL "http://www.netsurf-browser.org/" # "Support Information" link +!define UPDATEURL "http://www.netsurf-browser.org/" # "Product Updates" link +!define ABOUTURL "http://www.netsurf-browser.org/" # "Publisher" link +# This is the size (in kB) of all the files copied into "Program Files" +!define INSTALLSIZE 9000 + +RequestExecutionLevel admin ;Require admin rights on NT6+ (When UAC is turned on) + +InstallDir "$PROGRAMFILES\${COMPANYNAME}\${APPNAME}" + +# rtf or txt file - remember if it is txt, it must be in the DOS text format (\r\n) +LicenseData "COPYING" +# This will be in the installer/uninstaller's title bar +Name "${COMPANYNAME} - ${APPNAME}" +Icon "frontends\windows\res\NetSurf.ico" +outFile "netsurf-installer.exe" +BrandingText "${COMPANYNAME}" + +!include LogicLib.nsh + +# Just three pages - license agreement, install location, and installation +page license +page directory +Page instfiles + +!macro VerifyUserIsAdmin +UserInfo::GetAccountType +pop $0 +${If} $0 != "admin" ;Require admin rights on NT4+ + messageBox mb_iconstop "Administrator rights required!" + setErrorLevel 740 ;ERROR_ELEVATION_REQUIRED + quit +${EndIf} +!macroend + +function .onInit + setShellVarContext all + !insertmacro VerifyUserIsAdmin +functionEnd + +section "install" + # Files for the install directory - to build the installer, these should be in the same directory as the install script (this file) + setOutPath $INSTDIR + # Files added here should be removed by the uninstaller (see section "uninstall") + file "NetSurf.exe" + file /oname=NetSurf.ico "frontends\windows\res\NetSurf.ico" + file /oname=default.css "frontends\windows\res\default.css" + file /oname=internal.css "frontends\windows\res\internal.css" + file /oname=adblock.css "frontends\windows\res\adblock.css" + file /oname=welcome.html "frontends\windows\res\welcome.html" + file /oname=credits.html "frontends\windows\res\credits.html" + file /oname=licence.html "frontends\windows\res\licence.html" + file /oname=netsurf.png "frontends\windows\res\netsurf.png" + file /oname=messages "build-Linux-windows\messages" + file /oname=ca-bundle.crt "frontends\windows\res\ca-bundle.crt" + # Add any other files for the install directory (license files, app data, etc) here + + # Uninstaller - See function un.onInit and section "uninstall" for configuration + writeUninstaller "$INSTDIR\uninstall.exe" + + # Start Menu + createDirectory "$SMPROGRAMS\${COMPANYNAME}" + createShortCut "$SMPROGRAMS\${COMPANYNAME}\${APPNAME}.lnk" "$INSTDIR\NetSurf.exe" "" "$INSTDIR\NetSurf.ico" + + # Registry information for add/remove programs + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "DisplayName" "${COMPANYNAME} - ${APPNAME} - ${DESCRIPTION}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "InstallLocation" "$\"$INSTDIR$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "DisplayIcon" "$\"$INSTDIR\NetSurf.ico$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "Publisher" "$\"${COMPANYNAME}$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "HelpLink" "$\"${HELPURL}$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "URLUpdateInfo" "$\"${UPDATEURL}$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "URLInfoAbout" "$\"${ABOUTURL}$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "DisplayVersion" "$\"${VERSIONMAJOR}.${VERSIONMINOR}.${VERSIONBUILD}$\"" + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "VersionMajor" ${VERSIONMAJOR} + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "VersionMinor" ${VERSIONMINOR} + # There is no option for modifying or repairing the install + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "NoModify" 1 + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "NoRepair" 1 + # Set the INSTALLSIZE constant (!defined at the top of this script) so Add/Remove Programs can accurately report the size + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "EstimatedSize" ${INSTALLSIZE} +sectionEnd + +# Uninstaller + +function un.onInit + SetShellVarContext all + + #Verify the uninstaller - last chance to back out + MessageBox MB_OKCANCEL "Permanantly remove ${APPNAME}?" IDOK next + Abort + next: + !insertmacro VerifyUserIsAdmin +functionEnd + +section "uninstall" + + # Remove Start Menu launcher + delete "$SMPROGRAMS\${COMPANYNAME}\${APPNAME}.lnk" + # Try to remove the Start Menu folder - this will only happen if it is empty + rmDir "$SMPROGRAMS\${COMPANYNAME}" + + # Remove files + delete $INSTDIR\NetSurf.exe + delete $INSTDIR\NetSurf.ico + delete $INSTDIR\libcares-2.dll + delete $INSTDIR\libgnurx-0.dll + delete $INSTDIR\default.css + delete $INSTDIR\internal.css + delete $INSTDIR\adblock.css + delete $INSTDIR\welcome.html + delete $INSTDIR\credits.html + delete $INSTDIR\licence.html + delete $INSTDIR\netsurf.png + delete $INSTDIR\messages + delete $INSTDIR\ca-bundle.crt + + # Always delete uninstaller as the last action + delete $INSTDIR\uninstall.exe + + # Try to remove the install directory - this will only happen if it is empty + rmDir $INSTDIR + + # Remove uninstaller information from the registry + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" +sectionEnd diff --git a/frontends/windows/res/internal.css b/frontends/windows/res/internal.css new file mode 120000 index 000000000..17f9f1504 --- /dev/null +++ b/frontends/windows/res/internal.css @@ -0,0 +1 @@ +../../../!NetSurf/Resources/internal.css,f79 \ No newline at end of file diff --git a/frontends/windows/res/licence.html b/frontends/windows/res/licence.html new file mode 120000 index 000000000..147dd6db2 --- /dev/null +++ b/frontends/windows/res/licence.html @@ -0,0 +1 @@ +../../../!NetSurf/Resources/en/licence.html,faf \ No newline at end of file diff --git a/frontends/windows/res/netsurf.gif b/frontends/windows/res/netsurf.gif new file mode 100644 index 000000000..f4ee3aa15 Binary files /dev/null and b/frontends/windows/res/netsurf.gif differ diff --git a/frontends/windows/res/netsurf.png b/frontends/windows/res/netsurf.png new file mode 120000 index 000000000..905512c25 --- /dev/null +++ b/frontends/windows/res/netsurf.png @@ -0,0 +1 @@ +../../../!NetSurf/Resources/netsurf.png,b60 \ No newline at end of file diff --git a/frontends/windows/res/quirks.css b/frontends/windows/res/quirks.css new file mode 120000 index 000000000..88aabe48c --- /dev/null +++ b/frontends/windows/res/quirks.css @@ -0,0 +1 @@ +../../../!NetSurf/Resources/Quirks,f79 \ No newline at end of file diff --git a/frontends/windows/res/resource.rc b/frontends/windows/res/resource.rc new file mode 100644 index 000000000..b83205f6a --- /dev/null +++ b/frontends/windows/res/resource.rc @@ -0,0 +1,265 @@ +#include +#include +#include + +#include "../resourceid.h" + + +IDR_NETSURF_ICON ICON DISCARDABLE "NetSurf.ico" +IDR_TOOLBAR_BITMAP BITMAP DISCARDABLE "toolbar.bmp" +IDR_TOOLBAR_BITMAP_GREY BITMAP DISCARDABLE "toolbarg.bmp" +IDR_TOOLBAR_BITMAP_HOT BITMAP DISCARDABLE "toolbarh.bmp" +IDR_NETSURF_BANNER BITMAP DISCARDABLE "banner.bmp" +IDR_HOME_BITMAP BITMAP DISCARDABLE "home.bmp" + +IDR_THROBBER_FRAME0_BITMAP BITMAP DISCARDABLE "throbber/throbber0.bmp" +IDR_THROBBER_FRAME1_BITMAP BITMAP DISCARDABLE "throbber/throbber1.bmp" +IDR_THROBBER_FRAME2_BITMAP BITMAP DISCARDABLE "throbber/throbber2.bmp" +IDR_THROBBER_FRAME3_BITMAP BITMAP DISCARDABLE "throbber/throbber3.bmp" +IDR_THROBBER_FRAME4_BITMAP BITMAP DISCARDABLE "throbber/throbber4.bmp" +IDR_THROBBER_FRAME5_BITMAP BITMAP DISCARDABLE "throbber/throbber5.bmp" +IDR_THROBBER_FRAME6_BITMAP BITMAP DISCARDABLE "throbber/throbber6.bmp" +IDR_THROBBER_FRAME7_BITMAP BITMAP DISCARDABLE "throbber/throbber7.bmp" + +IDR_MENU_MAIN MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New Window",IDM_FILE_OPEN_WINDOW + MENUITEM "Open &Location",IDM_FILE_OPEN_LOCATION + MENUITEM "&Close",IDM_FILE_CLOSE_WINDOW + MENUITEM SEPARATOR + MENUITEM "&Save Page",IDM_FILE_SAVE_PAGE,GRAYED,HELP + POPUP "Save Page &As" + BEGIN + MENUITEM "Text",IDM_FILE_SAVEAS_TEXT,GRAYED + MENUITEM "PDF",IDM_FILE_SAVEAS_PDF,GRAYED + MENUITEM "Postscript",IDM_FILE_SAVEAS_POSTSCRIPT,GRAYED + END + MENUITEM SEPARATOR + MENUITEM "Print Pre&view",IDM_FILE_PRINT_PREVIEW + MENUITEM "&Print",IDM_FILE_PRINT + MENUITEM SEPARATOR + MENUITEM "E&xit",IDM_FILE_QUIT + END + POPUP "&Edit" + BEGIN + MENUITEM "Cu&t",IDM_EDIT_CUT + MENUITEM "&Copy",IDM_EDIT_COPY + MENUITEM "&Paste",IDM_EDIT_PASTE + MENUITEM "&Delete",IDM_EDIT_DELETE + MENUITEM SEPARATOR + MENUITEM "Select &All",IDM_EDIT_SELECT_ALL + MENUITEM SEPARATOR + MENUITEM "&Find",IDM_EDIT_SEARCH + END + POPUP "&View" + BEGIN + MENUITEM "Stop",IDM_NAV_STOP + MENUITEM "Reload",IDM_NAV_RELOAD + MENUITEM SEPARATOR + POPUP "&Zoom" + BEGIN + MENUITEM "Zoom &In",IDM_VIEW_ZOOMPLUS + MENUITEM "Zoom &Out",IDM_VIEW_ZOOMMINUS + MENUITEM "&Reset",IDM_VIEW_ZOOMNORMAL + END + MENUITEM SEPARATOR + MENUITEM "Page S&ource",IDM_VIEW_SOURCE + MENUITEM "&Full Screen",IDM_VIEW_FULLSCREEN + END + POPUP "&History" + BEGIN + MENUITEM "Back",IDM_NAV_BACK + MENUITEM "Forward",IDM_NAV_FORWARD + MENUITEM "Home",IDM_NAV_HOME + MENUITEM SEPARATOR + MENUITEM "Local History",IDM_NAV_LOCALHISTORY + MENUITEM "Global History",IDM_NAV_GLOBALHISTORY,GRAYED + END + POPUP "&Tools" + BEGIN + MENUITEM "&Downloads",IDM_VIEW_DOWNLOADS + MENUITEM "Save size and location",IDM_VIEW_SAVE_WIN_METRICS + POPUP "Debugging" + BEGIN + MENUITEM "Debug rendering",IDM_VIEW_TOGGLE_DEBUG_RENDERING + MENUITEM "Save Box Tree",IDM_VIEW_DEBUGGING_SAVE_BOXTREE,GRAYED + MENUITEM "Save DOM Tree",IDM_VIEW_DEBUGGING_SAVE_DOMTREE,GRAYED + END + MENUITEM SEPARATOR + MENUITEM "Options...",IDM_EDIT_PREFERENCES + END + POPUP "&Help" + BEGIN + MENUITEM "&Contents",IDM_HELP_CONTENTS + MENUITEM "G&uide",IDM_HELP_GUIDE + MENUITEM "&Info",IDM_HELP_INFO + MENUITEM SEPARATOR + MENUITEM "&About NetSurf",IDM_HELP_ABOUT + END +END + +IDR_MENU_CONTEXT MENU +BEGIN + POPUP "Context" + BEGIN + MENUITEM "&Back",IDM_NAV_BACK + MENUITEM "F&orward",IDM_NAV_FORWARD + MENUITEM "&Home",IDM_NAV_HOME + MENUITEM "&Stop",IDM_NAV_STOP + MENUITEM "&Reload",IDM_NAV_RELOAD + MENUITEM SEPARATOR + MENUITEM "C&ut",IDM_EDIT_CUT,GRAYED + MENUITEM "&Copy",IDM_EDIT_COPY,GRAYED + MENUITEM "&Paste",IDM_EDIT_PASTE,GRAYED + MENUITEM "&Delete",IDM_EDIT_DELETE,GRAYED + END +END + +IDD_DLG_ABOUT DIALOGEX 10,10,206,133 +CAPTION "About NetSurf" +FONT 8,"MS Sans Serif",0,0,0 +STYLE WS_VISIBLE|WS_CAPTION|WS_SYSMENU +EXSTYLE WS_EX_DLGMODALFRAME +BEGIN + CONTROL IDR_NETSURF_BANNER,IDC_IMG1,"Static",SS_BITMAP|0x40L /*SS_REALSIZECONTROL*/,0,0,205,53 + CONTROL "NetSurf",IDC_ABOUT_VERSION,"Static",SS_LEFT,10,60,185,16 + CONTROL "NetSurf is a small fast browser",IDC_ABOUT_TEXT,"Static",SS_LEFT,10,83,185,8 + CONTROL "Copyright 2003-2011 The NetSurf Developers",IDC_ABOUT_COPYRIGHT,"Static",SS_LEFT,10,96,185,8 + CONTROL "&OK",IDOK,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,143,111,54,15 + CONTROL "&Credits",IDC_BTN_CREDITS,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,10,111,54,15 + CONTROL "&Licence",IDC_BTN_LICENCE,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,70,111,54,15 +END + +IDD_DLG_DOWNLOAD DIALOGEX 0,0,201,84 +CAPTION "Download" +FONT 8,"MS Sans Serif",0,0,0 +STYLE WS_POPUP|WS_VISIBLE|WS_CAPTION|WS_SYSMENU|DS_MODALFRAME|DS_SETFONT +EXSTYLE WS_EX_DLGMODALFRAME +BEGIN + CONTROL "downloading [file] [size] from [domain] to [destination]",IDC_DOWNLOAD_LABEL,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_CENTER,6,6,189,35 + CONTROL "progress",IDC_DOWNLOAD_PROGRESS,PROGRESS_CLASS,WS_VISIBLE,6,50,189,10 + CONTROL "&OK",IDOK,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,141,66,54,15 + CONTROL "&Cancel",IDCANCEL,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,81,66,54,15 +END + + +IDD_DLG_OPTIONS_GENERAL DIALOGEX 0,0,220,200 +CAPTION "General" +FONT 8,"MS Shell Dlg" +STYLE DS_CONTROL|DS_SHELLFONT +BEGIN + /* home page entry */ + CONTROL "Home Page",IDC_STATIC,"Static",SS_LEFT,7,7,40,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,47,11,166,1 + CONTROL IDR_HOME_BITMAP,IDC_STATIC,"Static",SS_BITMAP,15,19,24,24 + CONTROL "",IDC_PREFS_HOMEPAGE,"Edit",WS_TABSTOP|ES_OEMCONVERT|ES_AUTOHSCROLL,43,19,170,14,WS_EX_CLIENTEDGE + + + /* Content control */ + CONTROL "Content Control",IDC_STATIC,"Static",SS_LEFT,7,40,60,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,67,44,146,1 + + CONTROL "Hide Images",IDC_PREFS_IMAGES,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,43,52,67,10 + CONTROL "Hide Advertisements",IDC_PREFS_ADVERTS,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,43,66,81,10 + CONTROL "Send referer",IDC_PREFS_REFERER,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,43,80,55,10 + +END + +IDD_DLG_OPTIONS_CONNECTIONS DIALOGEX 0,0,220,200 +CAPTION "Connections" +FONT 8,"MS Shell Dlg" +STYLE DS_CONTROL|DS_SHELLFONT +BEGIN + /* proxy divider */ + CONTROL "Proxy",IDC_STATIC,"Static",SS_LEFT,7,7,30,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,37,11,176,1 + + /* proxy controls */ + CONTROL "Type:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,22,40,8 + CONTROL "",IDC_PREFS_PROXYTYPE,"ComboBox",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|CBS_DROPDOWNLIST,80,19,60,60 + + CONTROL "Server:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,39,28,8 + CONTROL "",IDC_PREFS_PROXYHOST,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|ES_OEMCONVERT|ES_AUTOHSCROLL,80,36,80,14,WS_EX_CLIENTEDGE + + CONTROL "Port:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,164,39,16,8 + CONTROL "",IDC_PREFS_PROXYPORT,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|ES_OEMCONVERT|ES_AUTOHSCROLL,182,36,24,14,WS_EX_CLIENTEDGE + + CONTROL "Username:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,60,35,8 + CONTROL "",IDC_PREFS_PROXYNAME,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|ES_OEMCONVERT|ES_AUTOHSCROLL,80,57,45,14,WS_EX_CLIENTEDGE + + CONTROL "Password:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,132,60,34,8 + CONTROL "",IDC_PREFS_PROXYPASS,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|ES_OEMCONVERT|ES_AUTOHSCROLL|ES_PASSWORD,168,57,45,14,WS_EX_CLIENTEDGE + + + /* fetcher divider */ + CONTROL "Fetchers",IDC_STATIC,"Static",SS_LEFT,7,78,40,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,42,82,171,1 + + /* max fetchers */ + CONTROL "Max Fetchers:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP,43,96,64,8 + CONTROL "",IDC_PREFS_FETCHERS,"Edit",ES_NUMBER|ES_RIGHT|WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|WS_BORDER,111,93,30,14 + CONTROL "Max Fetchers",IDC_PREFS_FETCHERS_SPIN,UPDOWN_CLASS,UDS_AUTOBUDDY|UDS_ALIGNRIGHT|WS_VISIBLE,341,122,11,15 + + /* fetchers per host */ + CONTROL "Fetches per host:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP,43,118,64,8 + CONTROL "",IDC_PREFS_FETCH_HOST,"Edit",ES_NUMBER|ES_RIGHT|WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|WS_BORDER,111,114,30,14 + CONTROL "Fetches per host",IDC_PREFS_FETCH_HOST_SPIN,UPDOWN_CLASS,UDS_AUTOBUDDY|UDS_ALIGNRIGHT|WS_VISIBLE,341,140,11,15 + + /* cached fetchers */ + CONTROL "Cached Fetches:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP,43,138,64,8 + CONTROL "",IDC_PREFS_FETCH_HANDLES,"Edit",ES_NUMBER|ES_RIGHT|WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|WS_BORDER,111,135,30,14 + CONTROL "Cached Fetches",IDC_PREFS_FETCH_HANDLES_SPIN,UPDOWN_CLASS,UDS_AUTOBUDDY|UDS_ALIGNRIGHT|WS_VISIBLE,341,158,11,15 + +END + +IDD_DLG_OPTIONS_APPERANCE DIALOGEX 10,10,220,200 +CAPTION "Apperance" +FONT 8,"MS Shell Dlg" +STYLE DS_CONTROL|DS_SHELLFONT +BEGIN + /* proxy separator */ + CONTROL "Fonts",IDC_STATIC,"Static",SS_LEFT,7,7,20,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,27,11,186,1 + + /* font controls */ + CONTROL "Sans-serif:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,22,44,8 + CONTROL "Sans-serif",IDC_PREFS_SANS,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,89,19,50,14 + + CONTROL "Serif:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,40,24,8 + CONTROL "Serif",IDC_PREFS_SERIF,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,89,37,50,14 + + CONTROL "Monospace:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,58,40,8 + CONTROL "Monospace",IDC_PREFS_MONO,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,89,55,50,14 + + CONTROL "Cursive:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,76,32,8 + CONTROL "Cursive",IDC_PREFS_CURSIVE,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,89,73,50,14 + + CONTROL "Fantasy:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,94,32,8 + CONTROL "Fantasy",IDC_PREFS_FANTASY,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,89,91,50,14 + + + CONTROL "Default:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,112,38,8 + CONTROL "",IDC_PREFS_FONTDEF,"ComboBox",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|CBS_DROPDOWNLIST,89,109,50,60 + + CONTROL "Size:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,147,112,16,8 + CONTROL "",IDC_PREFS_FONT_SIZE,"Edit",ES_NUMBER|WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,165,109,35,14,WS_EX_CLIENTEDGE + CONTROL "Font Size",IDC_PREFS_FONT_SIZE_SPIN,UPDOWN_CLASS,UDS_AUTOBUDDY|UDS_ALIGNRIGHT|WS_VISIBLE,75,137,11,15 + + CONTROL "Minimum Size:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,43,130,52,8 + CONTROL "",IDC_PREFS_FONT_MINSIZE,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,97,127,35,14,WS_EX_CLIENTEDGE + CONTROL "Minimum Font Size",IDC_PREFS_FONT_MINSIZE_SPIN,UPDOWN_CLASS,UDS_AUTOBUDDY|UDS_ALIGNRIGHT|WS_VISIBLE,76,159,11,15 + + /* animation separator */ + CONTROL "Animation",IDC_STATIC,"Static",SS_LEFT,7,148,36,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,43,152,170,1 + + CONTROL "Disable",IDC_PREFS_NOANIMATION,"Button",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|BS_AUTOCHECKBOX,43,163,39,10 + CONTROL "Minimum delay:",IDC_STATIC,"Static",WS_CHILDWINDOW|WS_VISIBLE|WS_GROUP|SS_LEFT,55,180,56,8 + CONTROL "",IDC_PREFS_ANIMATIONDELAY,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP,113,177,35,14,WS_EX_CLIENTEDGE + CONTROL "Min delay",IDC_PREFS_ANIMATIONDELAY_SPIN,UPDOWN_CLASS,UDS_AUTOBUDDY|UDS_ALIGNRIGHT|WS_VISIBLE,43,210,11,15 + + + +END diff --git a/frontends/windows/res/throbber.avi b/frontends/windows/res/throbber.avi new file mode 100644 index 000000000..cced3a556 Binary files /dev/null and b/frontends/windows/res/throbber.avi differ diff --git a/frontends/windows/res/throbber/throbber0.bmp b/frontends/windows/res/throbber/throbber0.bmp new file mode 100644 index 000000000..2cef4da70 Binary files /dev/null and b/frontends/windows/res/throbber/throbber0.bmp differ diff --git a/frontends/windows/res/throbber/throbber0.png b/frontends/windows/res/throbber/throbber0.png new file mode 100755 index 000000000..ad13c5408 Binary files /dev/null and b/frontends/windows/res/throbber/throbber0.png differ diff --git a/frontends/windows/res/throbber/throbber1.bmp b/frontends/windows/res/throbber/throbber1.bmp new file mode 100644 index 000000000..7c7feb6b2 Binary files /dev/null and b/frontends/windows/res/throbber/throbber1.bmp differ diff --git a/frontends/windows/res/throbber/throbber1.png b/frontends/windows/res/throbber/throbber1.png new file mode 100755 index 000000000..9e4e575a3 Binary files /dev/null and b/frontends/windows/res/throbber/throbber1.png differ diff --git a/frontends/windows/res/throbber/throbber2.bmp b/frontends/windows/res/throbber/throbber2.bmp new file mode 100644 index 000000000..7d1d1147a Binary files /dev/null and b/frontends/windows/res/throbber/throbber2.bmp differ diff --git a/frontends/windows/res/throbber/throbber2.png b/frontends/windows/res/throbber/throbber2.png new file mode 100755 index 000000000..f571f7093 Binary files /dev/null and b/frontends/windows/res/throbber/throbber2.png differ diff --git a/frontends/windows/res/throbber/throbber3.bmp b/frontends/windows/res/throbber/throbber3.bmp new file mode 100644 index 000000000..1f98b12b0 Binary files /dev/null and b/frontends/windows/res/throbber/throbber3.bmp differ diff --git a/frontends/windows/res/throbber/throbber3.png b/frontends/windows/res/throbber/throbber3.png new file mode 100755 index 000000000..0bc8b66b5 Binary files /dev/null and b/frontends/windows/res/throbber/throbber3.png differ diff --git a/frontends/windows/res/throbber/throbber4.bmp b/frontends/windows/res/throbber/throbber4.bmp new file mode 100644 index 000000000..a5ddc00e3 Binary files /dev/null and b/frontends/windows/res/throbber/throbber4.bmp differ diff --git a/frontends/windows/res/throbber/throbber4.png b/frontends/windows/res/throbber/throbber4.png new file mode 100755 index 000000000..37c9ce842 Binary files /dev/null and b/frontends/windows/res/throbber/throbber4.png differ diff --git a/frontends/windows/res/throbber/throbber5.bmp b/frontends/windows/res/throbber/throbber5.bmp new file mode 100644 index 000000000..261f8cd13 Binary files /dev/null and b/frontends/windows/res/throbber/throbber5.bmp differ diff --git a/frontends/windows/res/throbber/throbber5.png b/frontends/windows/res/throbber/throbber5.png new file mode 100755 index 000000000..54f83d224 Binary files /dev/null and b/frontends/windows/res/throbber/throbber5.png differ diff --git a/frontends/windows/res/throbber/throbber6.bmp b/frontends/windows/res/throbber/throbber6.bmp new file mode 100644 index 000000000..01d3f480d Binary files /dev/null and b/frontends/windows/res/throbber/throbber6.bmp differ diff --git a/frontends/windows/res/throbber/throbber6.png b/frontends/windows/res/throbber/throbber6.png new file mode 100755 index 000000000..e36e1f872 Binary files /dev/null and b/frontends/windows/res/throbber/throbber6.png differ diff --git a/frontends/windows/res/throbber/throbber7.bmp b/frontends/windows/res/throbber/throbber7.bmp new file mode 100644 index 000000000..b5421cf0e Binary files /dev/null and b/frontends/windows/res/throbber/throbber7.bmp differ diff --git a/frontends/windows/res/throbber/throbber7.png b/frontends/windows/res/throbber/throbber7.png new file mode 100755 index 000000000..c6f2628b5 Binary files /dev/null and b/frontends/windows/res/throbber/throbber7.png differ diff --git a/frontends/windows/res/throbber/throbber8.png b/frontends/windows/res/throbber/throbber8.png new file mode 100755 index 000000000..d29d94414 Binary files /dev/null and b/frontends/windows/res/throbber/throbber8.png differ diff --git a/frontends/windows/res/toolbar.bmp b/frontends/windows/res/toolbar.bmp new file mode 100644 index 000000000..4087878a6 Binary files /dev/null and b/frontends/windows/res/toolbar.bmp differ diff --git a/frontends/windows/res/toolbarg.bmp b/frontends/windows/res/toolbarg.bmp new file mode 100644 index 000000000..9a59e8d43 Binary files /dev/null and b/frontends/windows/res/toolbarg.bmp differ diff --git a/frontends/windows/res/toolbarh.bmp b/frontends/windows/res/toolbarh.bmp new file mode 100644 index 000000000..81e666f03 Binary files /dev/null and b/frontends/windows/res/toolbarh.bmp differ diff --git a/frontends/windows/res/welcome.html b/frontends/windows/res/welcome.html new file mode 120000 index 000000000..28362130a --- /dev/null +++ b/frontends/windows/res/welcome.html @@ -0,0 +1 @@ +../../../!NetSurf/Resources/en/welcome.html,faf \ No newline at end of file diff --git a/frontends/windows/resourceid.h b/frontends/windows/resourceid.h new file mode 100644 index 000000000..bdec80a30 --- /dev/null +++ b/frontends/windows/resourceid.h @@ -0,0 +1,138 @@ +/* + * 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 IDR_NETSURF_ICON 100 +#define IDR_TOOLBAR_BITMAP 102 +#define IDR_TOOLBAR_BITMAP_GREY 103 +#define IDR_TOOLBAR_BITMAP_HOT 104 +#define IDR_NETSURF_BANNER 105 +#define IDR_HOME_BITMAP 114 + +#define IDR_THROBBER_FRAME0_BITMAP 106 +#define IDR_THROBBER_FRAME1_BITMAP 107 +#define IDR_THROBBER_FRAME2_BITMAP 108 +#define IDR_THROBBER_FRAME3_BITMAP 109 +#define IDR_THROBBER_FRAME4_BITMAP 110 +#define IDR_THROBBER_FRAME5_BITMAP 111 +#define IDR_THROBBER_FRAME6_BITMAP 112 +#define IDR_THROBBER_FRAME7_BITMAP 113 + +#define IDD_DLG_ABOUT 1000 +#define IDC_IMG1 1001 +#define IDC_ABOUT_VERSION 1002 +#define IDC_ABOUT_TEXT 1003 +#define IDC_ABOUT_COPYRIGHT 1004 +#define IDC_BTN_CREDITS 1005 +#define IDC_BTN_LICENCE 1006 + +#define IDD_DLG_DOWNLOAD 1100 +#define IDC_DOWNLOAD_LABEL 1101 +#define IDC_DOWNLOAD_PROGRESS 1102 + +#define IDD_DLG_MAIN 1300 +#define IDC_MAIN_TOOLBAR 1301 +#define IDC_MAIN_URLBAR 1302 +#define IDC_MAIN_THROBBER 1303 +#define IDC_MAIN_DRAWINGAREA 1304 +#define IDC_MAIN_STATUSBAR 1305 +#define IDC_MAIN_LAUNCH_URL 1306 + +#define IDD_DLG_OPTIONS_GENERAL 1400 +#define IDC_PREFS_HOMEPAGE 1401 +#define IDC_PREFS_IMAGES 1402 +#define IDC_PREFS_ADVERTS 1403 +#define IDC_PREFS_REFERER 1404 + +#define IDD_DLG_OPTIONS_CONNECTIONS 1500 +#define IDC_PREFS_FETCHERS 1501 +#define IDC_PREFS_FETCHERS_SPIN 1502 +#define IDC_PREFS_FETCH_HOST 1503 +#define IDC_PREFS_FETCH_HOST_SPIN 1504 +#define IDC_PREFS_FETCH_HANDLES 1505 +#define IDC_PREFS_FETCH_HANDLES_SPIN 1506 + +#define IDD_DLG_OPTIONS_APPERANCE 1200 +#define IDC_PREFS_PROXYTYPE 1206 +#define IDC_PREFS_PROXYHOST 1207 +#define IDC_PREFS_PROXYPORT 1208 +#define IDC_PREFS_PROXYNAME 1209 +#define IDC_PREFS_PROXYPASS 1210 +#define IDC_PREFS_FONT_SIZE 1211 +#define IDC_PREFS_FONT_MINSIZE 1212 +#define IDC_PREFS_FONT_MINSIZE_SPIN 1213 +#define IDC_PREFS_SANS 1214 +#define IDC_PREFS_SERIF 1215 +#define IDC_PREFS_FONT_SIZE_SPIN 1216 +#define IDC_PREFS_MONO 1217 +#define IDC_PREFS_CURSIVE 1218 +#define IDC_PREFS_FANTASY 1219 +#define IDC_PREFS_FONTDEF 1220 +#define IDC_PREFS_NOANIMATION 1227 +#define IDC_PREFS_ANIMATIONDELAY 1228 +#define IDC_PREFS_ANIMATIONDELAY_SPIN 1229 + +#define IDR_MENU_MAIN 10000 +#define IDM_FILE_OPEN_WINDOW 10001 +#define IDM_FILE_OPEN_LOCATION 10002 +#define IDM_FILE_CLOSE_WINDOW 10003 +#define IDM_FILE_SAVE_PAGE 10004 +#define IDM_FILE_SAVEAS_TEXT 10005 +#define IDM_FILE_SAVEAS_PDF 10006 +#define IDM_FILE_SAVEAS_POSTSCRIPT 10007 +#define IDM_FILE_PRINT_PREVIEW 10008 +#define IDM_FILE_PRINT 10009 +#define IDM_FILE_QUIT 10010 +#define IDM_EDIT_CUT 10011 +#define IDM_EDIT_COPY 10012 +#define IDM_EDIT_PASTE 10013 +#define IDM_EDIT_DELETE 10014 +#define IDM_EDIT_SELECT_ALL 10015 +#define IDM_EDIT_SEARCH 10016 +#define IDM_NAV_STOP 10017 +#define IDM_NAV_RELOAD 10018 +#define IDM_VIEW_ZOOMPLUS 10019 +#define IDM_VIEW_ZOOMMINUS 10020 +#define IDM_VIEW_ZOOMNORMAL 10021 +#define IDM_VIEW_SOURCE 10022 +#define IDM_VIEW_FULLSCREEN 10023 +#define IDM_NAV_BACK 10024 +#define IDM_NAV_FORWARD 10025 +#define IDM_NAV_HOME 10026 +#define IDM_NAV_LOCALHISTORY 10027 +#define IDM_NAV_GLOBALHISTORY 10028 +#define IDM_VIEW_DOWNLOADS 10029 +#define IDM_VIEW_SAVE_WIN_METRICS 10030 +#define IDM_VIEW_TOGGLE_DEBUG_RENDERING 10031 +#define IDM_VIEW_DEBUGGING_SAVE_BOXTREE 10032 +#define IDM_VIEW_DEBUGGING_SAVE_DOMTREE 10033 +#define IDM_EDIT_PREFERENCES 10034 +#define IDM_HELP_CONTENTS 10035 +#define IDM_HELP_GUIDE 10036 +#define IDM_HELP_INFO 10037 +#define IDM_HELP_ABOUT 10038 + +#define IDR_MENU_CONTEXT 11000 + +#endif diff --git a/frontends/windows/schedule.c b/frontends/windows/schedule.c new file mode 100644 index 000000000..5366add9c --- /dev/null +++ b/frontends/windows/schedule.c @@ -0,0 +1,235 @@ +/* + * 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 "utils/sys_time.h" +#include "utils/log.h" +#include "utils/utils.h" +#include "utils/errors.h" + +#include "windows/schedule.h" + +#ifdef DEBUG_SCHEDULER +#define SRLOG(x...) LOG(x) +#else +#define SRLOG(x...) ((void) 0) +#endif + +/* linked list of scheduled callbacks */ +static struct nscallback *schedule_list = NULL; + +/** + * scheduled callback. + */ +struct nscallback +{ + struct nscallback *next; + struct timeval tv; + void (*callback)(void *p); + void *p; +}; + + +/** + * 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. + */ + +static nserror schedule_remove(void (*callback)(void *p), void *p) +{ + struct nscallback *cur_nscb; + struct nscallback *prev_nscb; + struct nscallback *unlnk_nscb; + + /* check there is something on the list to remove */ + if (schedule_list == NULL) { + return NSERROR_OK; + } + + SRLOG("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 */ + + SRLOG("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; + } + } + return NSERROR_OK; +} + +/* exported interface documented in windows/schedule.h */ +nserror win32_schedule(int ival, void (*callback)(void *p), void *p) +{ + struct nscallback *nscb; + struct timeval tv; + nserror ret; + + ret = schedule_remove(callback, p); + if ((ival < 0) || (ret != NSERROR_OK)) { + return ret; + } + + tv.tv_sec = ival / 1000; /* miliseconds to seconds */ + tv.tv_usec = (ival % 1000) * 1000; /* remainder to microseconds */ + + nscb = calloc(1, sizeof(struct nscallback)); + if (nscb == NULL) { + return NSERROR_NOMEM; + } + + SRLOG("adding callback %p for %p(%p) at %d cs", + nscb, callback, p, 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; + + return NSERROR_OK; +} + +/* exported interface documented in schedule.h */ +int +schedule_run(void) +{ + struct timeval tv; + struct timeval nexttime; + struct timeval rettime; + struct nscallback *cur_nscb; + struct nscallback *prev_nscb; + struct nscallback *unlnk_nscb; + + if (schedule_list == NULL) + return -1; + + /* reset enumeration to the start of the list */ + cur_nscb = schedule_list; + prev_nscb = NULL; + nexttime = cur_nscb->tv; + + 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; + } + + SRLOG("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); + + /* dispatched events can modify the list, + * instead of locking we simply reset list + * enumeration to the start. + */ + if (schedule_list == NULL) + return -1; /* no more callbacks scheduled */ + + cur_nscb = schedule_list; + prev_nscb = NULL; + nexttime = cur_nscb->tv; + } else { + /* if the time to the event is sooner than the + * currently recorded soonest event record it + */ + if (timercmp(&nexttime, &cur_nscb->tv, >)) { + nexttime = cur_nscb->tv; + } + /* move to next element */ + prev_nscb = cur_nscb; + cur_nscb = prev_nscb->next; + } + } + + /* make returned time relative to now */ + timersub(&nexttime, &tv, &rettime); + + SRLOG("returning time to next event as %ldms", + (rettime.tv_sec * 1000) + (rettime.tv_usec / 1000)); + + /* return next event time in milliseconds (24days max wait) */ + return (rettime.tv_sec * 1000) + (rettime.tv_usec / 1000); +} + +/* exported interface documented in schedule.h */ +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; + } +} + + +/* + * Local Variables: + * c-basic-offset:8 + * End: + */ diff --git a/frontends/windows/schedule.h b/frontends/windows/schedule.h new file mode 100644 index 000000000..6d47b2db6 --- /dev/null +++ b/frontends/windows/schedule.h @@ -0,0 +1,65 @@ +/* + * 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 . + */ + +#ifndef WINDOWS_SCHEDULE_H +#define WINDOWS_SCHEDULE_H + +/** + * Schedule a callback. + * + * \param ival interval before the callback should be made in ms + * \param callback callback function + * \param p user parameter, passed to callback function + * + * The callback function will be called as soon as possible after t ms have + * passed. + */ +nserror win32_schedule(int ival, void (*callback)(void *p), void *p); + +/** + * Process scheduled callbacks up to current time. + * + * This walks the list of outstanding scheduled events and dispatches + * them if they have met their scheduled time. Due to legacy issues + * there are a couple of subtleties with how this operates: + * + * - Generally there are so few entries on the list the overhead of + * ordering the list exceeds the cost of simply enumerating them. + * + * - The scheduled time is the time *after* which we should call the + * operation back, this can result in the next scheduled time + * being zero. This is exceedingly rare as the core schedules in + * 10ms (cs) quanta and we almost always get called to schedule + * after the event time. + * + * - The callbacks can cause the schedule list to be re-arranged added + * to or even completely deleted. This means we must reset the + * list enumeration to the beginning every time an event is + * dispatched. + * + * @return The number of milliseconds untill the next scheduled event + * or -1 for no event. + */ +int schedule_run(void); + +/** + * LOG all current scheduled events. + */ +void list_schedule(void); + +#endif diff --git a/frontends/windows/windbg.c b/frontends/windows/windbg.c new file mode 100644 index 000000000..ccbecc31e --- /dev/null +++ b/frontends/windows/windbg.c @@ -0,0 +1,663 @@ +/* + * Copyright 2011 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 "windbg.h" + +const char *msg_num_to_name(int msg) +{ + static char str[256]; + + switch (msg) { + case 32768: + return "WM_APP"; + + case 6: + return "WM_ACTIVATE "; + + case 28: + return "WM_ACTIVATEAPP "; + + case 864: + return "WM_AFXFIRST "; + + case 895: + return "WM_AFXLAST "; + + case 780: + return "WM_ASKCBFORMATNAME "; + + case 75: + return "WM_CANCELJOURNAL "; + + case 31: + return "WM_CANCELMODE "; + + case 533: + return "WM_CAPTURECHANGED "; + + case 781: + return "WM_CHANGECBCHAIN "; + + case 258: + return "WM_CHAR "; + + case 47: + return "WM_CHARTOITEM "; + + case 34: + return "WM_CHILDACTIVATE "; + + case 771: + return "WM_CLEAR "; + + case 16: + return "WM_CLOSE "; + + case 273: + return "WM_COMMAND "; + + case 68: + return "WM_COMMNOTIFY "; + + case 65: + return "WM_COMPACTING "; + + case 57: + return "WM_COMPAREITEM "; + + case 123: + return "WM_CONTEXTMENU "; + + case 769: + return "WM_COPY "; + + case 74: + return "WM_COPYDATA "; + + case 1: + return "WM_CREATE "; + + case 309: + return "WM_CTLCOLORBTN "; + + case 310: + return "WM_CTLCOLORDLG "; + + case 307: + return "WM_CTLCOLOREDIT "; + + case 308: + return "WM_CTLCOLORLISTBOX "; + + case 306: + return "WM_CTLCOLORMSGBOX "; + + case 311: + return "WM_CTLCOLORSCROLLBAR "; + + case 312: + return "WM_CTLCOLORSTATIC "; + + case 768: + return "WM_CUT "; + + case 259: + return "WM_DEADCHAR "; + + case 45: + return "WM_DELETEITEM "; + + case 2: + return "WM_DESTROY "; + + case 775: + return "WM_DESTROYCLIPBOARD "; + + case 537: + return "WM_DEVICECHANGE "; + + case 27: + return "WM_DEVMODECHANGE "; + + case 126: + return "WM_DISPLAYCHANGE "; + + case 776: + return "WM_DRAWCLIPBOARD "; + + case 43: + return "WM_DRAWITEM "; + + case 563: + return "WM_DROPFILES "; + + case 10: + return "WM_ENABLE "; + + case 22: + return "WM_ENDSESSION "; + + case 289: + return "WM_ENTERIDLE "; + + case 529: + return "WM_ENTERMENULOOP "; + + case 561: + return "WM_ENTERSIZEMOVE "; + + case 20: + return "WM_ERASEBKGND "; + + case 530: + return "WM_EXITMENULOOP "; + + case 562: + return "WM_EXITSIZEMOVE "; + + case 29: + return "WM_FONTCHANGE "; + + case 135: + return "WM_GETDLGCODE "; + + case 49: + return "WM_GETFONT "; + + case 51: + return "WM_GETHOTKEY "; + + case 127: + return "WM_GETICON "; + + case 36: + return "WM_GETMINMAXINFO "; + + case 13: + return "WM_GETTEXT "; + + case 14: + return "WM_GETTEXTLENGTH "; + + case 856: + return "WM_HANDHELDFIRST "; + + case 863: + return "WM_HANDHELDLAST "; + + case 83: + return "WM_HELP "; + + case 786: + return "WM_HOTKEY "; + + case 276: + return "WM_HSCROLL "; + + case 782: + return "WM_HSCROLLCLIPBOARD "; + + case 39: + return "WM_ICONERASEBKGND "; + + case 272: + return "WM_INITDIALOG "; + + case 278: + return "WM_INITMENU "; + + case 279: + return "WM_INITMENUPOPUP "; + + case 0x00FF: + return "WM_INPUT "; + + case 81: + return "WM_INPUTLANGCHANGE "; + + case 80: + return "WM_INPUTLANGCHANGEREQUEST "; + + case 256: + return "WM_KEYDOWN "; + + case 257: + return "WM_KEYUP "; + + case 8: + return "WM_KILLFOCUS "; + + case 546: + return "WM_MDIACTIVATE "; + + case 551: + return "WM_MDICASCADE "; + + case 544: + return "WM_MDICREATE "; + + case 545: + return "WM_MDIDESTROY "; + + case 553: + return "WM_MDIGETACTIVE "; + + case 552: + return "WM_MDIICONARRANGE "; + + case 549: + return "WM_MDIMAXIMIZE "; + + case 548: + return "WM_MDINEXT "; + + case 564: + return "WM_MDIREFRESHMENU "; + + case 547: + return "WM_MDIRESTORE "; + + case 560: + return "WM_MDISETMENU "; + + case 550: + return "WM_MDITILE "; + + case 44: + return "WM_MEASUREITEM "; + + case 0x003D: + return "WM_GETOBJECT "; + + case 0x0127: + return "WM_CHANGEUISTATE "; + + case 0x0128: + return "WM_UPDATEUISTATE "; + + case 0x0129: + return "WM_QUERYUISTATE "; + + case 0x0125: + return "WM_UNINITMENUPOPUP "; + + case 290: + return "WM_MENURBUTTONUP "; + + case 0x0126: + return "WM_MENUCOMMAND "; + + case 0x0124: + return "WM_MENUGETOBJECT "; + + case 0x0123: + return "WM_MENUDRAG "; + + case 0x0319: + return "WM_APPCOMMAND "; + + case 288: + return "WM_MENUCHAR "; + + case 287: + return "WM_MENUSELECT "; + + case 531: + return "WM_NEXTMENU "; + + case 3: + return "WM_MOVE "; + + case 534: + return "WM_MOVING "; + + case 134: + return "WM_NCACTIVATE "; + + case 131: + return "WM_NCCALCSIZE "; + + case 129: + return "WM_NCCREATE "; + + case 130: + return "WM_NCDESTROY "; + + case 132: + return "WM_NCHITTEST "; + + case 163: + return "WM_NCLBUTTONDBLCLK "; + + case 161: + return "WM_NCLBUTTONDOWN "; + + case 162: + return "WM_NCLBUTTONUP "; + + case 169: + return "WM_NCMBUTTONDBLCLK "; + + case 167: + return "WM_NCMBUTTONDOWN "; + + case 168: + return "WM_NCMBUTTONUP "; + + case 171: + return "WM_NCXBUTTONDOWN "; + + case 172: + return "WM_NCXBUTTONUP "; + + case 173: + return "WM_NCXBUTTONDBLCLK "; + + case 0x02A0: + return "WM_NCMOUSEHOVER "; + + case 0x02A2: + return "WM_NCMOUSELEAVE "; + + case 160: + return "WM_NCMOUSEMOVE "; + + case 133: + return "WM_NCPAINT "; + + case 166: + return "WM_NCRBUTTONDBLCLK "; + + case 164: + return "WM_NCRBUTTONDOWN "; + + case 165: + return "WM_NCRBUTTONUP "; + + case 40: + return "WM_NEXTDLGCTL "; + + case 78: + return "WM_NOTIFY "; + + case 85: + return "WM_NOTIFYFORMAT "; + + case 0: + return "WM_NULL "; + + case 15: + return "WM_PAINT "; + + case 777: + return "WM_PAINTCLIPBOARD "; + + case 38: + return "WM_PAINTICON "; + + case 785: + return "WM_PALETTECHANGED "; + + case 784: + return "WM_PALETTEISCHANGING "; + + case 528: + return "WM_PARENTNOTIFY "; + + case 770: + return "WM_PASTE "; + + case 896: + return "WM_PENWINFIRST "; + + case 911: + return "WM_PENWINLAST "; + + case 72: + return "WM_POWER "; + + case 536: + return "WM_POWERBROADCAST "; + + case 791: + return "WM_PRINT "; + + case 792: + return "WM_PRINTCLIENT "; + + case 55: + return "WM_QUERYDRAGICON "; + + case 17: + return "WM_QUERYENDSESSION "; + + case 783: + return "WM_QUERYNEWPALETTE "; + + case 19: + return "WM_QUERYOPEN "; + + case 35: + return "WM_QUEUESYNC "; + + case 18: + return "WM_QUIT "; + + case 774: + return "WM_RENDERALLFORMATS "; + + case 773: + return "WM_RENDERFORMAT "; + + case 32: + return "WM_SETCURSOR "; + + case 7: + return "WM_SETFOCUS "; + + case 48: + return "WM_SETFONT "; + + case 50: + return "WM_SETHOTKEY "; + + case 128: + return "WM_SETICON "; + + case 11: + return "WM_SETREDRAW "; + + case 12: + return "WM_SETTEXT "; + + case 26: + return "WM_SETTINGCHANGE "; + + case 24: + return "WM_SHOWWINDOW "; + + case 5: + return "WM_SIZE "; + + case 779: + return "WM_SIZECLIPBOARD "; + + case 532: + return "WM_SIZING "; + + case 42: + return "WM_SPOOLERSTATUS "; + + case 125: + return "WM_STYLECHANGED "; + + case 124: + return "WM_STYLECHANGING "; + + case 262: + return "WM_SYSCHAR "; + + case 21: + return "WM_SYSCOLORCHANGE "; + + case 274: + return "WM_SYSCOMMAND "; + + case 263: + return "WM_SYSDEADCHAR "; + + case 260: + return "WM_SYSKEYDOWN "; + + case 261: + return "WM_SYSKEYUP "; + + case 82: + return "WM_TCARD "; + + case 794: + return "WM_THEMECHANGED "; + + case 30: + return "WM_TIMECHANGE "; + + case 275: + return "WM_TIMER "; + + case 772: + return "WM_UNDO "; + + case 1024: + return "WM_USER "; + + case 84: + return "WM_USERCHANGED "; + + case 46: + return "WM_VKEYTOITEM "; + + case 277: + return "WM_VSCROLL "; + + case 778: + return "WM_VSCROLLCLIPBOARD "; + + case 71: + return "WM_WINDOWPOSCHANGED "; + + case 70: + return "WM_WINDOWPOSCHANGING "; + + case 264: + return "WM_KEYLAST "; + + case 136: + return "WM_SYNCPAINT "; + + case 33: + return "WM_MOUSEACTIVATE "; + + case 512: + return "WM_MOUSEMOVE "; + + case 513: + return "WM_LBUTTONDOWN "; + + case 514: + return "WM_LBUTTONUP "; + + case 515: + return "WM_LBUTTONDBLCLK "; + + case 516: + return "WM_RBUTTONDOWN "; + + case 517: + return "WM_RBUTTONUP "; + + case 518: + return "WM_RBUTTONDBLCLK "; + + case 519: + return "WM_MBUTTONDOWN "; + + case 520: + return "WM_MBUTTONUP "; + + case 521: + return "WM_MBUTTONDBLCLK "; + + case 522: + return "WM_MOUSEWHEEL "; + + case 523: + return "WM_XBUTTONDOWN "; + + case 524: + return "WM_XBUTTONUP "; + + case 525: + return "WM_XBUTTONDBLCLK "; + + case 0x2A1: + return "WM_MOUSEHOVER "; + + case 0x2A3: + return "WM_MOUSELEAVE "; + + } + + sprintf(str,"%d",msg); + + return str; +} + +void win_perror(const char * lpszFunction) +{ + /* Retrieve the system error message for the last-error code */ + + LPVOID lpMsgBuf; + LPVOID lpDisplayBuf; + DWORD dw = GetLastError(); + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL ); + + /* Display the error message and exit the process */ + + lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); + + snprintf((LPTSTR)lpDisplayBuf, + LocalSize(lpDisplayBuf) / sizeof(TCHAR), + TEXT("%s failed with error %ld: %s"), + lpszFunction, dw, (char *)lpMsgBuf); + MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); + + LocalFree(lpMsgBuf); + LocalFree(lpDisplayBuf); +} diff --git a/frontends/windows/windbg.h b/frontends/windows/windbg.h new file mode 100644 index 000000000..b2d8640f4 --- /dev/null +++ b/frontends/windows/windbg.h @@ -0,0 +1,34 @@ +/* + * 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_WINDOWS_WINDBG_H_ +#define _NETSURF_WINDOWS_WINDBG_H_ + +#include "utils/log.h" + +const char *msg_num_to_name(int msg); +void win_perror(const char *lpszFunction); + +#define LOG_WIN_MSG(h, m, w, l) \ + if (((m) != WM_SETCURSOR) && \ + ((m) != WM_MOUSEMOVE) && \ + ((m) != WM_NCHITTEST) && \ + ((m) != WM_ENTERIDLE)) \ + LOG("%s, hwnd %p, w 0x%x, l 0x%Ix", msg_num_to_name(m), h, w, l); + +#endif diff --git a/frontends/windows/window.c b/frontends/windows/window.c new file mode 100644 index 000000000..f5f13fe24 --- /dev/null +++ b/frontends/windows/window.c @@ -0,0 +1,1741 @@ +/* + * Copyright 2011 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 "utils/config.h" + +#include +#include +#include +#include + +#include "utils/errors.h" +#include "utils/log.h" +#include "utils/utils.h" +#include "utils/nsoption.h" +#include "utils/nsurl.h" +#include "utils/messages.h" +#include "content/content.h" +#include "desktop/browser.h" +#include "desktop/gui_window.h" +#include "desktop/browser_history.h" +#include "desktop/textinput.h" + +#include "windows/gui.h" +#include "windows/pointers.h" +#include "windows/about.h" +#include "windows/resourceid.h" +#include "windows/findfile.h" +#include "windows/windbg.h" +#include "windows/drawable.h" +#include "windows/font.h" +#include "windows/prefs.h" +#include "windows/localhistory.h" +#include "windows/window.h" + +/** List of all our gui windows */ +static struct gui_window *window_list = NULL; + +/** The main window class name */ +static const char windowclassname_main[] = "nswsmainwindow"; + +/** width of the throbber element */ +#define NSWS_THROBBER_WIDTH 24 + +/** Number of open windows */ +static int open_windows = 0; + + +/** + * Obtain the DPI of the display. + */ +static int get_window_dpi(HWND hwnd) +{ + HDC hdc = GetDC(hwnd); + int dpi = GetDeviceCaps(hdc, LOGPIXELSY); + + if (dpi <= 10) { + dpi = 96; /* 96DPI is the default */ + } + + ReleaseDC(hwnd, hdc); + + LOG("FIX DPI %d", dpi); + + return dpi; +} + + +/** + * 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 = IDM_FILE_QUIT; + accels[1].key = 0x4E; /* N */ + accels[1].cmd = IDM_FILE_OPEN_WINDOW; + accels[2].key = VK_LEFT; + accels[2].cmd = IDM_NAV_BACK; + accels[3].key = VK_RIGHT; + accels[3].cmd = IDM_NAV_FORWARD; + accels[4].key = VK_UP; + accels[4].cmd = IDM_NAV_HOME; + accels[5].key = VK_BACK; + accels[5].cmd = IDM_NAV_STOP; + accels[6].key = VK_SPACE; + accels[6].cmd = IDM_NAV_RELOAD; + accels[7].key = 0x4C; /* L */ + accels[7].cmd = IDM_FILE_OPEN_LOCATION; + accels[8].key = 0x57; /* w */ + accels[8].cmd = IDM_FILE_CLOSE_WINDOW; + accels[9].key = 0x41; /* A */ + accels[9].cmd = IDM_EDIT_SELECT_ALL; + accels[10].key = VK_F8; + accels[10].cmd = IDM_VIEW_SOURCE; + accels[11].key = VK_RETURN; + accels[11].fVirt = FVIRTKEY; + accels[11].cmd = IDC_MAIN_LAUNCH_URL; + accels[12].key = VK_F11; + accels[12].fVirt = FVIRTKEY; + accels[12].cmd = IDM_VIEW_FULLSCREEN; + + w->acceltable = CreateAcceleratorTable(accels, nitems); +} + + +/** + * creation of a new full browser window + */ +static HWND nsws_window_create(struct gui_window *gw) +{ + HWND hwnd; + INITCOMMONCONTROLSEX icc; + + LOG("GUI window %p", gw); + + icc.dwSize = sizeof(icc); + icc.dwICC = ICC_BAR_CLASSES | ICC_WIN95_CLASSES; +#if WINVER > 0x0501 + icc.dwICC |= ICC_STANDARD_CLASSES; +#endif + InitCommonControlsEx(&icc); + + gw->mainmenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU_MAIN)); + gw->rclick = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU_CONTEXT)); + + LOG("creating window for hInstance %p", hInstance); + hwnd = CreateWindowEx(0, + windowclassname_main, + "NetSurf Browser", + WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CS_DBLCLKS, + CW_USEDEFAULT, + CW_USEDEFAULT, + gw->width, + gw->height, + NULL, + gw->mainmenu, + hInstance, + NULL); + + if (hwnd == NULL) { + LOG("Window create failed"); + return NULL; + } + + /* set the gui window associated with this browser */ + SetProp(hwnd, TEXT("GuiWnd"), (HANDLE)gw); + + browser_set_dpi(get_window_dpi(hwnd)); + + if ((nsoption_int(window_width) >= 100) && + (nsoption_int(window_height) >= 100) && + (nsoption_int(window_x) >= 0) && + (nsoption_int(window_y) >= 0)) { + LOG("Setting Window position %d,%d %d,%d", nsoption_int(window_x), nsoption_int(window_y), nsoption_int(window_width), nsoption_int(window_height)); + SetWindowPos(hwnd, HWND_TOP, + nsoption_int(window_x), nsoption_int(window_y), + nsoption_int(window_width), nsoption_int(window_height), + SWP_SHOWWINDOW); + } + + nsws_window_set_accels(gw); + + return hwnd; +} + + +/** + * calculate the dimensions of the url bar relative to the parent toolbar + */ +static void +urlbar_dimensions(HWND hWndParent, + int toolbuttonsize, + int buttonc, + int *x, + int *y, + int *width, + int *height) +{ + RECT rc; + const int cy_edit = 23; + + GetClientRect(hWndParent, &rc); + *x = (toolbuttonsize + 1) * (buttonc + 1) + (NSWS_THROBBER_WIDTH>>1); + *y = ((((rc.bottom - 1) - cy_edit) >> 1) * 2) / 3; + *width = (rc.right - 1) - *x - (NSWS_THROBBER_WIDTH>>1) - NSWS_THROBBER_WIDTH; + *height = cy_edit; +} + + + +static LRESULT +nsws_window_toolbar_command(struct gui_window *gw, + int notification_code, + int identifier, + HWND ctrl_window) +{ + LOG("notification_code %d identifier %d ctrl_window %p", notification_code, identifier, ctrl_window); + + switch(identifier) { + + case IDC_MAIN_URLBAR: + switch (notification_code) { + case EN_CHANGE: + LOG("EN_CHANGE"); + break; + + case EN_ERRSPACE: + LOG("EN_ERRSPACE"); + break; + + case EN_HSCROLL: + LOG("EN_HSCROLL"); + break; + + case EN_KILLFOCUS: + LOG("EN_KILLFOCUS"); + break; + + case EN_MAXTEXT: + LOG("EN_MAXTEXT"); + break; + + case EN_SETFOCUS: + LOG("EN_SETFOCUS"); + break; + + case EN_UPDATE: + LOG("EN_UPDATE"); + break; + + case EN_VSCROLL: + LOG("EN_VSCROLL"); + break; + + default: + LOG("Unknown notification_code"); + break; + } + break; + + default: + return 1; /* unhandled */ + + } + return 0; /* control message handled */ +} + + +/** + * callback for toolbar events + */ +static LRESULT CALLBACK +nsws_window_toolbar_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + struct gui_window *gw; + int urlx, urly, urlwidth, urlheight; + WNDPROC toolproc; + + LOG_WIN_MSG(hwnd, msg, wparam, lparam); + + gw = nsws_get_gui_window(hwnd); + + switch (msg) { + case WM_SIZE: + urlbar_dimensions(hwnd, + gw->toolbuttonsize, + gw->toolbuttonc, + &urlx, &urly, &urlwidth, &urlheight); + + /* resize url */ + if (gw->urlbar != NULL) { + MoveWindow(gw->urlbar, + urlx, urly, + urlwidth, urlheight, + true); + } + + /* move throbber */ + if (gw->throbber != NULL) { + MoveWindow(gw->throbber, + LOWORD(lparam) - NSWS_THROBBER_WIDTH - 4, 8, + NSWS_THROBBER_WIDTH, NSWS_THROBBER_WIDTH, + true); + } + break; + + case WM_COMMAND: + if (nsws_window_toolbar_command(gw, + HIWORD(wparam), + LOWORD(wparam), + (HWND)lparam) == 0) { + return 0; + } + break; + } + + /* remove properties if window is being destroyed */ + if (msg == WM_NCDESTROY) { + RemoveProp(hwnd, TEXT("GuiWnd")); + toolproc = (WNDPROC)RemoveProp(hwnd, TEXT("OrigMsgProc")); + } else { + toolproc = (WNDPROC)GetProp(hwnd, TEXT("OrigMsgProc")); + } + + if (toolproc == NULL) { + /* the original toolbar procedure is not available */ + return DefWindowProc(hwnd, msg, wparam, lparam); + } + + /* chain to the next handler */ + return CallWindowProc(toolproc, hwnd, msg, wparam, lparam); +} + + +static HIMAGELIST +get_imagelist(int resid, int bsize, int bcnt) +{ + HIMAGELIST hImageList; + HBITMAP hScrBM; + + LOG("resource id %d, bzize %d, bcnt %d", resid, bsize, bcnt); + + hImageList = ImageList_Create(bsize, bsize, ILC_COLOR24 | ILC_MASK, 0, + bcnt); + if (hImageList == NULL) + return NULL; + + hScrBM = LoadImage(hInstance, MAKEINTRESOURCE(resid), + IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); + + if (hScrBM == NULL) { + win_perror("LoadImage"); + return NULL; + } + + if (ImageList_AddMasked(hImageList, hScrBM, 0xcccccc) == -1) { + /* failed to add masked bitmap */ + ImageList_Destroy(hImageList); + hImageList = NULL; + } + DeleteObject(hScrBM); + + return hImageList; +} + + +/** + * callback for url bar events + */ +static LRESULT CALLBACK +nsws_window_urlbar_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + struct gui_window *gw; + WNDPROC urlproc; + HFONT hFont; + + LOG_WIN_MSG(hwnd, msg, wparam, lparam); + + gw = nsws_get_gui_window(hwnd); + + urlproc = (WNDPROC)GetProp(hwnd, TEXT("OrigMsgProc")); + + /* override messages */ + switch (msg) { + case WM_CHAR: + if (wparam == 13) { + SendMessage(gw->main, WM_COMMAND, IDC_MAIN_LAUNCH_URL, 0); + return 0; + } + break; + + case WM_DESTROY: + hFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0); + if (hFont != NULL) { + LOG("Destroyed font object"); + DeleteObject(hFont); + } + + + case WM_NCDESTROY: + /* remove properties if window is being destroyed */ + RemoveProp(hwnd, TEXT("GuiWnd")); + RemoveProp(hwnd, TEXT("OrigMsgProc")); + break; + } + + if (urlproc == NULL) { + /* the original toolbar procedure is not available */ + return DefWindowProc(hwnd, msg, wparam, lparam); + } + + /* chain to the next handler */ + return CallWindowProc(urlproc, hwnd, msg, wparam, lparam); +} + + +/** + * create a urlbar and message handler + * + * Create an Edit control for enerting urls + */ +static HWND +nsws_window_urlbar_create(struct gui_window *gw, HWND hwndparent) +{ + int urlx, urly, urlwidth, urlheight; + HWND hwnd; + WNDPROC urlproc; + HFONT hFont; + + urlbar_dimensions(hwndparent, + gw->toolbuttonsize, + gw->toolbuttonc, + &urlx, &urly, &urlwidth, &urlheight); + + /* Create the edit control */ + hwnd = CreateWindowEx(0L, + TEXT("Edit"), + NULL, + WS_CHILD | WS_BORDER | WS_VISIBLE | ES_LEFT | ES_AUTOHSCROLL, + urlx, + urly, + urlwidth, + urlheight, + hwndparent, + (HMENU)IDC_MAIN_URLBAR, + hInstance, + 0); + + if (hwnd == NULL) { + return NULL; + } + + /* set the gui window associated with this control */ + SetProp(hwnd, TEXT("GuiWnd"), (HANDLE)gw); + + /* subclass the message handler */ + urlproc = (WNDPROC)SetWindowLongPtr(hwnd, + GWLP_WNDPROC, + (LONG_PTR)nsws_window_urlbar_callback); + + /* save the real handler */ + SetProp(hwnd, TEXT("OrigMsgProc"), (HANDLE)urlproc); + + hFont = CreateFont(urlheight - 4, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial"); + if (hFont != NULL) { + LOG("Setting font object"); + SendMessage(hwnd, WM_SETFONT, (WPARAM)hFont, 0); + } + + LOG("Created url bar hwnd:%p, x:%d, y:%d, w:%d, h:%d", hwnd, urlx, urly, urlwidth, urlheight); + + return hwnd; +} + + +/** + * creation of throbber + */ +static HWND +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) IDC_MAIN_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); + return hwnd; +} + + +/* create a toolbar add controls and message handler */ +static HWND +nsws_window_create_toolbar(struct gui_window *gw, HWND hWndParent) +{ + HIMAGELIST hImageList; + HWND hWndToolbar; + /* Toolbar buttons */ + TBBUTTON tbButtons[] = { + {0, IDM_NAV_BACK, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, + {1, IDM_NAV_FORWARD, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, + {2, IDM_NAV_HOME, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, + {3, IDM_NAV_RELOAD, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, + {4, IDM_NAV_STOP, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, + }; + WNDPROC toolproc; + + /* Create the toolbar window and subclass its message handler. */ + hWndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, "Toolbar", + WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT, + 0, 0, 0, 0, + hWndParent, NULL, HINST_COMMCTRL, NULL); + if (!hWndToolbar) { + return NULL; + } + + /* set the gui window associated with this toolbar */ + SetProp(hWndToolbar, TEXT("GuiWnd"), (HANDLE)gw); + + /* subclass the message handler */ + toolproc = (WNDPROC)SetWindowLongPtr(hWndToolbar, + GWLP_WNDPROC, + (LONG_PTR)nsws_window_toolbar_callback); + + /* save the real handler */ + SetProp(hWndToolbar, TEXT("OrigMsgProc"), (HANDLE)toolproc); + + /* remember how many buttons are being created */ + gw->toolbuttonc = sizeof(tbButtons) / sizeof(TBBUTTON); + + /* Create the standard image list and assign to toolbar. */ + hImageList = get_imagelist(IDR_TOOLBAR_BITMAP, + gw->toolbuttonsize, + gw->toolbuttonc); + if (hImageList != NULL) { + SendMessage(hWndToolbar, TB_SETIMAGELIST, 0, (LPARAM)hImageList); + } + + /* Create the disabled image list and assign to toolbar. */ + hImageList = get_imagelist(IDR_TOOLBAR_BITMAP_GREY, + gw->toolbuttonsize, + gw->toolbuttonc); + if (hImageList != NULL) { + SendMessage(hWndToolbar, TB_SETDISABLEDIMAGELIST, 0, + (LPARAM)hImageList); + } + + /* Create the hot image list and assign to toolbar. */ + hImageList = get_imagelist(IDR_TOOLBAR_BITMAP_HOT, + gw->toolbuttonsize, + gw->toolbuttonc); + if (hImageList != NULL) { + SendMessage(hWndToolbar, TB_SETHOTIMAGELIST, 0, + (LPARAM)hImageList); + } + + /* Add buttons. */ + SendMessage(hWndToolbar, + TB_BUTTONSTRUCTSIZE, + (WPARAM)sizeof(TBBUTTON), + 0); + SendMessage(hWndToolbar, + TB_ADDBUTTONS, + (WPARAM)gw->toolbuttonc, + (LPARAM)&tbButtons); + + gw->urlbar = nsws_window_urlbar_create(gw, hWndToolbar); + + gw->throbber = nsws_window_throbber_create(gw); + + return hWndToolbar; +} + + +/** + * creation of status bar + */ +static HWND nsws_window_create_statusbar(struct gui_window *w) +{ + HWND hwnd = CreateWindowEx(0, + STATUSCLASSNAME, + NULL, + WS_CHILD | WS_VISIBLE, + 0, 0, 0, 0, + w->main, + (HMENU)IDC_MAIN_STATUSBAR, + hInstance, + NULL); + SendMessage(hwnd, SB_SETTEXT, 0, (LPARAM)"NetSurf"); + return hwnd; +} + + +static void nsws_update_edit(struct gui_window *w) +{ + browser_editor_flags editor_flags = (w->bw == NULL) ? + BW_EDITOR_NONE : browser_window_get_editor_flags(w->bw); + bool paste, copy, del; + bool sel = (editor_flags & BW_EDITOR_CAN_COPY); + 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 (sel){ + paste = (editor_flags & BW_EDITOR_CAN_PASTE); + copy = sel; + del = (editor_flags & BW_EDITOR_CAN_CUT); + } else { + paste = false; + copy = false; + del = false; + } + EnableMenuItem(w->mainmenu, + IDM_EDIT_PASTE, + (paste ? MF_ENABLED : MF_GRAYED)); + + EnableMenuItem(w->rclick, + IDM_EDIT_PASTE, + (paste ? MF_ENABLED : MF_GRAYED)); + + EnableMenuItem(w->mainmenu, + IDM_EDIT_COPY, + (copy ? MF_ENABLED : MF_GRAYED)); + + EnableMenuItem(w->rclick, + IDM_EDIT_COPY, + (copy ? MF_ENABLED : MF_GRAYED)); + + if (del == true) { + EnableMenuItem(w->mainmenu, IDM_EDIT_CUT, MF_ENABLED); + EnableMenuItem(w->mainmenu, IDM_EDIT_DELETE, MF_ENABLED); + EnableMenuItem(w->rclick, IDM_EDIT_CUT, MF_ENABLED); + EnableMenuItem(w->rclick, IDM_EDIT_DELETE, MF_ENABLED); + } else { + EnableMenuItem(w->mainmenu, IDM_EDIT_CUT, MF_GRAYED); + EnableMenuItem(w->mainmenu, IDM_EDIT_DELETE, MF_GRAYED); + EnableMenuItem(w->rclick, IDM_EDIT_CUT, MF_GRAYED); + EnableMenuItem(w->rclick, IDM_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; +} + + +/** + * 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 = browser_window_history_forward_available(w->bw); + bool back = browser_window_history_back_available(w->bw); + + if (w->mainmenu != NULL) { + EnableMenuItem(w->mainmenu, IDM_NAV_FORWARD, + (forward ? MF_ENABLED : MF_GRAYED)); + EnableMenuItem(w->mainmenu, IDM_NAV_BACK, + (back ? MF_ENABLED : MF_GRAYED)); + EnableMenuItem(w->rclick, IDM_NAV_FORWARD, + (forward ? MF_ENABLED : MF_GRAYED)); + EnableMenuItem(w->rclick, IDM_NAV_BACK, + (back ? MF_ENABLED : MF_GRAYED)); + } + + if (w->toolbar != NULL) { + SendMessage(w->toolbar, TB_SETSTATE, + (WPARAM) IDM_NAV_FORWARD, + MAKELONG((forward ? TBSTATE_ENABLED : + TBSTATE_INDETERMINATE), 0)); + SendMessage(w->toolbar, TB_SETSTATE, + (WPARAM) IDM_NAV_BACK, + MAKELONG((back ? TBSTATE_ENABLED : + TBSTATE_INDETERMINATE), 0)); + } +} + + +static bool win32_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; +} + + +static void nsws_set_scale(struct gui_window *gw, float scale) +{ + assert(gw != NULL); + + if (gw->scale == scale) + return; + + gw->scale = scale; + + if (gw->bw == NULL) + return; + + browser_window_set_scale(gw->bw, scale, true); +} + + +/** + * redraw the whole window + */ +static void win32_window_redraw_window(struct gui_window *gw) +{ + /* LOG("gw:%p", gw); */ + if (gw != NULL) { + RedrawWindow(gw->drawingarea, NULL, NULL, + RDW_INVALIDATE | RDW_NOERASE); + } +} + + +/** + * scroll the window + * + * \param w The win32 gui window to scroll. + * \param sx the new 'absolute' horizontal scroll location + * \param sy the new 'absolute' vertical scroll location + */ +void win32_window_set_scroll(struct gui_window *w, int sx, int sy) +{ + SCROLLINFO si; + nserror err; + int height; + int width; + POINT p; + + if ((w == NULL) || (w->bw == NULL)) + return; + + err = browser_window_get_extents(w->bw, true, &width, &height); + if (err != NSERROR_OK) { + return; + } + + /*LOG("scroll sx,sy:%d,%d x,y:%d,%d w.h:%d,%d",sx,sy,w->scrollx,w->scrolly, width,height);*/ + + /* The resulting gui window scroll must remain withn the + * windows bounding box. + */ + if (sx < 0) { + w->requestscrollx = -w->scrollx; + } else if (sx > (width - w->width)) { + w->requestscrollx = (width - w->width) - w->scrollx; + } else { + w->requestscrollx = sx - w->scrollx; + } + if (sy < 0) { + w->requestscrolly = -w->scrolly; + } else if (sy > (height - w->height)) { + w->requestscrolly = (height - w->height) - w->scrolly; + } else { + w->requestscrolly = sy - w->scrolly; + } + + /*LOG("requestscroll x,y:%d,%d", w->requestscrollx, w->requestscrolly);*/ + + /* set the vertical scroll offset */ + si.cbSize = sizeof(si); + si.fMask = SIF_ALL; + si.nMin = 0; + si.nMax = height - 1; + si.nPage = w->height; + si.nPos = max(w->scrolly + w->requestscrolly, 0); + si.nPos = min(si.nPos, height - w->height); + SetScrollInfo(w->drawingarea, SB_VERT, &si, TRUE); + /*LOG("SetScrollInfo VERT min:%d max:%d page:%d pos:%d", si.nMin, si.nMax, si.nPage, si.nPos);*/ + + /* set the horizontal scroll offset */ + si.cbSize = sizeof(si); + si.fMask = SIF_ALL; + si.nMin = 0; + si.nMax = width -1; + si.nPage = w->width; + si.nPos = max(w->scrollx + w->requestscrollx, 0); + si.nPos = min(si.nPos, width - w->width); + SetScrollInfo(w->drawingarea, SB_HORZ, &si, TRUE); + /*LOG("SetScrollInfo HORZ min:%d max:%d page:%d pos:%d", si.nMin, si.nMax, si.nPage, si.nPos);*/ + + /* Set caret position */ + GetCaretPos(&p); + HideCaret(w->drawingarea); + SetCaretPos(p.x - w->requestscrollx, p.y - w->requestscrolly); + ShowCaret(w->drawingarea); + + RECT r, redraw; + r.top = 0; + r.bottom = w->height + 1; + r.left = 0; + r.right = w->width + 1; + ScrollWindowEx(w->drawingarea, - w->requestscrollx, - w->requestscrolly, &r, NULL, NULL, &redraw, SW_INVALIDATE); + /*LOG("ScrollWindowEx %d, %d", - w->requestscrollx, - w->requestscrolly);*/ + w->scrolly += w->requestscrolly; + w->scrollx += w->requestscrollx; + w->requestscrollx = 0; + w->requestscrolly = 0; + +} + +/** + * Create a new window due to menu selection + * + * \param gw frontends graphical window. + * \return NSERROR_OK on success else appropriate error code. + */ +static nserror win32_open_new_window(struct gui_window *gw) +{ + const char *addr; + nsurl *url; + nserror ret; + + if (nsoption_charp(homepage_url) != NULL) { + addr = nsoption_charp(homepage_url); + } else { + addr = NETSURF_HOMEPAGE; + } + + ret = nsurl_create(addr, &url); + if (ret == NSERROR_OK) { + ret = browser_window_create(BW_CREATE_HISTORY, + url, + NULL, + gw->bw, + NULL); + nsurl_unref(url); + } + + return ret; +} + +static LRESULT +nsws_window_command(HWND hwnd, + struct gui_window *gw, + int notification_code, + int identifier, + HWND ctrl_window) +{ + nserror ret; + + LOG("notification_code %x identifier %x ctrl_window %p", + notification_code, identifier, ctrl_window); + + switch(identifier) { + + case IDM_FILE_QUIT: + { + struct gui_window *w; + w = window_list; + while (w != NULL) { + PostMessage(w->main, WM_CLOSE, 0, 0); + w = w->next; + } + break; + } + + case IDM_FILE_OPEN_LOCATION: + SetFocus(gw->urlbar); + break; + + case IDM_FILE_OPEN_WINDOW: + ret = win32_open_new_window(gw); + if (ret != NSERROR_OK) { + win32_warning(messages_get_errorcode(ret), 0); + } + break; + + case IDM_FILE_CLOSE_WINDOW: + PostMessage(gw->main, WM_CLOSE, 0, 0); + break; + + case IDM_FILE_SAVE_PAGE: + break; + + case IDM_FILE_SAVEAS_TEXT: + break; + + case IDM_FILE_SAVEAS_PDF: + break; + + case IDM_FILE_SAVEAS_POSTSCRIPT: + break; + + case IDM_FILE_PRINT_PREVIEW: + break; + + case IDM_FILE_PRINT: + break; + + case IDM_EDIT_CUT: + OpenClipboard(gw->main); + EmptyClipboard(); + CloseClipboard(); + if (GetFocus() == gw->urlbar) { + SendMessage(gw->urlbar, WM_CUT, 0, 0); + } else if (gw->bw != NULL) { + browser_window_key_press(gw->bw, NS_KEY_CUT_SELECTION); + } + break; + + case IDM_EDIT_COPY: + OpenClipboard(gw->main); + EmptyClipboard(); + CloseClipboard(); + if (GetFocus() == gw->urlbar) { + SendMessage(gw->urlbar, WM_COPY, 0, 0); + } else if (gw->bw != NULL) { + browser_window_key_press(gw->bw, NS_KEY_COPY_SELECTION); + } + break; + + case IDM_EDIT_PASTE: { + OpenClipboard(gw->main); + HANDLE h = GetClipboardData(CF_TEXT); + if (h != NULL) { + char *content = GlobalLock(h); + LOG("pasting %s\n", content); + GlobalUnlock(h); + } + CloseClipboard(); + if (GetFocus() == gw->urlbar) + SendMessage(gw->urlbar, WM_PASTE, 0, 0); + else + browser_window_key_press(gw->bw, NS_KEY_PASTE); + break; + } + + case IDM_EDIT_DELETE: + if (GetFocus() == gw->urlbar) + SendMessage(gw->urlbar, WM_CUT, 0, 0); + else + browser_window_key_press(gw->bw, NS_KEY_DELETE_RIGHT); + break; + + case IDM_EDIT_SELECT_ALL: + if (GetFocus() == gw->urlbar) + SendMessage(gw->urlbar, EM_SETSEL, 0, -1); + else + browser_window_key_press(gw->bw, NS_KEY_SELECT_ALL); + break; + + case IDM_EDIT_SEARCH: + break; + + case IDM_EDIT_PREFERENCES: + nsws_prefs_dialog_init(hInstance, gw->main); + break; + + case IDM_NAV_BACK: + if ((gw->bw != NULL) && + (browser_window_history_back_available(gw->bw))) { + browser_window_history_back(gw->bw, false); + } + nsws_window_update_forward_back(gw); + break; + + case IDM_NAV_FORWARD: + if ((gw->bw != NULL) && + (browser_window_history_forward_available(gw->bw))) { + browser_window_history_forward(gw->bw, false); + } + nsws_window_update_forward_back(gw); + break; + + case IDM_NAV_HOME: + { + nsurl *url; + + if (nsurl_create(nsoption_charp(homepage_url), &url) != NSERROR_OK) { + win32_warning("NoMemory", 0); + } else { + browser_window_navigate(gw->bw, + url, + NULL, + BW_NAVIGATE_HISTORY, + NULL, + NULL, + NULL); + nsurl_unref(url); + } + break; + } + + case IDM_NAV_STOP: + browser_window_stop(gw->bw); + break; + + case IDM_NAV_RELOAD: + browser_window_reload(gw->bw, true); + break; + + case IDM_NAV_LOCALHISTORY: + gw->localhistory = nsws_window_create_localhistory(gw); + break; + + case IDM_NAV_GLOBALHISTORY: + break; + + case IDM_VIEW_ZOOMPLUS: { + int x, y; + win32_window_get_scroll(gw, &x, &y); + if (gw->bw != NULL) { + nsws_set_scale(gw, gw->scale * 1.1); + } + win32_window_redraw_window(gw); + win32_window_set_scroll(gw, x, y); + break; + } + + case IDM_VIEW_ZOOMMINUS: { + int x, y; + win32_window_get_scroll(gw, &x, &y); + if (gw->bw != NULL) { + nsws_set_scale(gw, gw->scale * 0.9); + } + win32_window_redraw_window(gw); + win32_window_set_scroll(gw, x, y); + break; + } + + case IDM_VIEW_ZOOMNORMAL: { + int x, y; + win32_window_get_scroll(gw, &x, &y); + if (gw->bw != NULL) { + nsws_set_scale(gw, 1.0); + } + win32_window_redraw_window(gw); + win32_window_set_scroll(gw, x, y); + break; + } + + case IDM_VIEW_SOURCE: + break; + + case IDM_VIEW_SAVE_WIN_METRICS: { + RECT r; + GetWindowRect(gw->main, &r); + nsoption_set_int(window_x, r.left); + nsoption_set_int(window_y, r.top); + nsoption_set_int(window_width, r.right - r.left); + nsoption_set_int(window_height, r.bottom - r.top); + nsoption_write(options_file_location, NULL, NULL); + break; + } + + case IDM_VIEW_FULLSCREEN: { + RECT rdesk; + if (gw->fullscreen == NULL) { + HWND desktop = GetDesktopWindow(); + gw->fullscreen = malloc(sizeof(RECT)); + if ((desktop == NULL) || + (gw->fullscreen == NULL)) { + win32_warning("NoMemory", 0); + break; + } + GetWindowRect(desktop, &rdesk); + GetWindowRect(gw->main, gw->fullscreen); + DeleteObject(desktop); + SetWindowLong(gw->main, GWL_STYLE, 0); + SetWindowPos(gw->main, HWND_TOPMOST, 0, 0, + rdesk.right - rdesk.left, + rdesk.bottom - rdesk.top, + SWP_SHOWWINDOW); + } else { + SetWindowLong(gw->main, GWL_STYLE, + WS_OVERLAPPEDWINDOW | + WS_HSCROLL | WS_VSCROLL | + WS_CLIPCHILDREN | + WS_CLIPSIBLINGS | CS_DBLCLKS); + SetWindowPos(gw->main, HWND_TOPMOST, + gw->fullscreen->left, + gw->fullscreen->top, + gw->fullscreen->right - + gw->fullscreen->left, + gw->fullscreen->bottom - + gw->fullscreen->top, + SWP_SHOWWINDOW | SWP_FRAMECHANGED); + free(gw->fullscreen); + gw->fullscreen = NULL; + } + break; + } + + case IDM_VIEW_DOWNLOADS: + break; + + case IDM_VIEW_TOGGLE_DEBUG_RENDERING: + if (gw->bw != NULL) { + browser_window_debug(gw->bw, CONTENT_DEBUG_REDRAW); + /* TODO: This should only redraw, not reformat. + * (Layout doesn't change, so reformat is a waste of time) */ + browser_window_reformat(gw->bw, false, gw->width, gw->height); + } + break; + + case IDM_VIEW_DEBUGGING_SAVE_BOXTREE: + break; + + case IDM_VIEW_DEBUGGING_SAVE_DOMTREE: + break; + + case IDM_HELP_CONTENTS: + nsws_window_go(hwnd, + "http://www.netsurf-browser.org/documentation/"); + break; + + case IDM_HELP_GUIDE: + nsws_window_go(hwnd, + "http://www.netsurf-browser.org/documentation/guide"); + break; + + case IDM_HELP_INFO: + nsws_window_go(hwnd, + "http://www.netsurf-browser.org/documentation/info"); + break; + + case IDM_HELP_ABOUT: + nsws_about_dialog_init(hInstance, gw->main); + break; + + case IDC_MAIN_LAUNCH_URL: + { + nsurl *url; + + if (GetFocus() != gw->urlbar) + break; + + int len = SendMessage(gw->urlbar, WM_GETTEXTLENGTH, 0, 0); + char addr[len + 1]; + SendMessage(gw->urlbar, WM_GETTEXT, (WPARAM)(len + 1), (LPARAM)addr); + LOG("launching %s\n", addr); + + if (nsurl_create(addr, &url) != NSERROR_OK) { + win32_warning("NoMemory", 0); + } else { + browser_window_navigate(gw->bw, + url, + NULL, + BW_NAVIGATE_HISTORY, + NULL, + NULL, + NULL); + nsurl_unref(url); + } + + break; + } + + + default: + return 1; /* unhandled */ + + } + return 0; /* control message handled */ +} + + +static LRESULT +nsws_window_resize(struct gui_window *gw, + HWND hwnd, + WPARAM wparam, + LPARAM lparam) +{ + int x, y; + RECT rstatus, rtool; + + if ((gw->toolbar == NULL) || + (gw->urlbar == NULL) || + (gw->statusbar == NULL)) + return 0; + + SendMessage(gw->statusbar, WM_SIZE, wparam, lparam); + SendMessage(gw->toolbar, WM_SIZE, wparam, lparam); + + GetClientRect(gw->toolbar, &rtool); + GetWindowRect(gw->statusbar, &rstatus); + win32_window_get_scroll(gw, &x, &y); + gw->width = LOWORD(lparam); + gw->height = HIWORD(lparam) - (rtool.bottom - rtool.top) - (rstatus.bottom - rstatus.top); + + if (gw->drawingarea != NULL) { + MoveWindow(gw->drawingarea, + 0, + rtool.bottom, + gw->width, + gw->height, + true); + } + nsws_window_update_forward_back(gw); + + win32_window_set_scroll(gw, x, y); + + if (gw->toolbar != NULL) { + SendMessage(gw->toolbar, TB_SETSTATE, + (WPARAM) IDM_NAV_STOP, + MAKELONG(TBSTATE_INDETERMINATE, 0)); + } + + return 0; +} + + +/** + * callback for window events generally + */ +static LRESULT CALLBACK +nsws_window_event_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + struct gui_window *gw; + RECT rmain; + + LOG_WIN_MSG(hwnd, msg, wparam, lparam); + + /* deal with window creation as a special case */ + if (msg == WM_CREATE) { + /* To cause all the component child windows to be + * re-sized correctly a WM_SIZE message of the actual + * created size must be sent. + * + * The message must be posted here because the actual + * size values of the component windows are not known + * until after the WM_CREATE message is dispatched. + */ + GetClientRect(hwnd, &rmain); + PostMessage(hwnd, WM_SIZE, 0, MAKELPARAM(rmain.right, rmain.bottom)); + return DefWindowProc(hwnd, msg, wparam, lparam); + } + + + gw = nsws_get_gui_window(hwnd); + if (gw == NULL) { + LOG("Unable to find gui window structure for hwnd %p", hwnd); + return DefWindowProc(hwnd, msg, wparam, lparam); + } + + switch (msg) { + + case WM_CONTEXTMENU: + if (nsws_ctx_menu(gw, hwnd, GET_X_LPARAM(lparam), + GET_Y_LPARAM(lparam))) { + return 0; + } + break; + + case WM_COMMAND: + if (nsws_window_command(hwnd, gw, HIWORD(wparam), + LOWORD(wparam), (HWND)lparam) == 0) { + return 0; + } + break; + + case WM_SIZE: + return nsws_window_resize(gw, hwnd, wparam, lparam); + + case WM_NCDESTROY: + RemoveProp(hwnd, TEXT("GuiWnd")); + browser_window_destroy(gw->bw); + if (--open_windows <= 0) { + win32_set_quit(true); + } + break; + + } + + return DefWindowProc(hwnd, msg, wparam, lparam); +} + + +/** + * Create the main window class. + */ +nserror +nsws_create_main_class(HINSTANCE hinstance) { + nserror ret = NSERROR_OK; + WNDCLASSEX w; + + /* main window */ + 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(hinstance, MAKEINTRESOURCE(IDR_NETSURF_ICON)); + w.hCursor = NULL; + w.hbrBackground = (HBRUSH)(COLOR_MENU + 1); + w.lpszMenuName = NULL; + w.lpszClassName = windowclassname_main; + w.hIconSm = LoadIcon(hinstance, MAKEINTRESOURCE(IDR_NETSURF_ICON)); + + if (RegisterClassEx(&w) == 0) { + win_perror("DrawableClass"); + ret = NSERROR_INIT_FAILED; + } + + hInstance = hinstance; + + return ret; +} + + + + + + +/** + * create a new gui_window to contain a browser_window. + * + * \param bw the browser_window to connect to the new gui_window + * \param existing An existing window. + * \param flags The flags controlling the construction. + * \return The new win32 gui window or NULL on error. + */ +static struct gui_window * +win32_window_create(struct browser_window *bw, + struct gui_window *existing, + gui_window_create_flags flags) +{ + struct gui_window *gw; + + LOG("Creating gui window for browser window %p", bw); + + gw = calloc(1, sizeof(struct gui_window)); + + if (gw == NULL) { + return NULL; + } + + /* connect gui window to browser window */ + gw->bw = bw; + + gw->width = 800; + gw->height = 600; + gw->scale = 1.0; + gw->toolbuttonsize = 24; + gw->requestscrollx = 0; + gw->requestscrolly = 0; + gw->localhistory = NULL; + + gw->mouse = malloc(sizeof(struct browser_mouse)); + if (gw->mouse == NULL) { + free(gw); + LOG("Unable to allocate mouse state"); + return NULL; + } + gw->mouse->gui = gw; + gw->mouse->state = 0; + gw->mouse->pressed_x = 0; + gw->mouse->pressed_y = 0; + + /* add window to list */ + if (window_list != NULL) + window_list->prev = gw; + gw->next = window_list; + window_list = gw; + + gw->main = nsws_window_create(gw); + gw->toolbar = nsws_window_create_toolbar(gw, gw->main); + gw->statusbar = nsws_window_create_statusbar(gw); + gw->drawingarea = nsws_window_create_drawable(hInstance, gw->main, gw); + + LOG("new window: main:%p toolbar:%p statusbar %p drawingarea %p", gw->main, gw->toolbar, gw->statusbar, gw->drawingarea); + + font_hwnd = gw->drawingarea; + open_windows++; + ShowWindow(gw->main, SW_SHOWNORMAL); + + return gw; +} + + +/** + * window cleanup code + */ +static void win32_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; +} + + + + +static void +win32_window_update_box(struct gui_window *gw, const struct rect *rect) +{ + /* LOG("gw:%p %f,%f %f,%f", gw, data->redraw.x, data->redraw.y, data->redraw.width, data->redraw.height); */ + + if (gw == NULL) + return; + + RECT redrawrect; + + redrawrect.left = (long)rect->x0 - (gw->scrollx / gw->scale); + redrawrect.top = (long)rect->y0 - (gw->scrolly / gw->scale); + redrawrect.right =(long)rect->x1; + redrawrect.bottom = (long)rect->y1; + + RedrawWindow(gw->drawingarea, &redrawrect, NULL, + RDW_INVALIDATE | RDW_NOERASE); + +} + + + + + +static void win32_window_get_dimensions(struct gui_window *gw, int *width, int *height, + bool scaled) +{ + if (gw == NULL) + return; + + LOG("get dimensions %p w=%d h=%d", gw, gw->width, gw->height); + + *width = gw->width; + *height = gw->height; +} + +static void win32_window_update_extent(struct gui_window *w) +{ + +} + +/** + * callback from core to reformat a window. + * + * \param gw The win32 gui window to reformat. + */ +static void win32_window_reformat(struct gui_window *gw) +{ + if (gw != NULL) { + browser_window_reformat(gw->bw, false, gw->width, gw->height); + } +} + + +/** + * set window title + * + * \param w the Windows gui window. + * \param title to set on window + */ +static void win32_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) { + win32_warning("NoMemory", 0); + return; + } + strcpy(fulltitle, title); + strcat(fulltitle, " - NetSurf"); + SendMessage(w->main, WM_SETTEXT, 0, (LPARAM)fulltitle); + free(fulltitle); +} + + +static nserror win32_window_set_url(struct gui_window *w, nsurl *url) +{ + SendMessage(w->urlbar, WM_SETTEXT, 0, (LPARAM) nsurl_access(url)); + + return NSERROR_OK; +} + + +/** + * set the status bar message + */ +static void win32_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 + */ +static void win32_window_set_pointer(struct gui_window *w, + gui_pointer_shape shape) +{ + SetCursor(nsws_get_pointer(shape)); +} + + +/** + * place caret in window + */ +static void win32_window_place_caret(struct gui_window *w, int x, int y, + int height, const struct rect *clip) +{ + if (w == NULL) + return; + CreateCaret(w->drawingarea, (HBITMAP)NULL, 1, height * w->scale); + SetCaretPos(x * w->scale - w->scrollx, + y * w->scale - w->scrolly); + ShowCaret(w->drawingarea); +} + +/** + * clear window caret + */ +static void win32_window_remove_caret(struct gui_window *w) +{ + if (w == NULL) + return; + HideCaret(w->drawingarea); +} + + + + +static void win32_window_start_throbber(struct gui_window *w) +{ + if (w == NULL) + return; + nsws_window_update_forward_back(w); + + if (w->mainmenu != NULL) { + EnableMenuItem(w->mainmenu, IDM_NAV_STOP, MF_ENABLED); + EnableMenuItem(w->mainmenu, IDM_NAV_RELOAD, MF_GRAYED); + } + if (w->rclick != NULL) { + EnableMenuItem(w->rclick, IDM_NAV_STOP, MF_ENABLED); + EnableMenuItem(w->rclick, IDM_NAV_RELOAD, MF_GRAYED); + } + if (w->toolbar != NULL) { + SendMessage(w->toolbar, TB_SETSTATE, (WPARAM) IDM_NAV_STOP, + MAKELONG(TBSTATE_ENABLED, 0)); + SendMessage(w->toolbar, TB_SETSTATE, + (WPARAM) IDM_NAV_RELOAD, + MAKELONG(TBSTATE_INDETERMINATE, 0)); + } + w->throbbing = true; + Animate_Play(w->throbber, 0, -1, -1); +} + + + +static void win32_window_stop_throbber(struct gui_window *w) +{ + if (w == NULL) + return; + + nsws_window_update_forward_back(w); + if (w->mainmenu != NULL) { + EnableMenuItem(w->mainmenu, IDM_NAV_STOP, MF_GRAYED); + EnableMenuItem(w->mainmenu, IDM_NAV_RELOAD, MF_ENABLED); + } + + if (w->rclick != NULL) { + EnableMenuItem(w->rclick, IDM_NAV_STOP, MF_GRAYED); + EnableMenuItem(w->rclick, IDM_NAV_RELOAD, MF_ENABLED); + } + + if (w->toolbar != NULL) { + SendMessage(w->toolbar, TB_SETSTATE, (WPARAM) IDM_NAV_STOP, + MAKELONG(TBSTATE_INDETERMINATE, 0)); + SendMessage(w->toolbar, TB_SETSTATE, + (WPARAM) IDM_NAV_RELOAD, + MAKELONG(TBSTATE_ENABLED, 0)); + } + + w->throbbing = false; + Animate_Stop(w->throbber); + Animate_Seek(w->throbber, 0); +} + +static struct gui_window_table window_table = { + .create = win32_window_create, + .destroy = win32_window_destroy, + .redraw = win32_window_redraw_window, + .update = win32_window_update_box, + .get_scroll = win32_window_get_scroll, + .set_scroll = win32_window_set_scroll, + .get_dimensions = win32_window_get_dimensions, + .update_extent = win32_window_update_extent, + .reformat = win32_window_reformat, + + .set_title = win32_window_set_title, + .set_url = win32_window_set_url, + .set_status = win32_window_set_status, + .set_pointer = win32_window_set_pointer, + .place_caret = win32_window_place_caret, + .remove_caret = win32_window_remove_caret, + .start_throbber = win32_window_start_throbber, + .stop_throbber = win32_window_stop_throbber, +}; + +struct gui_window_table *win32_window_table = &window_table; + +/* exported interface documented in windows/window.h */ +struct gui_window *nsws_get_gui_window(HWND hwnd) +{ + struct gui_window *gw = NULL; + HWND phwnd = hwnd; + + /* scan the window hierachy for gui window */ + while (phwnd != NULL) { + gw = GetProp(phwnd, TEXT("GuiWnd")); + if (gw != NULL) + break; + phwnd = GetParent(phwnd); + } + + if (gw == NULL) { + /* try again looking for owner windows instead */ + phwnd = hwnd; + while (phwnd != NULL) { + gw = GetProp(phwnd, TEXT("GuiWnd")); + if (gw != NULL) + break; + phwnd = GetWindow(phwnd, GW_OWNER); + } + } + + return gw; +} + + +/* exported interface documented in windows/window.h */ +bool nsws_window_go(HWND hwnd, const char *urltxt) +{ + struct gui_window *gw; + nsurl *url; + + gw = nsws_get_gui_window(hwnd); + if (gw == NULL) + return false; + + if (nsurl_create(urltxt, &url) != NSERROR_OK) { + win32_warning("NoMemory", 0); + } else { + browser_window_navigate(gw->bw, + url, + NULL, + BW_NAVIGATE_HISTORY, + NULL, + NULL, + NULL); + nsurl_unref(url); + } + + return true; +} + + +/* exported interface documented in windows/window.h */ +HWND gui_window_main_window(struct gui_window *w) +{ + if (w == NULL) + return NULL; + return w->main; +} + + +/* exported interface documented in windows/window.h */ +struct nsws_localhistory *gui_window_localhistory(struct gui_window *w) +{ + if (w == NULL) + return NULL; + return w->localhistory; +} diff --git a/frontends/windows/window.h b/frontends/windows/window.h new file mode 100644 index 000000000..ec54287f4 --- /dev/null +++ b/frontends/windows/window.h @@ -0,0 +1,109 @@ +/* + * Copyright 2011 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_WINDOWS_WINDOW_H_ +#define _NETSURF_WINDOWS_WINDOW_H_ + +/** The window operation function table for win32 */ +extern struct gui_window_table *win32_window_table; + +#include "desktop/mouse.h" + +struct browser_mouse { + struct gui_window *gui; + struct box *box; + + double pressed_x; + double pressed_y; + bool waiting; + browser_mouse_state state; +}; + +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 */ + struct nsws_localhistory *localhistory; /**< handle to local history window */ + int width; /**< width of window */ + int height; /**< height of drawing area */ + + int toolbuttonc; /**< number of toolbar buttons */ + int toolbuttonsize; /**< width, height of buttons */ + bool throbbing; /**< whether currently throbbing */ + + 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. */ + int requestscrollx, requestscrolly; /**< scolling requested. */ + struct gui_window *next, *prev; /**< global linked list */ +}; + + +/** + * Obtain gui window structure from window handle. + * + * \param hwnd The window handle. + * \return The gui window associated with the window handle. + */ +struct gui_window *nsws_get_gui_window(HWND hwnd); + +/** + * Cause a browser window to navigate to a url + * + * \param hwnd The win32 handle to the browser window or one of its decendants. + * \param urltxt The URL to navigate to. + */ +bool nsws_window_go(HWND hwnd, const char *urltxt); + +void win32_window_set_scroll(struct gui_window *w, int sx, int sy); + +nserror nsws_create_main_class(HINSTANCE hinstance); + +/** + * Get the main win32 window handle from a gui window + */ +HWND gui_window_main_window(struct gui_window *); + + +/** + * Get the localhistory win32 window handle from a gui window + */ +struct nsws_localhistory *gui_window_localhistory(struct gui_window *); + + +#endif /* _NETSURF_WINDOWS_WINDOW_H_ */ -- cgit v1.2.3