summaryrefslogtreecommitdiff
path: root/frontends/framebuffer
diff options
context:
space:
mode:
Diffstat (limited to 'frontends/framebuffer')
-rw-r--r--frontends/framebuffer/Makefile11
-rw-r--r--frontends/framebuffer/bitmap.c21
-rw-r--r--frontends/framebuffer/clipboard.c4
-rw-r--r--frontends/framebuffer/corewindow.c262
-rw-r--r--frontends/framebuffer/corewindow.h107
-rw-r--r--frontends/framebuffer/fbtk.h6
-rw-r--r--frontends/framebuffer/fbtk/event.c4
-rw-r--r--frontends/framebuffer/fbtk/fbtk.c46
-rw-r--r--frontends/framebuffer/fbtk/scroll.c4
-rw-r--r--frontends/framebuffer/fbtk/text.c46
-rw-r--r--frontends/framebuffer/fetch.c2
-rw-r--r--frontends/framebuffer/font_freetype.c21
-rw-r--r--frontends/framebuffer/font_internal.c6
-rw-r--r--frontends/framebuffer/framebuffer.c612
-rw-r--r--frontends/framebuffer/gui.c143
-rw-r--r--frontends/framebuffer/gui.h18
-rw-r--r--frontends/framebuffer/local_history.c248
-rw-r--r--frontends/framebuffer/local_history.h49
-rw-r--r--frontends/framebuffer/localhistory.c144
l---------frontends/framebuffer/res/Messages1
l---------frontends/framebuffer/res/adblock.css2
l---------frontends/framebuffer/res/credits.html2
l---------frontends/framebuffer/res/default.css2
l---------frontends/framebuffer/res/internal.css2
l---------frontends/framebuffer/res/licence.html2
l---------frontends/framebuffer/res/maps.html2
l---------frontends/framebuffer/res/netsurf.png2
l---------frontends/framebuffer/res/quirks.css2
l---------frontends/framebuffer/res/welcome.html2
-rw-r--r--frontends/framebuffer/schedule.c23
30 files changed, 1281 insertions, 515 deletions
diff --git a/frontends/framebuffer/Makefile b/frontends/framebuffer/Makefile
index 6d2acb079..bdedd903b 100644
--- a/frontends/framebuffer/Makefile
+++ b/frontends/framebuffer/Makefile
@@ -130,10 +130,12 @@ define convert_font
S_FONTS += $(2)
-$(2): $(1) $(TOOLROOT)/convert_font
+$(2) $(3): $(1) $(TOOLROOT)/convert_font
$(VQ)echo " FONT: $(1) ($(4))"
$(Q)$(TOOLROOT)/convert_font -H $(3) $(1) $(2)
+frontends/framebuffer/font_internal.c: $(2)
+
endef
S_FONTS :=
@@ -146,7 +148,7 @@ $(eval $(foreach V,$(filter FB_FONT_$(NETSURF_FB_FONTLIB)_%,$(.VARIABLES)),$(cal
# S_FRONTEND are sources purely for the framebuffer build
S_FRONTEND := gui.c framebuffer.c schedule.c bitmap.c fetch.c \
- findfile.c localhistory.c clipboard.c
+ findfile.c corewindow.c local_history.c clipboard.c
# toolkit sources
S_FRAMEBUFFER_FBTK := fbtk.c event.c fill.c bitmap.c user.c window.c \
@@ -168,14 +170,15 @@ EXETARGET := nsfb
NETSURF_FRAMEBUFFER_RESOURCE_LIST := adblock.css credits.html \
default.css internal.css licence.html \
- netsurf.png quirks.css welcome.html maps.html Messages
+ netsurf.png quirks.css welcome.html maps.html
install-framebuffer:
$(Q)$(MKDIR) -p $(DESTDIR)$(NETSURF_FRAMEBUFFER_BIN)
$(Q)$(MKDIR) -p $(DESTDIR)$(NETSURF_FRAMEBUFFER_RESOURCES)
$(Q)cp -v $(EXETARGET) $(DESTDIR)/$(NETSURF_FRAMEBUFFER_BIN)netsurf-fb
$(Q)for F in $(NETSURF_FRAMEBUFFER_RESOURCE_LIST); do cp -vL $(FRONTEND_RESOURCES_DIR)/$$F $(DESTDIR)/$(NETSURF_FRAMEBUFFER_RESOURCES); done
- $(Q)$(SPLIT_MESSAGES) -l en -p fb -f messages resources/FatMessages | gzip -9n > $(DESTDIR)$(NETSURF_FRAMEBUFFER_RESOURCES)messages
+ $(Q)$(RM) $(DESTDIR)$(NETSURF_FRAMEBUFFER_RESOURCES)messages
+ $(Q)$(SPLIT_MESSAGES) -l en -p fb -f messages -o $(DESTDIR)$(NETSURF_FRAMEBUFFER_RESOURCES)messages -z resources/FatMessages
# ----------------------------------------------------------------------------
# Package target
diff --git a/frontends/framebuffer/bitmap.c b/frontends/framebuffer/bitmap.c
index 027e0122b..1fc9f46a2 100644
--- a/frontends/framebuffer/bitmap.c
+++ b/frontends/framebuffer/bitmap.c
@@ -51,7 +51,8 @@ static void *bitmap_create(int width, int height, unsigned int state)
{
nsfb_t *bm;
- LOG("width %d, height %d, state %u", width, height, state);
+ NSLOG(netsurf, INFO, "width %d, height %d, state %u", width, height,
+ state);
bm = nsfb_new(NSFB_SURFACE_RAM);
if (bm == NULL) {
@@ -69,7 +70,7 @@ static void *bitmap_create(int width, int height, unsigned int state)
return NULL;
}
- LOG("bitmap %p", bm);
+ NSLOG(netsurf, INFO, "bitmap %p", bm);
return bm;
}
@@ -197,11 +198,11 @@ static bool bitmap_test_opaque(void *bitmap)
while (tst-- > 0) {
if (bmpptr[(tst << 2) + 3] != 0xff) {
- LOG("bitmap %p has transparency", bm);
+ NSLOG(netsurf, INFO, "bitmap %p has transparency", bm);
return false;
}
}
- LOG("bitmap %p is opaque", bm);
+ NSLOG(netsurf, INFO, "bitmap %p is opaque", bm);
return true;
}
@@ -282,14 +283,14 @@ bitmap_render(struct bitmap *bitmap,
nsfb_get_geometry(tbm, &width, &height, NULL);
- LOG("width %d, height %d", width, height);
+ NSLOG(netsurf, INFO, "width %d, height %d", width, height);
/* Calculate size of buffer to render the content into */
- /* We get the width from the content width, unless it exceeds 1024,
- * in which case we use 1024. This means we never create excessively
- * large render buffers for huge contents, which would eat memory and
- * cripple performance. */
- cwidth = min(content_get_width(content), 1024);
+ /* We get the width from the largest of the bitmap width and the content
+ * width, unless it exceeds 1024, in which case we use 1024. This means
+ * we never create excessively large render buffers for huge contents,
+ * which would eat memory and cripple performance. */
+ cwidth = max(width, min(content_get_width(content), 1024));
/* The height is set in proportion with the width, according to the
* aspect ratio of the required thumbnail. */
cheight = ((cwidth * height) + (width / 2)) / width;
diff --git a/frontends/framebuffer/clipboard.c b/frontends/framebuffer/clipboard.c
index 1254c36f3..20a00e038 100644
--- a/frontends/framebuffer/clipboard.c
+++ b/frontends/framebuffer/clipboard.c
@@ -53,8 +53,8 @@ static void gui_get_clipboard(char **buffer, size_t *length)
if (gui_clipboard.length > 0) {
assert(gui_clipboard.buffer != NULL);
- LOG("Pasting %zd bytes: \"%s\"\n",
- gui_clipboard.length, gui_clipboard.buffer);
+ NSLOG(netsurf, INFO, "Pasting %zd bytes: \"%s\"\n",
+ gui_clipboard.length, gui_clipboard.buffer);
*buffer = malloc(gui_clipboard.length);
diff --git a/frontends/framebuffer/corewindow.c b/frontends/framebuffer/corewindow.c
new file mode 100644
index 000000000..93f88ff61
--- /dev/null
+++ b/frontends/framebuffer/corewindow.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2017 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * framebuffer generic core window interface.
+ *
+ * Provides interface for core renderers to the framebufefr toolkit
+ * drawable area.
+ *
+ * This module is an object that must be encapsulated. Client users
+ * should embed a struct fb_corewindow at the beginning of their
+ * context for this display surface, fill in relevant data and then
+ * call fb_corewindow_init()
+ *
+ * The fb core window structure requires the callback for draw, key and
+ * mouse operations.
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include <libnsfb.h>
+#include <libnsfb_plot.h>
+#include <libnsfb_event.h>
+
+#include "utils/log.h"
+#include "utils/utils.h"
+#include "utils/messages.h"
+#include "utils/utf8.h"
+#include "utils/nsoption.h"
+#include "netsurf/keypress.h"
+#include "netsurf/mouse.h"
+#include "netsurf/plot_style.h"
+
+#include "framebuffer/gui.h"
+#include "framebuffer/fbtk.h"
+#include "framebuffer/corewindow.h"
+
+
+/* toolkit event handlers that do generic things and call internal callbacks */
+
+
+static int
+fb_cw_mouse_press_event(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ struct fb_corewindow *fb_cw = (struct fb_corewindow *)cbi->context;
+ browser_mouse_state state;
+
+ /** \todo frambuffer corewindow mouse event handling needs improving */
+ if (cbi->event->type != NSFB_EVENT_KEY_UP) {
+ state = BROWSER_MOUSE_HOVER;
+ } else {
+ state = BROWSER_MOUSE_PRESS_1;
+ }
+
+ fb_cw->mouse(fb_cw, state, cbi->x, cbi->y);
+
+ return 1;
+}
+
+/*
+static bool
+fb_cw_input_event(toolkit_widget *widget, void *ctx)
+{
+ struct fb_corewindow *fb_cw = (struct fb_corewindow *)ctx;
+
+ fb_cw->key(fb_cw, keycode);
+
+ return true;
+}
+*/
+
+/**
+ * handler for toolkit window redraw event
+ */
+static int fb_cw_draw_event(fbtk_widget_t *widget, fbtk_callback_info *cbi)
+{
+ struct fb_corewindow *fb_cw;
+ nsfb_bbox_t rbox;
+ struct rect clip;
+
+ fb_cw = (struct fb_corewindow *)cbi->context;
+
+ rbox.x0 = fbtk_get_absx(widget);
+ rbox.y0 = fbtk_get_absy(widget);
+
+ rbox.x1 = rbox.x0 + fbtk_get_width(widget);
+ rbox.y1 = rbox.y0 + fbtk_get_height(widget);
+
+ nsfb_claim(fbtk_get_nsfb(widget), &rbox);
+
+ clip.x0 = fb_cw->scrollx;
+ clip.y0 = fb_cw->scrolly;
+ clip.x1 = fbtk_get_width(widget) + fb_cw->scrollx;
+ clip.y1 = fbtk_get_height(widget) + fb_cw->scrolly;
+
+ fb_cw->draw(fb_cw, &clip);
+
+ nsfb_update(fbtk_get_nsfb(widget), &rbox);
+
+ return 0;
+}
+
+
+/**
+ * callback from core to request a redraw
+ */
+static nserror
+fb_cw_invalidate(struct core_window *cw, const struct rect *r)
+{
+/* struct fb_corewindow *fb_cw = (struct fb_corewindow *)cw;
+
+ toolkit_widget_queue_draw_area(fb_cw->widget,
+ r->x0, r->y0,
+ r->x1 - r->x0, r->y1 - r->y0);
+*/
+ return NSERROR_OK;
+}
+
+
+static void
+fb_cw_update_size(struct core_window *cw, int width, int height)
+{
+/* struct fb_corewindow *fb_cw = (struct fb_corewindow *)cw;
+
+ toolkit_widget_set_size_request(FB_WIDGET(fb_cw->drawing_area),
+ width, height);
+*/
+}
+
+
+static void
+fb_cw_scroll_visible(struct core_window *cw, const struct rect *r)
+{
+/* struct fb_corewindow *fb_cw = (struct fb_corewindow *)cw;
+
+ toolkit_scroll_widget(fb_cw->widget, r);
+*/
+}
+
+
+static void
+fb_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
+{
+ struct fb_corewindow *fb_cw = (struct fb_corewindow *)cw;
+
+ *width = fbtk_get_width(fb_cw->drawable);
+ *height = fbtk_get_height(fb_cw->drawable);
+}
+
+
+static void
+fb_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
+{
+ struct fb_corewindow *fb_cw = (struct fb_corewindow *)cw;
+ fb_cw->drag_status = ds;
+}
+
+
+struct core_window_callback_table fb_cw_cb_table = {
+ .invalidate = fb_cw_invalidate,
+ .update_size = fb_cw_update_size,
+ .scroll_visible = fb_cw_scroll_visible,
+ .get_window_dimensions = fb_cw_get_window_dimensions,
+ .drag_status = fb_cw_drag_status
+};
+
+/* exported function documented fb/corewindow.h */
+nserror fb_corewindow_init(fbtk_widget_t *parent, struct fb_corewindow *fb_cw)
+{
+ int furniture_width;
+
+ furniture_width = nsoption_int(fb_furniture_size);
+
+ /* setup the core window callback table */
+ fb_cw->cb_table = &fb_cw_cb_table;
+ fb_cw->drag_status = CORE_WINDOW_DRAG_NONE;
+
+ /* container window */
+ fb_cw->wnd = fbtk_create_window(parent, 0, 0, 0, 0, 0);
+
+ fb_cw->drawable = fbtk_create_user(fb_cw->wnd,
+ 0, 0,
+ -furniture_width, -furniture_width,
+ fb_cw);
+
+ fbtk_set_handler(fb_cw->drawable,
+ FBTK_CBT_REDRAW,
+ fb_cw_draw_event,
+ fb_cw);
+
+ fbtk_set_handler(fb_cw->drawable,
+ FBTK_CBT_CLICK,
+ fb_cw_mouse_press_event,
+ fb_cw);
+/*
+ fbtk_set_handler(fb_cw->drawable,
+ FBTK_CBT_INPUT,
+ fb_cw_input_event,
+ fb_cw);
+
+ fbtk_set_handler(fb_cw->drawable,
+ FBTK_CBT_POINTERMOVE,
+ fb_cw_move_event,
+ fb_cw);
+*/
+
+ /* create horizontal scrollbar */
+ fb_cw->hscroll = fbtk_create_hscroll(fb_cw->wnd,
+ 0,
+ fbtk_get_height(fb_cw->wnd) - furniture_width,
+ fbtk_get_width(fb_cw->wnd) - furniture_width,
+ furniture_width,
+ FB_SCROLL_COLOUR,
+ FB_FRAME_COLOUR,
+ NULL,
+ NULL);
+
+ fb_cw->vscroll = fbtk_create_vscroll(fb_cw->wnd,
+ fbtk_get_width(fb_cw->wnd) - furniture_width,
+ 0,
+ furniture_width,
+ fbtk_get_height(fb_cw->wnd) - furniture_width,
+ FB_SCROLL_COLOUR,
+ FB_FRAME_COLOUR,
+ NULL,
+ NULL);
+
+ fbtk_create_fill(fb_cw->wnd,
+ fbtk_get_width(fb_cw->wnd) - furniture_width,
+ fbtk_get_height(fb_cw->wnd) - furniture_width,
+ furniture_width,
+ furniture_width,
+ FB_FRAME_COLOUR);
+
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in fb/corewindow.h */
+nserror fb_corewindow_fini(struct fb_corewindow *fb_cw)
+{
+ return NSERROR_OK;
+}
diff --git a/frontends/framebuffer/corewindow.h b/frontends/framebuffer/corewindow.h
new file mode 100644
index 000000000..5546c09b6
--- /dev/null
+++ b/frontends/framebuffer/corewindow.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2017 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef FB_COREWINDOW_H
+#define FB_COREWINDOW_H
+
+#include "netsurf/core_window.h"
+
+/**
+ * fb core window state
+ */
+struct fb_corewindow {
+
+ /**
+ * framebuffer toolkit window.
+ */
+ struct fbtk_widget_s *wnd;
+ /**
+ * framebuffer toolkit horizontal scrollbar.
+ */
+ struct fbtk_widget_s *hscroll;
+ /**
+ * framebuffer toolkit vertical scrollbar.
+ */
+ struct fbtk_widget_s *vscroll;
+ /**
+ * framebuffer toolkit user drawable widget.
+ */
+ struct fbtk_widget_s *drawable;
+
+ int scrollx, scrolly; /**< scroll offsets. */
+
+
+ /** drag status set by core */
+ core_window_drag_status drag_status;
+
+ /** table of callbacks for core window operations */
+ struct core_window_callback_table *cb_table;
+
+ /**
+ * callback to draw on drawable area of fb core window
+ *
+ * \param fb_cw The fb core window structure.
+ * \param r The rectangle of the window that needs updating.
+ * \return NSERROR_OK on success otherwise apropriate error code
+ */
+ nserror (*draw)(struct fb_corewindow *fb_cw, struct rect *r);
+
+ /**
+ * callback for keypress on fb core window
+ *
+ * \param fb_cw The fb core window structure.
+ * \param nskey The netsurf key code.
+ * \return NSERROR_OK if key processed,
+ * NSERROR_NOT_IMPLEMENTED if key not processed
+ * otherwise apropriate error code
+ */
+ nserror (*key)(struct fb_corewindow *fb_cw, uint32_t nskey);
+
+ /**
+ * callback for mouse event on fb core window
+ *
+ * \param fb_cw The fb core window structure.
+ * \param mouse_state mouse state
+ * \param x location of event
+ * \param y location of event
+ * \return NSERROR_OK on sucess otherwise apropriate error code.
+ */
+ nserror (*mouse)(struct fb_corewindow *fb_cw, browser_mouse_state mouse_state, int x, int y);
+};
+
+
+/**
+ * initialise elements of fb core window.
+ *
+ * As a pre-requisite the draw, key and mouse callbacks must be defined
+ *
+ * \param fb_cw A fb core window structure to initialise
+ * \return NSERROR_OK on successful initialisation otherwise error code.
+ */
+nserror fb_corewindow_init(fbtk_widget_t *parent, struct fb_corewindow *fb_cw);
+
+
+/**
+ * finalise elements of fb core window.
+ *
+ * \param fb_cw A fb core window structure to initialise
+ * \return NSERROR_OK on successful finalisation otherwise error code.
+ */
+nserror fb_corewindow_fini(struct fb_corewindow *fb_cw);
+
+#endif
diff --git a/frontends/framebuffer/fbtk.h b/frontends/framebuffer/fbtk.h
index 3cc326cef..86bdc864b 100644
--- a/frontends/framebuffer/fbtk.h
+++ b/frontends/framebuffer/fbtk.h
@@ -21,12 +21,6 @@
#include "netsurf/types.h"
-#ifdef FBTK_LOGGING
-#define FBTK_LOG(x) LOG(x)
-#else
-#define FBTK_LOG(x)
-#endif
-
#define FB_SCROLL_COLOUR 0xFFAAAAAA
#define FB_FRAME_COLOUR 0xFFDDDDDD
#define FB_COLOUR_BLACK 0xFF000000
diff --git a/frontends/framebuffer/fbtk/event.c b/frontends/framebuffer/fbtk/event.c
index a48e63809..84c6c3791 100644
--- a/frontends/framebuffer/fbtk/event.c
+++ b/frontends/framebuffer/fbtk/event.c
@@ -51,7 +51,7 @@ fbtk_input(fbtk_widget_t *root, nsfb_event_t *event)
/* obtain widget with input focus */
input = root->u.root.input;
if (input == NULL) {
- LOG("No widget has input focus.");
+ NSLOG(netsurf, INFO, "No widget has input focus.");
return; /* no widget with input */
}
@@ -84,7 +84,7 @@ fbtk_click(fbtk_widget_t *widget, nsfb_event_t *event)
x = fbtk_get_absx(clicked);
y = fbtk_get_absy(clicked);
- LOG("clicked %p at %d,%d", clicked, x, y);
+ NSLOG(netsurf, INFO, "clicked %p at %d,%d", clicked, x, y);
/* post the click */
fbtk_post_callback(clicked, FBTK_CBT_CLICK, event, cloc.x0 - x, cloc.y0 - y);
diff --git a/frontends/framebuffer/fbtk/fbtk.c b/frontends/framebuffer/fbtk/fbtk.c
index c63a6d8c9..91f6e2570 100644
--- a/frontends/framebuffer/fbtk/fbtk.c
+++ b/frontends/framebuffer/fbtk/fbtk.c
@@ -53,7 +53,7 @@ dump_tk_tree(fbtk_widget_t *widget)
int indent = 0;
while (widget != NULL) {
- LOG("%*s%p", indent, "", widget);
+ NSLOG(fbtk, DEBUG, "%*s%p", indent, "", widget);
if (widget->first_child != NULL) {
widget = widget->first_child;
indent += 6;
@@ -100,9 +100,13 @@ fbtk_request_redraw(fbtk_widget_t *widget)
widget->redraw.width = widget->width;
widget->redraw.height = widget->height;
-#ifdef FBTK_LOGGING
- LOG("redrawing %p %d,%d %d,%d", widget, widget->redraw.x, widget->redraw.y, widget->redraw.width, widget->redraw.height);
-#endif
+ NSLOG(fbtk, DEBUG,
+ "redrawing %p %d,%d %d,%d",
+ widget,
+ widget->redraw.x,
+ widget->redraw.y,
+ widget->redraw.width,
+ widget->redraw.height);
cwidget = widget->last_child;
while (cwidget != NULL) {
@@ -122,7 +126,7 @@ fbtk_request_redraw(fbtk_widget_t *widget)
int
fbtk_set_mapping(fbtk_widget_t *widget, bool map)
{
- LOG("setting mapping on %p to %d", widget, map);
+ NSLOG(netsurf, INFO, "setting mapping on %p to %d", widget, map);
widget->mapped = map;
if (map) {
fbtk_request_redraw(widget);
@@ -132,9 +136,11 @@ fbtk_set_mapping(fbtk_widget_t *widget, bool map)
return 0;
}
-/** swap the widget given with the next sibling.
- *
+
+/**
* Swap a sibling widget with the next deepest in the hierachy
+ *
+ * \param lw The widget to swap
*/
static void
swap_siblings(fbtk_widget_t *lw)
@@ -145,7 +151,7 @@ swap_siblings(fbtk_widget_t *lw)
assert(rw != NULL);
- LOG("Swapping %p with %p", lw, rw);
+ NSLOG(netsurf, INFO, "Swapping %p with %p", lw, rw);
before = lw->prev;
after = rw->next;
@@ -401,7 +407,6 @@ fbtk_set_ptr(fbtk_widget_t *widget, fbtk_callback_info *cbi)
}
-
/* internally exported function documented in widget.h */
fbtk_widget_t *
fbtk_get_root_widget(fbtk_widget_t *widget)
@@ -411,7 +416,8 @@ fbtk_get_root_widget(fbtk_widget_t *widget)
/* check root widget was found */
if (widget->type != FB_WIDGET_TYPE_ROOT) {
- LOG("Widget with null parent that is not the root widget!");
+ NSLOG(netsurf, INFO,
+ "Widget with null parent that is not the root widget!");
return NULL;
}
@@ -433,6 +439,7 @@ fbtk_get_absx(fbtk_widget_t *widget)
return x;
}
+
/* exported function documented in fbtk.h */
int
fbtk_get_absy(fbtk_widget_t *widget)
@@ -447,6 +454,7 @@ fbtk_get_absy(fbtk_widget_t *widget)
return y;
}
+
/* exported function documented in fbtk.h */
int
fbtk_get_height(fbtk_widget_t *widget)
@@ -551,9 +559,7 @@ fbtk_widget_new(fbtk_widget_t *parent,
if (neww == NULL)
return NULL;
-#ifdef FBTK_LOGGING
- LOG("creating %p %d,%d %d,%d", neww, x, y, width, height);
-#endif
+ NSLOG(fbtk, DEBUG, "creating %p %d,%d %d,%d", neww, x, y, width, height);
/* make new window fit inside parent */
if (width == 0) {
@@ -574,9 +580,8 @@ fbtk_widget_new(fbtk_widget_t *parent,
height = parent->height - y;
}
-#ifdef FBTK_LOGGING
- LOG("using %p %d,%d %d,%d", neww, x, y, width, height);
-#endif
+ NSLOG(fbtk, DEBUG, "using %p %d,%d %d,%d", neww, x, y, width, height);
+
/* set values */
neww->type = type;
neww->x = x;
@@ -634,9 +639,12 @@ do_redraw(nsfb_t *nsfb, fbtk_widget_t *widget)
plot_ctx.x1 = plot_ctx.x0 + widget->redraw.width;
plot_ctx.y1 = plot_ctx.y0 + widget->redraw.height;
-#ifdef FBTK_LOGGING
- LOG("clipping %p %d,%d %d,%d", widget, plot_ctx.x0, plot_ctx.y0, plot_ctx.x1, plot_ctx.y1);
-#endif
+ NSLOG(fbtk, DEBUG,
+ "clipping %p %d,%d %d,%d",
+ widget,
+ plot_ctx.x0, plot_ctx.y0,
+ plot_ctx.x1, plot_ctx.y1);
+
if (nsfb_plot_set_clip(nsfb, &plot_ctx) == true) {
fbtk_post_callback(widget, FBTK_CBT_REDRAW);
}
diff --git a/frontends/framebuffer/fbtk/scroll.c b/frontends/framebuffer/fbtk/scroll.c
index cc98fb2dd..b056ac81f 100644
--- a/frontends/framebuffer/fbtk/scroll.c
+++ b/frontends/framebuffer/fbtk/scroll.c
@@ -334,7 +334,7 @@ hscroll_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi)
hpos = 0;
}
- LOG("hscroll %d", hscroll);
+ NSLOG(netsurf, INFO, "hscroll %d", hscroll);
rect.x0 = bbox.x0 + 3 + hpos;
rect.y0 = bbox.y0 + 5;
@@ -362,7 +362,7 @@ hscrolll_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
newpos = scrollw->u.scroll.minimum;
if (newpos == scrollw->u.scroll.position) {
- LOG("horiz scroll was the same %d", newpos);
+ NSLOG(netsurf, INFO, "horiz scroll was the same %d", newpos);
return 0;
}
diff --git a/frontends/framebuffer/fbtk/text.c b/frontends/framebuffer/fbtk/text.c
index 00dcba491..9c96dcef4 100644
--- a/frontends/framebuffer/fbtk/text.c
+++ b/frontends/framebuffer/fbtk/text.c
@@ -71,7 +71,7 @@ fb_text_font_style(fbtk_widget_t *widget, int *font_height, int *padding,
#endif
font_style->family = PLOT_FONT_FAMILY_SANS_SERIF;
- font_style->size = px_to_pt(*font_height * FONT_SIZE_SCALE);
+ font_style->size = px_to_pt(*font_height * PLOT_STYLE_SCALE);
font_style->weight = 400;
font_style->flags = FONTF_NONE;
font_style->background = widget->bg;
@@ -98,6 +98,11 @@ fb_redraw_text(fbtk_widget_t *widget, fbtk_callback_info *cbi )
int padding;
int scroll = 0;
bool caret = false;
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &fb_plotters
+ };
fb_text_font_style(widget, &fh, &padding, &font_style);
@@ -142,8 +147,11 @@ fb_redraw_text(fbtk_widget_t *widget, fbtk_callback_info *cbi )
}
/* Call the fb text plotting, baseline is 3/4 down the font */
- fb_plotters.text(x, y, widget->u.text.text,
- widget->u.text.len, &font_style);
+ ctx.plot->text(&ctx,
+ &font_style,
+ x, y,
+ widget->u.text.text,
+ widget->u.text.len);
}
if (caret) {
@@ -209,6 +217,11 @@ fb_redraw_text_button(fbtk_widget_t *widget, fbtk_callback_info *cbi )
int fh;
int border;
fbtk_widget_t *root = fbtk_get_root_widget(widget);
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &fb_plotters
+ };
fb_text_font_style(widget, &fh, &border, &font_style);
@@ -256,11 +269,12 @@ fb_redraw_text_button(fbtk_widget_t *widget, fbtk_callback_info *cbi )
if (widget->u.text.text != NULL) {
/* Call the fb text plotting, baseline is 3/4 down the font */
- fb_plotters.text(bbox.x0 + border,
- bbox.y0 + ((fh * 3) / 4) + border,
- widget->u.text.text,
- widget->u.text.len,
- &font_style);
+ ctx.plot->text(&ctx,
+ &font_style,
+ bbox.x0 + border,
+ bbox.y0 + ((fh * 3) / 4) + border,
+ widget->u.text.text,
+ widget->u.text.len);
}
nsfb_update(root->u.root.fb, &bbox);
@@ -374,6 +388,22 @@ text_input(fbtk_widget_t *widget, fbtk_callback_info *cbi)
}
break;
+ case NSFB_KEY_HOME:
+ if (widget->u.text.idx > 0) {
+ widget->u.text.idx = 0;
+
+ caret_moved = true;
+ }
+ break;
+
+ case NSFB_KEY_END:
+ if (widget->u.text.idx < widget->u.text.len) {
+ widget->u.text.idx = widget->u.text.len;
+
+ caret_moved = true;
+ }
+ break;
+
case NSFB_KEY_PAGEUP:
case NSFB_KEY_PAGEDOWN:
case NSFB_KEY_UP:
diff --git a/frontends/framebuffer/fetch.c b/frontends/framebuffer/fetch.c
index 801b87a74..23cbb4f21 100644
--- a/frontends/framebuffer/fetch.c
+++ b/frontends/framebuffer/fetch.c
@@ -65,7 +65,7 @@ static nsurl *get_resource_url(const char *path)
static const char *fetch_filetype(const char *unix_path)
{
int l;
- LOG("unix path %s", unix_path);
+ NSLOG(netsurf, INFO, "unix path %s", unix_path);
l = strlen(unix_path);
if (2 < l && strcasecmp(unix_path + l - 3, "css") == 0)
return "text/css";
diff --git a/frontends/framebuffer/font_freetype.c b/frontends/framebuffer/font_freetype.c
index e7c07f5ff..744ac6281 100644
--- a/frontends/framebuffer/font_freetype.c
+++ b/frontends/framebuffer/font_freetype.c
@@ -90,12 +90,13 @@ ft_face_requester(FTC_FaceID face_id,
error = FT_New_Face(library, fb_face->fontfile, fb_face->index, face);
if (error) {
- LOG("Could not find font (code %d)", error);
+ NSLOG(netsurf, INFO, "Could not find font (code %d)", error);
} else {
error = FT_Select_Charmap(*face, FT_ENCODING_UNICODE);
if (error) {
- LOG("Could not select charmap (code %d)", error);
+ NSLOG(netsurf, INFO,
+ "Could not select charmap (code %d)", error);
} else {
for (cidx = 0; cidx < (*face)->num_charmaps; cidx++) {
if ((*face)->charmap == (*face)->charmaps[cidx]) {
@@ -105,7 +106,7 @@ ft_face_requester(FTC_FaceID face_id,
}
}
}
- LOG("Loaded face from %s", fb_face->fontfile);
+ NSLOG(netsurf, INFO, "Loaded face from %s", fb_face->fontfile);
return error;
}
@@ -132,7 +133,8 @@ fb_new_face(const char *option, const char *resname, const char *fontname)
error = FTC_Manager_LookupFace(ft_cmanager, (FTC_FaceID)newf, &aface);
if (error) {
- LOG("Could not find font face %s (code %d)", fontname, error);
+ NSLOG(netsurf, INFO, "Could not find font face %s (code %d)",
+ fontname, error);
free(newf->fontfile);
free(newf);
newf = NULL;
@@ -152,7 +154,8 @@ bool fb_font_init(void)
/* freetype library initialise */
error = FT_Init_FreeType( &library );
if (error) {
- LOG("Freetype could not initialised (code %d)", error);
+ NSLOG(netsurf, INFO,
+ "Freetype could not initialised (code %d)", error);
return false;
}
@@ -172,7 +175,9 @@ bool fb_font_init(void)
NULL,
&ft_cmanager);
if (error) {
- LOG("Freetype could not initialise cache manager (code %d)", error);
+ NSLOG(netsurf, INFO,
+ "Freetype could not initialise cache manager (code %d)",
+ error);
FT_Done_FreeType(library);
return false;
}
@@ -189,7 +194,7 @@ bool fb_font_init(void)
NETSURF_FB_FONT_SANS_SERIF);
if (fb_face == NULL) {
/* The sans serif font is the default and must be found. */
- LOG("Could not find the default font");
+ NSLOG(netsurf, INFO, "Could not find the default font");
FTC_Manager_Done(ft_cmanager);
FT_Done_FreeType(library);
return false;
@@ -387,7 +392,7 @@ static void fb_fill_scalar(const plot_font_style_t *fstyle, FTC_Scaler srec)
srec->face_id = (FTC_FaceID)fb_faces[selected_face];
- srec->width = srec->height = (fstyle->size * 64) / FONT_SIZE_SCALE;
+ srec->width = srec->height = (fstyle->size * 64) / PLOT_STYLE_SCALE;
srec->pixel = 0;
srec->x_res = srec->y_res = browser_get_dpi();
diff --git a/frontends/framebuffer/font_internal.c b/frontends/framebuffer/font_internal.c
index 3b8a1c43f..d755681c6 100644
--- a/frontends/framebuffer/font_internal.c
+++ b/frontends/framebuffer/font_internal.c
@@ -212,7 +212,7 @@ fb_get_font_size(const plot_font_style_t *fstyle)
{
int size = fstyle->size * 10 /
(((nsoption_int(font_min_size) * 3 +
- nsoption_int(font_size)) / 4) * FONT_SIZE_SCALE);
+ nsoption_int(font_size)) / 4) * PLOT_STYLE_SCALE);
if (size > 2)
size = 2;
else if (size <= 0)
@@ -270,6 +270,7 @@ fb_get_glyph(uint32_t ucs4, enum fb_font_style style, int scale)
break;
}
}
+ /* Fall through. */
case FB_BOLD:
section = fb_bold_section_table[ucs4 / 256];
if (section != 0 || ucs4 / 256 == 0) {
@@ -280,6 +281,7 @@ fb_get_glyph(uint32_t ucs4, enum fb_font_style style, int scale)
break;
}
}
+ /* Fall through. */
case FB_ITALIC:
section = fb_italic_section_table[ucs4 / 256];
if (section != 0 || ucs4 / 256 == 0) {
@@ -290,6 +292,7 @@ fb_get_glyph(uint32_t ucs4, enum fb_font_style style, int scale)
break;
}
}
+ /* Fall through. */
case FB_REGULAR:
section = fb_regular_section_table[ucs4 / 256];
if (section != 0 || ucs4 / 256 == 0) {
@@ -300,6 +303,7 @@ fb_get_glyph(uint32_t ucs4, enum fb_font_style style, int scale)
break;
}
}
+ /* Fall through. */
default:
glyph_data = get_codepoint(ucs4, style & FB_ITALIC);
break;
diff --git a/frontends/framebuffer/framebuffer.c b/frontends/framebuffer/framebuffer.c
index 74c72fe71..52afdbf5d 100644
--- a/frontends/framebuffer/framebuffer.c
+++ b/frontends/framebuffer/framebuffer.c
@@ -45,139 +45,274 @@
static nsfb_t *nsfb;
-static bool
-framebuffer_plot_disc(int x, int y, int radius, const plot_style_t *style)
+/**
+ * \brief Sets a clip rectangle for subsequent plot operations.
+ *
+ * \param ctx The current redraw context.
+ * \param clip The rectangle to limit all subsequent plot
+ * operations within.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+framebuffer_plot_clip(const struct redraw_context *ctx, const struct rect *clip)
{
- nsfb_bbox_t ellipse;
- ellipse.x0 = x - radius;
- ellipse.y0 = y - radius;
- ellipse.x1 = x + radius;
- ellipse.y1 = y + radius;
-
- if (style->fill_type != PLOT_OP_TYPE_NONE) {
- nsfb_plot_ellipse_fill(nsfb, &ellipse, style->fill_colour);
- }
-
- if (style->stroke_type != PLOT_OP_TYPE_NONE) {
- nsfb_plot_ellipse(nsfb, &ellipse, style->stroke_colour);
- }
- return true;
+ nsfb_bbox_t nsfb_clip;
+ nsfb_clip.x0 = clip->x0;
+ nsfb_clip.y0 = clip->y0;
+ nsfb_clip.x1 = clip->x1;
+ nsfb_clip.y1 = clip->y1;
+
+ if (!nsfb_plot_set_clip(nsfb, &nsfb_clip)) {
+ return NSERROR_INVALID;
+ }
+ return NSERROR_OK;
}
-static bool
-framebuffer_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style)
+
+/**
+ * Plots an arc
+ *
+ * plot an arc segment around (x,y), anticlockwise from angle1
+ * to angle2. Angles are measured anticlockwise from
+ * horizontal, in degrees.
+ *
+ * \param ctx The current redraw context.
+ * \param style Style controlling the arc plot.
+ * \param x The x coordinate of the arc.
+ * \param y The y coordinate of the arc.
+ * \param radius The radius of the arc.
+ * \param angle1 The start angle of the arc.
+ * \param angle2 The finish angle of the arc.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+framebuffer_plot_arc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius, int angle1, int angle2)
{
- return nsfb_plot_arc(nsfb, x, y, radius, angle1, angle2, style->fill_colour);
+ if (!nsfb_plot_arc(nsfb, x, y, radius, angle1, angle2, style->fill_colour)) {
+ return NSERROR_INVALID;
+ }
+ return NSERROR_OK;
}
-static bool
-framebuffer_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
+
+/**
+ * Plots a circle
+ *
+ * Plot a circle centered on (x,y), which is optionally filled.
+ *
+ * \param ctx The current redraw context.
+ * \param style Style controlling the circle plot.
+ * \param x x coordinate of circle centre.
+ * \param y y coordinate of circle centre.
+ * \param radius circle radius.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+framebuffer_plot_disc(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ int x, int y, int radius)
{
- return nsfb_plot_polygon(nsfb, p, n, style->fill_colour);
+ nsfb_bbox_t ellipse;
+ ellipse.x0 = x - radius;
+ ellipse.y0 = y - radius;
+ ellipse.x1 = x + radius;
+ ellipse.y1 = y + radius;
+
+ if (style->fill_type != PLOT_OP_TYPE_NONE) {
+ nsfb_plot_ellipse_fill(nsfb, &ellipse, style->fill_colour);
+ }
+
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ nsfb_plot_ellipse(nsfb, &ellipse, style->stroke_colour);
+ }
+ return NSERROR_OK;
}
-#ifdef FB_USE_FREETYPE
-static bool
-framebuffer_plot_text(int x, int y, const char *text, size_t length,
- const plot_font_style_t *fstyle)
+/**
+ * Plots a line
+ *
+ * plot a line from (x0,y0) to (x1,y1). Coordinates are at
+ * centre of line width/thickness.
+ *
+ * \param ctx The current redraw context.
+ * \param style Style controlling the line plot.
+ * \param line A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+framebuffer_plot_line(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *line)
{
- uint32_t ucs4;
- size_t nxtchr = 0;
- FT_Glyph glyph;
- FT_BitmapGlyph bglyph;
- nsfb_bbox_t loc;
-
- while (nxtchr < length) {
- ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
- nxtchr = utf8_next(text, length, nxtchr);
-
- glyph = fb_getglyph(fstyle, ucs4);
- if (glyph == NULL)
- continue;
-
- if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
- bglyph = (FT_BitmapGlyph)glyph;
-
- loc.x0 = x + bglyph->left;
- loc.y0 = y - bglyph->top;
- loc.x1 = loc.x0 + bglyph->bitmap.width;
- loc.y1 = loc.y0 + bglyph->bitmap.rows;
-
- /* now, draw to our target surface */
- if (bglyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
- nsfb_plot_glyph1(nsfb,
- &loc,
- bglyph->bitmap.buffer,
- bglyph->bitmap.pitch,
- fstyle->foreground);
- } else {
- nsfb_plot_glyph8(nsfb,
- &loc,
- bglyph->bitmap.buffer,
- bglyph->bitmap.pitch,
- fstyle->foreground);
- }
- }
- x += glyph->advance.x >> 16;
-
- }
- return true;
+ nsfb_bbox_t rect;
+ nsfb_plot_pen_t pen;
+
+ rect.x0 = line->x0;
+ rect.y0 = line->y0;
+ rect.x1 = line->x1;
+ rect.y1 = line->y1;
+
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+
+ if (style->stroke_type == PLOT_OP_TYPE_DOT) {
+ pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
+ pen.stroke_pattern = 0xAAAAAAAA;
+ } else if (style->stroke_type == PLOT_OP_TYPE_DASH) {
+ pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
+ pen.stroke_pattern = 0xF0F0F0F0;
+ } else {
+ pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
+ }
+
+ pen.stroke_colour = style->stroke_colour;
+ pen.stroke_width = plot_style_fixed_to_int(style->stroke_width);
+ nsfb_plot_line(nsfb, &rect, &pen);
+ }
+ return NSERROR_OK;
}
-#else
-static bool framebuffer_plot_text(int x, int y, const char *text, size_t length,
- const plot_font_style_t *fstyle)
+
+
+/**
+ * Plots a rectangle.
+ *
+ * The rectangle can be filled an outline or both controlled
+ * by the plot style The line can be solid, dotted or
+ * dashed. Top left corner at (x0,y0) and rectangle has given
+ * width and height.
+ *
+ * \param ctx The current redraw context.
+ * \param style Style controlling the rectangle plot.
+ * \param nsrect A rectangle defining the line to be drawn
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+framebuffer_plot_rectangle(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const struct rect *nsrect)
{
- enum fb_font_style style = fb_get_font_style(fstyle);
- int size = fb_get_font_size(fstyle);
- const uint8_t *chrp;
- size_t nxtchr = 0;
- nsfb_bbox_t loc;
- uint32_t ucs4;
- int p = FB_FONT_PITCH * size;
- int w = FB_FONT_WIDTH * size;
- int h = FB_FONT_HEIGHT * size;
+ nsfb_bbox_t rect;
+ bool dotted = false;
+ bool dashed = false;
- y -= ((h * 3) / 4);
- /* the coord is the bottom-left of the pixels offset by 1 to make
- * it work since fb coords are the top-left of pixels */
- y += 1;
+ rect.x0 = nsrect->x0;
+ rect.y0 = nsrect->y0;
+ rect.x1 = nsrect->x1;
+ rect.y1 = nsrect->y1;
- while (nxtchr < length) {
- ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
- nxtchr = utf8_next(text, length, nxtchr);
+ if (style->fill_type != PLOT_OP_TYPE_NONE) {
+ nsfb_plot_rectangle_fill(nsfb, &rect, style->fill_colour);
+ }
- if (!codepoint_displayable(ucs4))
- continue;
+ if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ if (style->stroke_type == PLOT_OP_TYPE_DOT) {
+ dotted = true;
+ }
- loc.x0 = x;
- loc.y0 = y;
- loc.x1 = loc.x0 + w;
- loc.y1 = loc.y0 + h;
+ if (style->stroke_type == PLOT_OP_TYPE_DASH) {
+ dashed = true;
+ }
- chrp = fb_get_glyph(ucs4, style, size);
- nsfb_plot_glyph1(nsfb, &loc, chrp, p, fstyle->foreground);
+ nsfb_plot_rectangle(nsfb, &rect,
+ plot_style_fixed_to_int(style->stroke_width),
+ style->stroke_colour, dotted, dashed);
+ }
+ return NSERROR_OK;
+}
- x += w;
- }
+/**
+ * Plot a polygon
+ *
+ * Plots a filled polygon with straight lines between
+ * points. The lines around the edge of the ploygon are not
+ * plotted. The polygon is filled with the non-zero winding
+ * rule.
+ *
+ * \param ctx The current redraw context.
+ * \param style Style controlling the polygon plot.
+ * \param p verticies of polygon
+ * \param n number of verticies.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+framebuffer_plot_polygon(const struct redraw_context *ctx,
+ const plot_style_t *style,
+ const int *p,
+ unsigned int n)
+{
+ if (!nsfb_plot_polygon(nsfb, p, n, style->fill_colour)) {
+ return NSERROR_INVALID;
+ }
+ return NSERROR_OK;
+}
- return true;
+
+/**
+ * Plots a path.
+ *
+ * Path plot consisting of cubic Bezier curves. Line and fill colour is
+ * controlled by the plot style.
+ *
+ * \param ctx The current redraw context.
+ * \param pstyle Style controlling the path plot.
+ * \param p elements of path
+ * \param n nunber of elements on path
+ * \param transform A transform to apply to the path.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+framebuffer_plot_path(const struct redraw_context *ctx,
+ const plot_style_t *pstyle,
+ const float *p,
+ unsigned int n,
+ const float transform[6])
+{
+ NSLOG(netsurf, INFO, "path unimplemented");
+ return NSERROR_OK;
}
-#endif
-static bool
-framebuffer_plot_bitmap(int x, int y,
- int width, int height,
- struct bitmap *bitmap, colour bg,
- bitmap_flags_t flags)
+/**
+ * Plot a bitmap
+ *
+ * Tiled plot of a bitmap image. (x,y) gives the top left
+ * coordinate of an explicitly placed tile. From this tile the
+ * image can repeat in all four directions -- up, down, left
+ * and right -- to the extents given by the current clip
+ * rectangle.
+ *
+ * The bitmap_flags say whether to tile in the x and y
+ * directions. If not tiling in x or y directions, the single
+ * image is plotted. The width and height give the dimensions
+ * the image is to be scaled to.
+ *
+ * \param ctx The current redraw context.
+ * \param bitmap The bitmap to plot
+ * \param x The x coordinate to plot the bitmap
+ * \param y The y coordiante to plot the bitmap
+ * \param width The width of area to plot the bitmap into
+ * \param height The height of area to plot the bitmap into
+ * \param bg the background colour to alpha blend into
+ * \param flags the flags controlling the type of plot operation
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+framebuffer_plot_bitmap(const struct redraw_context *ctx,
+ struct bitmap *bitmap,
+ int x, int y,
+ int width,
+ int height,
+ colour bg,
+ bitmap_flags_t flags)
{
- nsfb_bbox_t loc;
- nsfb_bbox_t clipbox;
- bool repeat_x = (flags & BITMAPF_REPEAT_X);
- bool repeat_y = (flags & BITMAPF_REPEAT_Y);
+ nsfb_bbox_t loc;
+ nsfb_bbox_t clipbox;
+ bool repeat_x = (flags & BITMAPF_REPEAT_X);
+ bool repeat_y = (flags & BITMAPF_REPEAT_Y);
int bmwidth;
int bmheight;
int bmstride;
@@ -193,15 +328,18 @@ framebuffer_plot_bitmap(int x, int y,
if (!(repeat_x || repeat_y)) {
/* Not repeating at all, so just plot it */
- loc.x0 = x;
- loc.y0 = y;
- loc.x1 = loc.x0 + width;
- loc.y1 = loc.y0 + height;
+ loc.x0 = x;
+ loc.y0 = y;
+ loc.x1 = loc.x0 + width;
+ loc.y1 = loc.y0 + height;
- return nsfb_plot_copy(bm, NULL, nsfb, &loc);
+ if (!nsfb_plot_copy(bm, NULL, nsfb, &loc)) {
+ return NSERROR_INVALID;
+ }
+ return NSERROR_OK;
}
- nsfb_plot_get_clip(nsfb, &clipbox);
+ nsfb_plot_get_clip(nsfb, &clipbox);
nsfb_get_geometry(bm, &bmwidth, &bmheight, &bmformat);
nsfb_get_buffer(bm, &bmptr, &bmstride);
@@ -209,8 +347,11 @@ framebuffer_plot_bitmap(int x, int y,
* of the area. Can only be done when image is fully opaque. */
if ((bmwidth == 1) && (bmheight == 1)) {
if ((*(nsfb_colour_t *)bmptr & 0xff000000) != 0) {
- return nsfb_plot_rectangle_fill(nsfb, &clipbox,
- *(nsfb_colour_t *)bmptr);
+ if (!nsfb_plot_rectangle_fill(nsfb, &clipbox,
+ *(nsfb_colour_t *)bmptr)) {
+ return NSERROR_INVALID;
+ }
+ return NSERROR_OK;
}
}
@@ -221,24 +362,29 @@ framebuffer_plot_bitmap(int x, int y,
if (framebuffer_bitmap_get_opaque(bm)) {
/** TODO: Currently using top left pixel. Maybe centre
* pixel or average value would be better. */
- return nsfb_plot_rectangle_fill(nsfb, &clipbox,
- *(nsfb_colour_t *)bmptr);
+ if (!nsfb_plot_rectangle_fill(nsfb, &clipbox,
+ *(nsfb_colour_t *)bmptr)) {
+ return NSERROR_INVALID;
+ }
+ return NSERROR_OK;
}
}
/* get left most tile position */
- if (repeat_x)
+ if (repeat_x) {
for (; x > clipbox.x0; x -= width);
+ }
/* get top most tile position */
- if (repeat_y)
+ if (repeat_y) {
for (; y > clipbox.y0; y -= height);
+ }
/* set up top left tile location */
- loc.x0 = x;
- loc.y0 = y;
- loc.x1 = loc.x0 + width;
- loc.y1 = loc.y0 + height;
+ loc.x0 = x;
+ loc.y0 = y;
+ loc.x1 = loc.x0 + width;
+ loc.y1 = loc.y0 + height;
/* plot tiling across and down to extents */
nsfb_plot_bitmap_tiles(nsfb, &loc,
@@ -247,94 +393,135 @@ framebuffer_plot_bitmap(int x, int y,
(nsfb_colour_t *)bmptr, bmwidth, bmheight,
bmstride * 8 / 32, bmformat == NSFB_FMT_ABGR8888);
- return true;
+ return NSERROR_OK;
}
-static bool
-framebuffer_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
-{
- nsfb_bbox_t rect;
- bool dotted = false;
- bool dashed = false;
-
- rect.x0 = x0;
- rect.y0 = y0;
- rect.x1 = x1;
- rect.y1 = y1;
- if (style->fill_type != PLOT_OP_TYPE_NONE) {
- nsfb_plot_rectangle_fill(nsfb, &rect, style->fill_colour);
- }
-
- if (style->stroke_type != PLOT_OP_TYPE_NONE) {
- if (style->stroke_type == PLOT_OP_TYPE_DOT)
- dotted = true;
-
- if (style->stroke_type == PLOT_OP_TYPE_DASH)
- dashed = true;
+#ifdef FB_USE_FREETYPE
+/**
+ * Text plotting.
+ *
+ * \param ctx The current redraw context.
+ * \param fstyle plot style for this text
+ * \param x x coordinate
+ * \param y y coordinate
+ * \param text UTF-8 string to plot
+ * \param length length of string, in bytes
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+framebuffer_plot_text(const struct redraw_context *ctx,
+ const struct plot_font_style *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
+{
+ uint32_t ucs4;
+ size_t nxtchr = 0;
+ FT_Glyph glyph;
+ FT_BitmapGlyph bglyph;
+ nsfb_bbox_t loc;
+
+ while (nxtchr < length) {
+ ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
+ nxtchr = utf8_next(text, length, nxtchr);
+
+ glyph = fb_getglyph(fstyle, ucs4);
+ if (glyph == NULL)
+ continue;
+
+ if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
+ bglyph = (FT_BitmapGlyph)glyph;
+
+ loc.x0 = x + bglyph->left;
+ loc.y0 = y - bglyph->top;
+ loc.x1 = loc.x0 + bglyph->bitmap.width;
+ loc.y1 = loc.y0 + bglyph->bitmap.rows;
+
+ /* now, draw to our target surface */
+ if (bglyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
+ nsfb_plot_glyph1(nsfb,
+ &loc,
+ bglyph->bitmap.buffer,
+ bglyph->bitmap.pitch,
+ fstyle->foreground);
+ } else {
+ nsfb_plot_glyph8(nsfb,
+ &loc,
+ bglyph->bitmap.buffer,
+ bglyph->bitmap.pitch,
+ fstyle->foreground);
+ }
+ }
+ x += glyph->advance.x >> 16;
- nsfb_plot_rectangle(nsfb, &rect, style->stroke_width, style->stroke_colour, dotted, dashed);
}
+ return NSERROR_OK;
- return true;
}
-static bool
-framebuffer_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
+#else
+
+/**
+ * Text plotting.
+ *
+ * \param ctx The current redraw context.
+ * \param fstyle plot style for this text
+ * \param x x coordinate
+ * \param y y coordinate
+ * \param text UTF-8 string to plot
+ * \param length length of string, in bytes
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+framebuffer_plot_text(const struct redraw_context *ctx,
+ const struct plot_font_style *fstyle,
+ int x,
+ int y,
+ const char *text,
+ size_t length)
{
- nsfb_bbox_t rect;
- nsfb_plot_pen_t pen;
+ enum fb_font_style style = fb_get_font_style(fstyle);
+ int size = fb_get_font_size(fstyle);
+ const uint8_t *chrp;
+ size_t nxtchr = 0;
+ nsfb_bbox_t loc;
+ uint32_t ucs4;
+ int p = FB_FONT_PITCH * size;
+ int w = FB_FONT_WIDTH * size;
+ int h = FB_FONT_HEIGHT * size;
- rect.x0 = x0;
- rect.y0 = y0;
- rect.x1 = x1;
- rect.y1 = y1;
-
- if (style->stroke_type != PLOT_OP_TYPE_NONE) {
+ y -= ((h * 3) / 4);
+ /* the coord is the bottom-left of the pixels offset by 1 to make
+ * it work since fb coords are the top-left of pixels */
+ y += 1;
- if (style->stroke_type == PLOT_OP_TYPE_DOT) {
- pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
- pen.stroke_pattern = 0xAAAAAAAA;
- } else if (style->stroke_type == PLOT_OP_TYPE_DASH) {
- pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
- pen.stroke_pattern = 0xF0F0F0F0;
- } else {
- pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
- }
+ while (nxtchr < length) {
+ ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
+ nxtchr = utf8_next(text, length, nxtchr);
- pen.stroke_colour = style->stroke_colour;
- pen.stroke_width = style->stroke_width;
- nsfb_plot_line(nsfb, &rect, &pen);
- }
+ if (!codepoint_displayable(ucs4))
+ continue;
- return true;
-}
+ loc.x0 = x;
+ loc.y0 = y;
+ loc.x1 = loc.x0 + w;
+ loc.y1 = loc.y0 + h;
+ chrp = fb_get_glyph(ucs4, style, size);
+ nsfb_plot_glyph1(nsfb, &loc, chrp, p, fstyle->foreground);
-static bool
-framebuffer_plot_path(const float *p,
- unsigned int n,
- colour fill,
- float width,
- colour c,
- const float transform[6])
-{
- LOG("path unimplemented");
- return true;
-}
+ x += w;
-static bool
-framebuffer_plot_clip(const struct rect *clip)
-{
- nsfb_bbox_t nsfb_clip;
- nsfb_clip.x0 = clip->x0;
- nsfb_clip.y0 = clip->y0;
- nsfb_clip.x1 = clip->x1;
- nsfb_clip.y1 = clip->y1;
+ }
- return nsfb_plot_set_clip(nsfb, &nsfb_clip);
+ return NSERROR_OK;
}
+#endif
+
+/** framebuffer plot operation table */
const struct plotter_table fb_plotters = {
.clip = framebuffer_plot_clip,
.arc = framebuffer_plot_arc,
@@ -345,7 +532,7 @@ const struct plotter_table fb_plotters = {
.path = framebuffer_plot_path,
.bitmap = framebuffer_plot_bitmap,
.text = framebuffer_plot_text,
- .option_knockout = true,
+ .option_knockout = true,
};
@@ -377,7 +564,7 @@ static bool framebuffer_format_from_bpp(int bpp, enum nsfb_format_e *fmt)
break;
default:
- LOG("Bad bits per pixel (%d)\n", bpp);
+ NSLOG(netsurf, INFO, "Bad bits per pixel (%d)\n", bpp);
return false;
}
@@ -394,33 +581,34 @@ framebuffer_initialise(const char *fename, int width, int height, int bpp)
/* bpp is a proxy for the framebuffer format */
if (framebuffer_format_from_bpp(bpp, &fbfmt) == false) {
- return NULL;
+ return NULL;
}
fbtype = nsfb_type_from_name(fename);
if (fbtype == NSFB_SURFACE_NONE) {
- LOG("The %s surface is not available from libnsfb\n", fename);
- return NULL;
+ NSLOG(netsurf, INFO,
+ "The %s surface is not available from libnsfb\n", fename);
+ return NULL;
}
nsfb = nsfb_new(fbtype);
if (nsfb == NULL) {
- LOG("Unable to create %s fb surface\n", fename);
- return NULL;
+ NSLOG(netsurf, INFO, "Unable to create %s fb surface\n", fename);
+ return NULL;
}
-
+
if (nsfb_set_geometry(nsfb, width, height, fbfmt) == -1) {
- LOG("Unable to set surface geometry\n");
- nsfb_free(nsfb);
- return NULL;
+ NSLOG(netsurf, INFO, "Unable to set surface geometry\n");
+ nsfb_free(nsfb);
+ return NULL;
}
nsfb_cursor_init(nsfb);
-
+
if (nsfb_init(nsfb) == -1) {
- LOG("Unable to initialise nsfb surface\n");
- nsfb_free(nsfb);
- return NULL;
+ NSLOG(netsurf, INFO, "Unable to initialise nsfb surface\n");
+ nsfb_free(nsfb);
+ return NULL;
}
return nsfb;
@@ -434,12 +622,12 @@ framebuffer_resize(nsfb_t *nsfb, int width, int height, int bpp)
/* bpp is a proxy for the framebuffer format */
if (framebuffer_format_from_bpp(bpp, &fbfmt) == false) {
- return false;
+ return false;
}
if (nsfb_set_geometry(nsfb, width, height, fbfmt) == -1) {
- LOG("Unable to change surface geometry\n");
- return false;
+ NSLOG(netsurf, INFO, "Unable to change surface geometry\n");
+ return false;
}
return true;
@@ -449,14 +637,14 @@ framebuffer_resize(nsfb_t *nsfb, int width, int height, int bpp)
void
framebuffer_finalise(void)
{
- nsfb_free(nsfb);
+ nsfb_free(nsfb);
}
bool
framebuffer_set_cursor(struct fbtk_bitmap *bm)
{
return nsfb_cursor_set(nsfb, (nsfb_colour_t *)bm->pixdata, bm->width, bm->height, bm->width, bm->hot_x, bm->hot_y);
-}
+}
nsfb_t *framebuffer_set_surface(nsfb_t *new_nsfb)
{
diff --git a/frontends/framebuffer/gui.c b/frontends/framebuffer/gui.c
index 4d4c7334f..1e27dafb6 100644
--- a/frontends/framebuffer/gui.c
+++ b/frontends/framebuffer/gui.c
@@ -54,6 +54,7 @@
#include "framebuffer/clipboard.h"
#include "framebuffer/fetch.h"
#include "framebuffer/bitmap.h"
+#include "framebuffer/local_history.h"
#define NSFB_TOOLBAR_DEFAULT_LAYOUT "blfsrutc"
@@ -119,7 +120,7 @@ static void die(const char *error)
*/
static nserror fb_warn_user(const char *warning, const char *detail)
{
- LOG("%s %s", warning, detail);
+ NSLOG(netsurf, INFO, "%s %s", warning, detail);
return NSERROR_OK;
}
@@ -152,7 +153,7 @@ widget_scroll_y(struct gui_window *gw, int y, bool abs)
int content_width, content_height;
int height;
- LOG("window scroll");
+ NSLOG(netsurf, INFO, "window scroll");
if (abs) {
bwidget->pany = y - bwidget->scrolly;
} else {
@@ -236,7 +237,7 @@ fb_pan(fbtk_widget_t *widget,
height = fbtk_get_height(widget);
width = fbtk_get_width(widget);
- LOG("panning %d, %d", bwidget->panx, bwidget->pany);
+ NSLOG(netsurf, INFO, "panning %d, %d", bwidget->panx, bwidget->pany);
x = fbtk_get_absx(widget);
y = fbtk_get_absy(widget);
@@ -412,7 +413,8 @@ fb_browser_window_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi)
bwidget = fbtk_get_userpw(widget);
if (bwidget == NULL) {
- LOG("browser widget from widget %p was null", widget);
+ NSLOG(netsurf, INFO,
+ "browser widget from widget %p was null", widget);
return -1;
}
@@ -464,7 +466,7 @@ process_cmdline(int argc, char** argv)
{0, 0, 0, 0 }
}; /* no long options */
- LOG("argc %d, argv %p", argc, argv);
+ NSLOG(netsurf, INFO, "argc %d, argv %p", argc, argv);
fename = "sdl";
febpp = 32;
@@ -533,7 +535,7 @@ static nserror set_defaults(struct nsoption_s *defaults)
if (nsoption_charp(cookie_file) == NULL ||
nsoption_charp(cookie_jar) == NULL) {
- LOG("Failed initialising cookie options");
+ NSLOG(netsurf, INFO, "Failed initialising cookie options");
return NSERROR_BAD_PARAMETER;
}
@@ -611,7 +613,7 @@ static void framebuffer_run(void)
static void gui_quit(void)
{
- LOG("gui_quit");
+ NSLOG(netsurf, INFO, "gui_quit");
urldb_save_cookies(nsoption_charp(cookie_jar));
@@ -638,7 +640,8 @@ fb_browser_window_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
cbi->event->type != NSFB_EVENT_KEY_UP)
return 0;
- LOG("browser window clicked at %d,%d", cbi->x, cbi->y);
+ NSLOG(netsurf, INFO, "browser window clicked at %d,%d", cbi->x,
+ cbi->y);
switch (cbi->event->type) {
case NSFB_EVENT_KEY_DOWN:
@@ -823,7 +826,7 @@ fb_browser_window_input(fbtk_widget_t *widget, fbtk_callback_info *cbi)
static fbtk_modifier_type modifier = FBTK_MOD_CLEAR;
int ucs4 = -1;
- LOG("got value %d", cbi->event->value.keycode);
+ NSLOG(netsurf, INFO, "got value %d", cbi->event->value.keycode);
switch (cbi->event->type) {
case NSFB_EVENT_KEY_DOWN:
@@ -948,8 +951,8 @@ fb_browser_window_input(fbtk_widget_t *widget, fbtk_callback_info *cbi)
browser_window_key_press(gw->bw, NS_KEY_REDO);
break;
}
- /* Z or Y pressed but not undo or redo;
- * Fall through to default handling */
+ /* Z or Y pressed but not undo or redo; */
+ /* Fall through */
default:
ucs4 = fbtk_keycode_to_ucs4(cbi->event->value.keycode,
@@ -1150,7 +1153,7 @@ fb_localhistory_btn_clik(fbtk_widget_t *widget, fbtk_callback_info *cbi)
if (cbi->event->type != NSFB_EVENT_KEY_UP)
return 0;
- fb_localhistory_map(gw->localhistory);
+ fb_local_history_present(fbtk, gw->bw);
return 0;
}
@@ -1199,7 +1202,7 @@ create_toolbar(struct gui_window *gw,
toolbar_layout = NSFB_TOOLBAR_DEFAULT_LAYOUT;
}
- LOG("Using toolbar layout %s", toolbar_layout);
+ NSLOG(netsurf, INFO, "Using toolbar layout %s", toolbar_layout);
itmtype = toolbar_layout;
@@ -1233,7 +1236,7 @@ create_toolbar(struct gui_window *gw,
(*itmtype != 0) &&
(xdir !=0)) {
- LOG("toolbar adding %c", *itmtype);
+ NSLOG(netsurf, INFO, "toolbar adding %c", *itmtype);
switch (*itmtype) {
@@ -1375,7 +1378,9 @@ create_toolbar(struct gui_window *gw,
default:
widget = NULL;
xdir = 0;
- LOG("Unknown element %c in toolbar layout", *itmtype);
+ NSLOG(netsurf, INFO,
+ "Unknown element %c in toolbar layout",
+ *itmtype);
break;
}
@@ -1384,7 +1389,7 @@ create_toolbar(struct gui_window *gw,
xpos += (xdir * (fbtk_get_width(widget) + padding));
}
- LOG("xpos is %d", xpos);
+ NSLOG(netsurf, INFO, "xpos is %d", xpos);
itmtype += xdir;
}
@@ -1583,7 +1588,7 @@ resize_browser_widget(struct gui_window *gw, int x, int y,
int width, int height)
{
fbtk_set_pos_and_size(gw->browser, x, y, width, height);
- browser_window_reformat(gw->bw, false, width, height);
+ browser_window_schedule_reformat(gw->bw);
}
static void
@@ -1594,7 +1599,7 @@ create_normal_browser_window(struct gui_window *gw, int furniture_width)
int statusbar_width = 0;
int toolbar_height = nsoption_int(fb_toolbar_size);
- LOG("Normal window");
+ NSLOG(netsurf, INFO, "Normal window");
gw->window = fbtk_create_window(fbtk, 0, 0, 0, 0, 0);
@@ -1625,7 +1630,8 @@ create_normal_browser_window(struct gui_window *gw, int furniture_width)
false);
fbtk_set_handler(gw->status, FBTK_CBT_POINTERENTER, set_ptr_default_move, NULL);
- LOG("status bar %p at %d,%d", gw->status, fbtk_get_absx(gw->status), fbtk_get_absy(gw->status));
+ NSLOG(netsurf, INFO, "status bar %p at %d,%d", gw->status,
+ fbtk_get_absx(gw->status), fbtk_get_absy(gw->status));
/* create horizontal scrollbar */
gw->hscroll = fbtk_create_hscroll(gw->window,
@@ -1782,7 +1788,6 @@ gui_window_create(struct browser_window *bw,
gw->bw = bw;
create_normal_browser_window(gw, nsoption_int(fb_furniture_size));
- gw->localhistory = fb_create_localhistory(bw, fbtk, nsoption_int(fb_furniture_size));
/* map and request redraw of gui window */
fbtk_set_mapping(gw->window, true);
@@ -1803,21 +1808,33 @@ gui_window_destroy(struct gui_window *gw)
free(gw);
}
-static void
-gui_window_redraw_window(struct gui_window *g)
-{
- fb_queue_redraw(g->browser, 0, 0, fbtk_get_width(g->browser), fbtk_get_height(g->browser) );
-}
-static void
-gui_window_update_box(struct gui_window *g, const struct rect *rect)
+/**
+ * Invalidates an area of a framebuffer browser window
+ *
+ * \param g The netsurf window being invalidated.
+ * \param rect area to redraw or NULL for the entire window area
+ * \return NSERROR_OK on success or appropriate error code
+ */
+static nserror
+fb_window_invalidate_area(struct gui_window *g, const struct rect *rect)
{
struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser);
- fb_queue_redraw(g->browser,
- rect->x0 - bwidget->scrollx,
- rect->y0 - bwidget->scrolly,
- rect->x1 - bwidget->scrollx,
- rect->y1 - bwidget->scrolly);
+
+ if (rect != NULL) {
+ fb_queue_redraw(g->browser,
+ rect->x0 - bwidget->scrollx,
+ rect->y0 - bwidget->scrolly,
+ rect->x1 - bwidget->scrollx,
+ rect->y1 - bwidget->scrolly);
+ } else {
+ fb_queue_redraw(g->browser,
+ 0,
+ 0,
+ fbtk_get_width(g->browser),
+ fbtk_get_height(g->browser));
+ }
+ return NSERROR_OK;
}
static bool
@@ -1832,34 +1849,56 @@ gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
return true;
}
-static void
-gui_window_set_scroll(struct gui_window *gw, int sx, int sy)
+/**
+ * Set the scroll position of a framebuffer browser window.
+ *
+ * Scrolls the viewport to ensure the specified rectangle of the
+ * content is shown. The framebuffer implementation scrolls the contents so
+ * the specified point in the content is at the top of the viewport.
+ *
+ * \param gw gui_window to scroll
+ * \param rect The rectangle to ensure is shown.
+ * \return NSERROR_OK on success or apropriate error code.
+ */
+static nserror
+gui_window_set_scroll(struct gui_window *gw, const struct rect *rect)
{
struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser);
float scale = browser_window_get_scale(gw->bw);
assert(bwidget);
- widget_scroll_x(gw, sx * scale, true);
- widget_scroll_y(gw, sy * scale, true);
+ widget_scroll_x(gw, rect->x0 * scale, true);
+ widget_scroll_y(gw, rect->y0 * scale, true);
+
+ return NSERROR_OK;
}
-static void
-gui_window_get_dimensions(struct gui_window *g,
+/**
+ * Find the current dimensions of a framebuffer browser window content area.
+ *
+ * \param gw The gui window to measure content area of.
+ * \param width receives width of window
+ * \param height receives height of window
+ * \param scaled whether to return scaled values
+ * \return NSERROR_OK on sucess and width and height updated.
+ */
+static nserror
+gui_window_get_dimensions(struct gui_window *gw,
int *width,
int *height,
bool scaled)
{
- float scale = browser_window_get_scale(g->bw);
-
- *width = fbtk_get_width(g->browser);
- *height = fbtk_get_height(g->browser);
+ *width = fbtk_get_width(gw->browser);
+ *height = fbtk_get_height(gw->browser);
if (scaled) {
+ float scale = browser_window_get_scale(gw->bw);
*width /= scale;
*height /= scale;
}
+ return NSERROR_OK;
}
static void
@@ -2038,26 +2077,15 @@ gui_window_remove_caret(struct gui_window *g)
}
}
-static void framebuffer_window_reformat(struct gui_window *gw)
-{
- /** @todo if we ever do zooming reformat should be implemented */
- LOG("window:%p", gw);
-
- /*
- browser_window_reformat(gw->bw, false, width, height);
- */
-}
static struct gui_window_table framebuffer_window_table = {
.create = gui_window_create,
.destroy = gui_window_destroy,
- .redraw = gui_window_redraw_window,
- .update = gui_window_update_box,
+ .invalidate = fb_window_invalidate_area,
.get_scroll = gui_window_get_scroll,
.set_scroll = gui_window_set_scroll,
.get_dimensions = gui_window_get_dimensions,
.update_extent = gui_window_update_extent,
- .reformat = framebuffer_window_reformat,
.set_url = gui_window_set_url,
.set_status = gui_window_set_status,
@@ -2160,7 +2188,7 @@ main(int argc, char** argv)
/* create an initial browser window */
- LOG("calling browser_window_create");
+ NSLOG(netsurf, INFO, "calling browser_window_create");
ret = nsurl_create(feurl, &url);
if (ret == NSERROR_OK) {
@@ -2182,11 +2210,14 @@ main(int argc, char** argv)
netsurf_exit();
if (fb_font_finalise() == false)
- LOG("Font finalisation failed.");
+ NSLOG(netsurf, INFO, "Font finalisation failed.");
/* finalise options */
nsoption_finalise(nsoptions, nsoptions_default);
+ /* finalise logging */
+ nslog_finalise();
+
return 0;
}
diff --git a/frontends/framebuffer/gui.h b/frontends/framebuffer/gui.h
index 0de1add69..abb27c4bb 100644
--- a/frontends/framebuffer/gui.h
+++ b/frontends/framebuffer/gui.h
@@ -27,17 +27,6 @@ typedef struct fb_cursor_s fb_cursor_t;
/* bounding box */
typedef struct nsfb_bbox_s bbox_t;
-struct gui_localhistory {
- struct browser_window *bw;
-
- struct fbtk_widget_s *window;
- struct fbtk_widget_s *hscroll;
- struct fbtk_widget_s *vscroll;
- struct fbtk_widget_s *history;
-
- int scrollx, scrolly; /**< scroll offsets. */
-};
-
struct gui_window {
struct browser_window *bw;
@@ -59,8 +48,6 @@ struct gui_window {
int throbber_index;
- struct gui_localhistory *localhistory;
-
struct gui_window *next;
struct gui_window *prev;
};
@@ -68,13 +55,8 @@ struct gui_window {
extern struct gui_window *window_list;
-struct gui_localhistory *fb_create_localhistory(struct browser_window *bw,
- struct fbtk_widget_s *parent, int furniture_width);
-void fb_localhistory_map(struct gui_localhistory * glh);
-
void gui_resize(struct fbtk_widget_s *root, int width, int height);
-
#endif /* NETSURF_FB_GUI_H */
/*
diff --git a/frontends/framebuffer/local_history.c b/frontends/framebuffer/local_history.c
new file mode 100644
index 000000000..cc45b1f29
--- /dev/null
+++ b/frontends/framebuffer/local_history.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2017 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of framebuffer local history manager.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include <libnsfb.h>
+#include <libnsfb_plot.h>
+#include <libnsfb_event.h>
+
+#include "utils/log.h"
+#include "netsurf/keypress.h"
+#include "netsurf/plotters.h"
+#include "desktop/local_history.h"
+
+#include "framebuffer/gui.h"
+#include "framebuffer/fbtk.h"
+#include "framebuffer/framebuffer.h"
+#include "framebuffer/corewindow.h"
+#include "framebuffer/local_history.h"
+
+struct fb_local_history_window {
+ struct fb_corewindow core;
+
+ struct local_history_session *session;
+};
+
+static struct fb_local_history_window *local_history_window = NULL;
+
+
+/**
+ * callback for mouse action on local history window
+ *
+ * \param fb_cw The fb core window structure.
+ * \param mouse_state netsurf mouse state on event
+ * \param x location of event
+ * \param y location of event
+ * \return NSERROR_OK on success otherwise apropriate error code
+ */
+static nserror
+fb_local_history_mouse(struct fb_corewindow *fb_cw,
+ browser_mouse_state mouse_state,
+ int x, int y)
+{
+ struct fb_local_history_window *lhw;
+ /* technically degenerate container of */
+ lhw = (struct fb_local_history_window *)fb_cw;
+
+ local_history_mouse_action(lhw->session, mouse_state, x, y);
+
+ if (mouse_state != BROWSER_MOUSE_HOVER) {
+ fbtk_set_mapping(lhw->core.wnd, false);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * callback for keypress on local history window
+ *
+ * \param fb_cw The fb core window structure.
+ * \param nskey The netsurf key code
+ * \return NSERROR_OK on success otherwise apropriate error code
+ */
+static nserror
+fb_local_history_key(struct fb_corewindow *fb_cw, uint32_t nskey)
+{
+ struct fb_local_history_window *lhw;
+ /* technically degenerate container of */
+ lhw = (struct fb_local_history_window *)fb_cw;
+
+ if (local_history_keypress(lhw->session, nskey)) {
+ return NSERROR_OK;
+ }
+ return NSERROR_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * callback on draw event for local history window
+ *
+ * \param fb_cw The fb core window structure.
+ * \param r The rectangle of the window that needs updating.
+ * \return NSERROR_OK on success otherwise apropriate error code
+ */
+static nserror
+fb_local_history_draw(struct fb_corewindow *fb_cw, struct rect *r)
+{
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &fb_plotters
+ };
+ struct fb_local_history_window *lhw;
+
+ /* technically degenerate container of */
+ lhw = (struct fb_local_history_window *)fb_cw;
+
+ local_history_redraw(lhw->session, 0, 0, r, &ctx);
+
+ return NSERROR_OK;
+}
+
+/**
+ * Creates the window for the local history view.
+ *
+ * \return NSERROR_OK on success else appropriate error code on faliure.
+ */
+static nserror
+fb_local_history_init(fbtk_widget_t *parent,
+ struct browser_window *bw,
+ struct fb_local_history_window **win_out)
+{
+ struct fb_local_history_window *ncwin;
+ nserror res;
+
+ /* memoise window so it can be represented when necessary
+ * instead of recreating every time.
+ */
+ if ((*win_out) != NULL) {
+ res = local_history_set((*win_out)->session, bw);
+ return res;
+ }
+
+ ncwin = calloc(1, sizeof(*ncwin));
+ if (ncwin == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ ncwin->core.draw = fb_local_history_draw;
+ ncwin->core.key = fb_local_history_key;
+ ncwin->core.mouse = fb_local_history_mouse;
+
+ res = fb_corewindow_init(parent, &ncwin->core);
+ if (res != NSERROR_OK) {
+ free(ncwin);
+ return res;
+ }
+
+ res = local_history_init(ncwin->core.cb_table,
+ (struct core_window *)ncwin,
+ bw,
+ &ncwin->session);
+ if (res != NSERROR_OK) {
+ free(ncwin);
+ return res;
+ }
+
+ *win_out = ncwin;
+
+ return NSERROR_OK;
+}
+
+
+/* exported function documented gtk/history.h */
+nserror fb_local_history_present(fbtk_widget_t *parent,
+ struct browser_window *bw)
+{
+ nserror res;
+ int prnt_width, prnt_height;
+ int width, height;
+
+ res = fb_local_history_init(parent, bw, &local_history_window);
+ if (res == NSERROR_OK) {
+
+ prnt_width = fbtk_get_width(parent);
+ prnt_height = fbtk_get_height(parent);
+
+ /* resize history widget ensureing the drawing area is
+ * no larger than parent window
+ */
+ res = local_history_get_size(local_history_window->session,
+ &width,
+ &height);
+ if (width > prnt_width) {
+ width = prnt_width;
+ }
+ if (height > prnt_height) {
+ height = prnt_height;
+ }
+ /* should update scroll area with contents */
+
+ fbtk_set_zorder(local_history_window->core.wnd, INT_MIN);
+ fbtk_set_mapping(local_history_window->core.wnd, true);
+ }
+
+ return res;
+}
+
+
+/* exported function documented gtk/history.h */
+nserror fb_local_history_hide(void)
+{
+ nserror res = NSERROR_OK;
+
+ if (local_history_window != NULL) {
+ fbtk_set_mapping(local_history_window->core.wnd, false);
+
+ res = local_history_set(local_history_window->session, NULL);
+ }
+
+ return res;
+}
+
+
+/* exported function documented gtk/history.h */
+nserror fb_local_history_destroy(void)
+{
+ nserror res;
+
+ if (local_history_window == NULL) {
+ return NSERROR_OK;
+ }
+
+ res = local_history_fini(local_history_window->session);
+ if (res == NSERROR_OK) {
+ res = fb_corewindow_fini(&local_history_window->core);
+ //gtk_widget_destroy(GTK_WIDGET(local_history_window->wnd));
+ free(local_history_window);
+ local_history_window = NULL;
+ }
+
+ return res;
+
+}
diff --git a/frontends/framebuffer/local_history.h b/frontends/framebuffer/local_history.h
new file mode 100644
index 000000000..929eeacd8
--- /dev/null
+++ b/frontends/framebuffer/local_history.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2017 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Interface to framebuffer local history manager
+ */
+
+#ifndef FB_LOCAL_HISTORY_H
+#define FB_LOCAL_HISTORY_H
+
+struct browser_window;
+
+/**
+ * make the local history window visible.
+ *
+ * \return NSERROR_OK on success else appropriate error code on faliure.
+ */
+nserror fb_local_history_present(fbtk_widget_t *parent, struct browser_window *bw);
+
+/**
+ * hide the local history window from being visible.
+ *
+ * \return NSERROR_OK on success else appropriate error code on faliure.
+ */
+nserror fb_local_history_hide(void);
+
+/**
+ * Destroys the local history window and performs any other necessary cleanup
+ * actions.
+ */
+nserror fb_local_history_destroy(void);
+
+#endif
diff --git a/frontends/framebuffer/localhistory.c b/frontends/framebuffer/localhistory.c
deleted file mode 100644
index 3192f0747..000000000
--- a/frontends/framebuffer/localhistory.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright 2010 Vincent Sanders <vince@simtec.co.uk>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <limits.h>
-
-#include <libnsfb.h>
-#include <libnsfb_plot.h>
-#include <libnsfb_event.h>
-
-#include "desktop/browser_history.h"
-#include "netsurf/plotters.h"
-
-#include "framebuffer/gui.h"
-#include "framebuffer/fbtk.h"
-#include "framebuffer/framebuffer.h"
-
-static int
-localhistory_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi)
-{
- struct gui_localhistory *glh = cbi->context;
- nsfb_bbox_t rbox;
-
- struct redraw_context ctx = {
- .interactive = true,
- .background_images = true,
- .plot = &fb_plotters
- };
-
- rbox.x0 = fbtk_get_absx(widget);
- rbox.y0 = fbtk_get_absy(widget);
-
- rbox.x1 = rbox.x0 + fbtk_get_width(widget);
- rbox.y1 = rbox.y0 + fbtk_get_height(widget);
-
- nsfb_claim(fbtk_get_nsfb(widget), &rbox);
-
- nsfb_plot_rectangle_fill(fbtk_get_nsfb(widget), &rbox, 0xffffffff);
-
- browser_window_history_redraw_rectangle(glh->bw,
- glh->scrollx,
- glh->scrolly,
- fbtk_get_width(widget) + glh->scrollx,
- fbtk_get_height(widget) + glh->scrolly,
- 0, 0, &ctx);
-
- nsfb_update(fbtk_get_nsfb(widget), &rbox);
-
- return 0;
-}
-
-static int
-localhistory_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
-{
- struct gui_localhistory *glh = cbi->context;
-
- if (cbi->event->type != NSFB_EVENT_KEY_UP)
- return 0;
-
- browser_window_history_click(glh->bw, cbi->x, cbi->y, false);
-
- fbtk_set_mapping(glh->window, false);
-
- return 1;
-}
-
-struct gui_localhistory *
-fb_create_localhistory(struct browser_window *bw,
- fbtk_widget_t *parent,
- int furniture_width)
-{
- struct gui_localhistory *glh;
- glh = calloc(1, sizeof(struct gui_localhistory));
-
- if (glh == NULL)
- return NULL;
-
- glh->bw = bw;
-
- /* container window */
- glh->window = fbtk_create_window(parent, 0, 0, 0, 0, 0);
-
- glh->history = fbtk_create_user(glh->window, 0, 0, -furniture_width, -furniture_width, glh);
-
- fbtk_set_handler(glh->history, FBTK_CBT_REDRAW, localhistory_redraw, glh);
- fbtk_set_handler(glh->history, FBTK_CBT_CLICK, localhistory_click, glh);
- /*
- fbtk_set_handler(gw->localhistory, FBTK_CBT_INPUT, fb_browser_window_input, gw);
- fbtk_set_handler(gw->localhistory, FBTK_CBT_POINTERMOVE, fb_browser_window_move, bw);
- */
-
- /* create horizontal scrollbar */
- glh->hscroll = fbtk_create_hscroll(glh->window,
- 0,
- fbtk_get_height(glh->window) - furniture_width,
- fbtk_get_width(glh->window) - furniture_width,
- furniture_width,
- FB_SCROLL_COLOUR,
- FB_FRAME_COLOUR,
- NULL,
- NULL);
-
- glh->vscroll = fbtk_create_vscroll(glh->window,
- fbtk_get_width(glh->window) - furniture_width,
- 0,
- furniture_width,
- fbtk_get_height(glh->window) - furniture_width,
- FB_SCROLL_COLOUR,
- FB_FRAME_COLOUR,
- NULL,
- NULL);
-
- fbtk_create_fill(glh->window,
- fbtk_get_width(glh->window) - furniture_width,
- fbtk_get_height(glh->window) - furniture_width,
- furniture_width,
- furniture_width,
- FB_FRAME_COLOUR);
-
- return glh;
-}
-
-void
-fb_localhistory_map(struct gui_localhistory * glh)
-{
- fbtk_set_zorder(glh->window, INT_MIN);
- fbtk_set_mapping(glh->window, true);
-}
diff --git a/frontends/framebuffer/res/Messages b/frontends/framebuffer/res/Messages
deleted file mode 120000
index 72c9eff90..000000000
--- a/frontends/framebuffer/res/Messages
+++ /dev/null
@@ -1 +0,0 @@
-../../../!NetSurf/Resources/en/Messages \ No newline at end of file
diff --git a/frontends/framebuffer/res/adblock.css b/frontends/framebuffer/res/adblock.css
index ff2485622..0d12aaa7c 120000
--- a/frontends/framebuffer/res/adblock.css
+++ b/frontends/framebuffer/res/adblock.css
@@ -1 +1 @@
-../../../!NetSurf/Resources/AdBlock,f79 \ No newline at end of file
+../../../resources/adblock.css \ No newline at end of file
diff --git a/frontends/framebuffer/res/credits.html b/frontends/framebuffer/res/credits.html
index 1ba17392b..b43a1a06c 120000
--- a/frontends/framebuffer/res/credits.html
+++ b/frontends/framebuffer/res/credits.html
@@ -1 +1 @@
-../../../!NetSurf/Resources/en/credits.html,faf \ No newline at end of file
+../../../resources/en/credits.html \ No newline at end of file
diff --git a/frontends/framebuffer/res/default.css b/frontends/framebuffer/res/default.css
index a8579eb7c..fa3ae6c26 120000
--- a/frontends/framebuffer/res/default.css
+++ b/frontends/framebuffer/res/default.css
@@ -1 +1 @@
-../../../!NetSurf/Resources/CSS,f79 \ No newline at end of file
+../../../resources/default.css \ No newline at end of file
diff --git a/frontends/framebuffer/res/internal.css b/frontends/framebuffer/res/internal.css
index 17f9f1504..5583a9811 120000
--- a/frontends/framebuffer/res/internal.css
+++ b/frontends/framebuffer/res/internal.css
@@ -1 +1 @@
-../../../!NetSurf/Resources/internal.css,f79 \ No newline at end of file
+../../../resources/internal.css \ No newline at end of file
diff --git a/frontends/framebuffer/res/licence.html b/frontends/framebuffer/res/licence.html
index 147dd6db2..c0c1e6630 120000
--- a/frontends/framebuffer/res/licence.html
+++ b/frontends/framebuffer/res/licence.html
@@ -1 +1 @@
-../../../!NetSurf/Resources/en/licence.html,faf \ No newline at end of file
+../../../resources/en/licence.html \ No newline at end of file
diff --git a/frontends/framebuffer/res/maps.html b/frontends/framebuffer/res/maps.html
index 28362130a..05bcdc42e 120000
--- a/frontends/framebuffer/res/maps.html
+++ b/frontends/framebuffer/res/maps.html
@@ -1 +1 @@
-../../../!NetSurf/Resources/en/welcome.html,faf \ No newline at end of file
+../../../resources/en/maps.html \ No newline at end of file
diff --git a/frontends/framebuffer/res/netsurf.png b/frontends/framebuffer/res/netsurf.png
index 905512c25..d0ab72a5e 120000
--- a/frontends/framebuffer/res/netsurf.png
+++ b/frontends/framebuffer/res/netsurf.png
@@ -1 +1 @@
-../../../!NetSurf/Resources/netsurf.png,b60 \ No newline at end of file
+../../../resources/netsurf.png \ No newline at end of file
diff --git a/frontends/framebuffer/res/quirks.css b/frontends/framebuffer/res/quirks.css
index 88aabe48c..1e752cb9e 120000
--- a/frontends/framebuffer/res/quirks.css
+++ b/frontends/framebuffer/res/quirks.css
@@ -1 +1 @@
-../../../!NetSurf/Resources/Quirks,f79 \ No newline at end of file
+../../../resources/quirks.css \ No newline at end of file
diff --git a/frontends/framebuffer/res/welcome.html b/frontends/framebuffer/res/welcome.html
index 28362130a..d5220f90a 120000
--- a/frontends/framebuffer/res/welcome.html
+++ b/frontends/framebuffer/res/welcome.html
@@ -1 +1 @@
-../../../!NetSurf/Resources/en/welcome.html,faf \ No newline at end of file
+../../../resources/en/welcome.html \ No newline at end of file
diff --git a/frontends/framebuffer/schedule.c b/frontends/framebuffer/schedule.c
index 581ad72f1..6d1711236 100644
--- a/frontends/framebuffer/schedule.c
+++ b/frontends/framebuffer/schedule.c
@@ -24,12 +24,6 @@
#include "framebuffer/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;
@@ -63,7 +57,7 @@ static nserror schedule_remove(void (*callback)(void *p), void *p)
return NSERROR_OK;
}
- SRLOG("removing %p, %p", callback, p);
+ NSLOG(schedule, DEBUG, "removing %p, %p", callback, p);
cur_nscb = schedule_list;
prev_nscb = NULL;
@@ -73,7 +67,8 @@ static nserror schedule_remove(void (*callback)(void *p), void *p)
(cur_nscb->p == p)) {
/* item to remove */
- SRLOG("callback entry %p removing %p(%p)",
+ NSLOG(schedule, DEBUG,
+ "callback entry %p removing %p(%p)",
cur_nscb, cur_nscb->callback, cur_nscb->p);
/* remove callback */
@@ -109,7 +104,7 @@ nserror framebuffer_schedule(int tival, void (*callback)(void *p), void *p)
return ret;
}
- SRLOG("Adding %p(%p) in %d", callback, p, tival);
+ NSLOG(schedule, DEBUG, "Adding %p(%p) in %d", callback, p, tival);
tv.tv_sec = tival / 1000; /* miliseconds to seconds */
tv.tv_usec = (tival % 1000) * 1000; /* remainder to microseconds */
@@ -190,7 +185,9 @@ int schedule_run(void)
/* make rettime relative to now */
timersub(&nexttime, &tv, &rettime);
- SRLOG("returning time to next event as %ldms",(rettime.tv_sec * 1000) + (rettime.tv_usec / 1000));
+ NSLOG(schedule, DEBUG,
+ "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);
@@ -203,12 +200,14 @@ void list_schedule(void)
gettimeofday(&tv, NULL);
- LOG("schedule list at %ld:%ld", tv.tv_sec, tv.tv_usec);
+ NSLOG(netsurf, INFO, "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);
+ NSLOG(netsurf, INFO, "Schedule %p at %ld:%ld", cur_nscb,
+ cur_nscb->tv.tv_sec, cur_nscb->tv.tv_usec);
cur_nscb = cur_nscb->next;
}
}