Bug Summary

File:frontends/framebuffer/gui.c
Warning:line 1698, column 3
Value stored to 'widget' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name gui.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/var/lib/jenkins/workspace/scan-build-netsurf -resource-dir /usr/lib/llvm-14/lib/clang/14.0.6 -I . -I include -I build/Linux-framebuffer -I frontends -I content/handlers -D WITH_JPEG -U WITH_PDF_EXPORT -D LIBICONV_PLUG -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -I /usr/include/x86_64-linux-gnu -D WITH_CURL -D WITH_OPENSSL -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D UTF8PROC_EXPORTS -D WITH_UTF8PROC -D WITH_WEBP -I /usr/include/libpng16 -D WITH_PNG -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include/ -D WITH_BMP -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_GIF -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NS_SVG -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NSSPRITE -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NSPSL -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D WITH_NSLOG -D NETSURF_UA_FORMAT_STRING="Mozilla/5.0 (%s) NetSurf/%d.%d" -D NETSURF_HOMEPAGE="about:welcome" -D NETSURF_LOG_LEVEL=VERBOSE -D NETSURF_BUILTIN_LOG_FILTER="(level:WARNING || cat:jserrors)" -D NETSURF_BUILTIN_VERBOSE_FILTER="(level:VERBOSE || cat:jserrors)" -D STMTEXPR=1 -D nsframebuffer -D small -D NETSURF_FB_RESPATH="${HOME}/.netsurf/:${NETSURFRES}:/var/lib/jenkins/artifacts-x86_64-linux-gnu/share/netsurf:./frontends/framebuffer/res" -D NETSURF_FB_FONTPATH="/usr/share/fonts/truetype/dejavu:/usr/share/fonts/truetype/msttcorefonts" -D NETSURF_FB_FONT_SANS_SERIF="DejaVuSans.ttf" -D NETSURF_FB_FONT_SANS_SERIF_BOLD="DejaVuSans-Bold.ttf" -D NETSURF_FB_FONT_SANS_SERIF_ITALIC="DejaVuSans-Oblique.ttf" -D NETSURF_FB_FONT_SANS_SERIF_ITALIC_BOLD="DejaVuSans-BoldOblique.ttf" -D NETSURF_FB_FONT_SERIF="DejaVuSerif.ttf" -D NETSURF_FB_FONT_SERIF_BOLD="DejaVuSerif-Bold.ttf" -D NETSURF_FB_FONT_MONOSPACE="DejaVuSansMono.ttf" -D NETSURF_FB_FONT_MONOSPACE_BOLD="DejaVuSansMono-Bold.ttf" -D NETSURF_FB_FONT_CURSIVE="Comic_Sans_MS.ttf" -D NETSURF_FB_FONT_FANTASY="Impact.ttf" -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D _POSIX_C_SOURCE=200809L -D _XOPEN_SOURCE=700 -D _BSD_SOURCE -D _DEFAULT_SOURCE -D _NETBSD_SOURCE -D DUK_OPT_HAVE_CUSTOM_H -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wwrite-strings -Wno-unused-parameter -Wno-unused-but-set-variable -std=c99 -fconst-strings -fdebug-compilation-dir=/var/lib/jenkins/workspace/scan-build-netsurf -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-display-progress -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /var/lib/jenkins/workspace/scan-build-netsurf/clangScanBuildReports/2024-03-19-091938-614606-1 -x c frontends/framebuffer/gui.c
1/*
2 * Copyright 2008, 2014 Vincent Sanders <vince@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <stdint.h>
20#include <limits.h>
21#include <getopt.h>
22#include <assert.h>
23#include <string.h>
24#include <stdbool.h>
25#include <stdlib.h>
26#include <nsutils/time.h>
27
28#include <libnsfb.h>
29#include <libnsfb_plot.h>
30#include <libnsfb_event.h>
31
32#include "utils/utils.h"
33#include "utils/nsoption.h"
34#include "utils/filepath.h"
35#include "utils/log.h"
36#include "utils/messages.h"
37#include "netsurf/browser_window.h"
38#include "netsurf/keypress.h"
39#include "desktop/browser_history.h"
40#include "netsurf/plotters.h"
41#include "netsurf/window.h"
42#include "netsurf/misc.h"
43#include "netsurf/netsurf.h"
44#include "netsurf/cookie_db.h"
45#include "content/fetch.h"
46
47#include "framebuffer/gui.h"
48#include "framebuffer/fbtk.h"
49#include "framebuffer/framebuffer.h"
50#include "framebuffer/schedule.h"
51#include "framebuffer/findfile.h"
52#include "framebuffer/image_data.h"
53#include "framebuffer/font.h"
54#include "framebuffer/clipboard.h"
55#include "framebuffer/fetch.h"
56#include "framebuffer/bitmap.h"
57#include "framebuffer/local_history.h"
58
59
60#define NSFB_TOOLBAR_DEFAULT_LAYOUT"blfsrutc" "blfsrutc"
61
62fbtk_widget_t *fbtk;
63
64static bool_Bool fb_complete = false0;
65
66struct gui_window *input_window = NULL((void*)0);
67struct gui_window *search_current_window;
68struct gui_window *window_list = NULL((void*)0);
69
70/* private data for browser user widget */
71struct browser_widget_s {
72 struct browser_window *bw; /**< The browser window connected to this gui window */
73 int scrollx, scrolly; /**< scroll offsets. */
74
75 /* Pending window redraw state. */
76 bool_Bool redraw_required; /**< flag indicating the foreground loop
77 * needs to redraw the browser widget.
78 */
79 bbox_t redraw_box; /**< Area requiring redraw. */
80 bool_Bool pan_required; /**< flag indicating the foreground loop
81 * needs to pan the window.
82 */
83 int panx, pany; /**< Panning required. */
84};
85
86static struct gui_drag {
87 enum state {
88 GUI_DRAG_NONE,
89 GUI_DRAG_PRESSED,
90 GUI_DRAG_DRAG
91 } state;
92 int button;
93 int x;
94 int y;
95 bool_Bool grabbed_pointer;
96} gui_drag;
97
98
99/**
100 * Cause an abnormal program termination.
101 *
102 * \note This never returns and is intended to terminate without any cleanup.
103 *
104 * \param error The message to display to the user.
105 */
106static void die(const char *error)
107{
108 fprintf(stderrstderr, "%s\n", error);
109 exit(1);
110}
111
112
113/**
114 * Warn the user of an event.
115 *
116 * \param[in] warning A warning looked up in the message translation table
117 * \param[in] detail Additional text to be displayed or NULL.
118 * \return NSERROR_OK on success or error code if there was a
119 * faliure displaying the message to the user.
120 */
121static nserror fb_warn_user(const char *warning, const char *detail)
122{
123 NSLOG(netsurf, INFO, "%s %s", warning, detail)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 123
, }; nslog__log(&_nslog_ctx, "%s %s", warning, detail); }
} while(0)
;
124 return NSERROR_OK;
125}
126
127/* queue a redraw operation, co-ordinates are relative to the window */
128static void
129fb_queue_redraw(struct fbtk_widget_s *widget, int x0, int y0, int x1, int y1)
130{
131 struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
132
133 bwidget->redraw_box.x0 = min(bwidget->redraw_box.x0, x0)(((bwidget->redraw_box.x0)<(x0))?(bwidget->redraw_box
.x0):(x0))
;
134 bwidget->redraw_box.y0 = min(bwidget->redraw_box.y0, y0)(((bwidget->redraw_box.y0)<(y0))?(bwidget->redraw_box
.y0):(y0))
;
135 bwidget->redraw_box.x1 = max(bwidget->redraw_box.x1, x1)(((bwidget->redraw_box.x1)>(x1))?(bwidget->redraw_box
.x1):(x1))
;
136 bwidget->redraw_box.y1 = max(bwidget->redraw_box.y1, y1)(((bwidget->redraw_box.y1)>(y1))?(bwidget->redraw_box
.y1):(y1))
;
137
138 if (fbtk_clip_to_widget(widget, &bwidget->redraw_box)) {
139 bwidget->redraw_required = true1;
140 fbtk_request_redraw(widget);
141 } else {
142 bwidget->redraw_box.y0 = bwidget->redraw_box.x0 = INT_MAX2147483647;
143 bwidget->redraw_box.y1 = bwidget->redraw_box.x1 = -(INT_MAX2147483647);
144 bwidget->redraw_required = false0;
145 }
146}
147
148/* queue a window scroll */
149static void
150widget_scroll_y(struct gui_window *gw, int y, bool_Bool abs)
151{
152 struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser);
153 int content_width, content_height;
154 int height;
155
156 NSLOG(netsurf, DEEPDEBUG, "window scroll")do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_DEEPDEBUG, "frontends/framebuffer/gui.c", sizeof
("frontends/framebuffer/gui.c") - 1, __PRETTY_FUNCTION__, sizeof
(__PRETTY_FUNCTION__) - 1, 156, }; nslog__log(&_nslog_ctx
, "window scroll"); } } while(0)
;
157 if (abs) {
158 bwidget->pany = y - bwidget->scrolly;
159 } else {
160 bwidget->pany += y;
161 }
162
163 browser_window_get_extents(gw->bw, true1,
164 &content_width, &content_height);
165
166 height = fbtk_get_height(gw->browser);
167
168 /* dont pan off the top */
169 if ((bwidget->scrolly + bwidget->pany) < 0)
170 bwidget->pany = -bwidget->scrolly;
171
172 /* do not pan off the bottom of the content */
173 if ((bwidget->scrolly + bwidget->pany) > (content_height - height))
174 bwidget->pany = (content_height - height) - bwidget->scrolly;
175
176 if (bwidget->pany == 0)
177 return;
178
179 bwidget->pan_required = true1;
180
181 fbtk_request_redraw(gw->browser);
182
183 fbtk_set_scroll_position(gw->vscroll, bwidget->scrolly + bwidget->pany);
184}
185
186/* queue a window scroll */
187static void
188widget_scroll_x(struct gui_window *gw, int x, bool_Bool abs)
189{
190 struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser);
191 int content_width, content_height;
192 int width;
193
194 if (abs) {
195 bwidget->panx = x - bwidget->scrollx;
196 } else {
197 bwidget->panx += x;
198 }
199
200 browser_window_get_extents(gw->bw, true1,
201 &content_width, &content_height);
202
203 width = fbtk_get_width(gw->browser);
204
205 /* dont pan off the left */
206 if ((bwidget->scrollx + bwidget->panx) < 0)
207 bwidget->panx = - bwidget->scrollx;
208
209 /* do not pan off the right of the content */
210 if ((bwidget->scrollx + bwidget->panx) > (content_width - width))
211 bwidget->panx = (content_width - width) - bwidget->scrollx;
212
213 if (bwidget->panx == 0)
214 return;
215
216 bwidget->pan_required = true1;
217
218 fbtk_request_redraw(gw->browser);
219
220 fbtk_set_scroll_position(gw->hscroll, bwidget->scrollx + bwidget->panx);
221}
222
223static void
224fb_pan(fbtk_widget_t *widget,
225 struct browser_widget_s *bwidget,
226 struct browser_window *bw)
227{
228 int x;
229 int y;
230 int width;
231 int height;
232 nsfb_bbox_t srcbox;
233 nsfb_bbox_t dstbox;
234
235 nsfb_t *nsfb = fbtk_get_nsfb(widget);
236
237 height = fbtk_get_height(widget);
238 width = fbtk_get_width(widget);
239
240 NSLOG(netsurf, DEEPDEBUG, "panning %d, %d",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_DEEPDEBUG, "frontends/framebuffer/gui.c", sizeof
("frontends/framebuffer/gui.c") - 1, __PRETTY_FUNCTION__, sizeof
(__PRETTY_FUNCTION__) - 1, 241, }; nslog__log(&_nslog_ctx
, "panning %d, %d", bwidget->panx, bwidget->pany); } } while
(0)
241 bwidget->panx, bwidget->pany)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_DEEPDEBUG, "frontends/framebuffer/gui.c", sizeof
("frontends/framebuffer/gui.c") - 1, __PRETTY_FUNCTION__, sizeof
(__PRETTY_FUNCTION__) - 1, 241, }; nslog__log(&_nslog_ctx
, "panning %d, %d", bwidget->panx, bwidget->pany); } } while
(0)
;
242
243 x = fbtk_get_absx(widget);
244 y = fbtk_get_absy(widget);
245
246 /* if the pan exceeds the viewport size just redraw the whole area */
247 if (bwidget->pany >= height || bwidget->pany <= -height ||
248 bwidget->panx >= width || bwidget->panx <= -width) {
249
250 bwidget->scrolly += bwidget->pany;
251 bwidget->scrollx += bwidget->panx;
252 fb_queue_redraw(widget, 0, 0, width, height);
253
254 /* ensure we don't try to scroll again */
255 bwidget->panx = 0;
256 bwidget->pany = 0;
257 bwidget->pan_required = false0;
258 return;
259 }
260
261 if (bwidget->pany < 0) {
262 /* pan up by less then viewport height */
263 srcbox.x0 = x;
264 srcbox.y0 = y;
265 srcbox.x1 = srcbox.x0 + width;
266 srcbox.y1 = srcbox.y0 + height + bwidget->pany;
267
268 dstbox.x0 = x;
269 dstbox.y0 = y - bwidget->pany;
270 dstbox.x1 = dstbox.x0 + width;
271 dstbox.y1 = dstbox.y0 + height + bwidget->pany;
272
273 /* move part that remains visible up */
274 nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox);
275
276 /* redraw newly exposed area */
277 bwidget->scrolly += bwidget->pany;
278 fb_queue_redraw(widget, 0, 0, width, - bwidget->pany);
279
280 } else if (bwidget->pany > 0) {
281 /* pan down by less then viewport height */
282 srcbox.x0 = x;
283 srcbox.y0 = y + bwidget->pany;
284 srcbox.x1 = srcbox.x0 + width;
285 srcbox.y1 = srcbox.y0 + height - bwidget->pany;
286
287 dstbox.x0 = x;
288 dstbox.y0 = y;
289 dstbox.x1 = dstbox.x0 + width;
290 dstbox.y1 = dstbox.y0 + height - bwidget->pany;
291
292 /* move part that remains visible down */
293 nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox);
294
295 /* redraw newly exposed area */
296 bwidget->scrolly += bwidget->pany;
297 fb_queue_redraw(widget, 0, height - bwidget->pany,
298 width, height);
299 }
300
301 if (bwidget->panx < 0) {
302 /* pan left by less then viewport width */
303 srcbox.x0 = x;
304 srcbox.y0 = y;
305 srcbox.x1 = srcbox.x0 + width + bwidget->panx;
306 srcbox.y1 = srcbox.y0 + height;
307
308 dstbox.x0 = x - bwidget->panx;
309 dstbox.y0 = y;
310 dstbox.x1 = dstbox.x0 + width + bwidget->panx;
311 dstbox.y1 = dstbox.y0 + height;
312
313 /* move part that remains visible left */
314 nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox);
315
316 /* redraw newly exposed area */
317 bwidget->scrollx += bwidget->panx;
318 fb_queue_redraw(widget, 0, 0, -bwidget->panx, height);
319
320 } else if (bwidget->panx > 0) {
321 /* pan right by less then viewport width */
322 srcbox.x0 = x + bwidget->panx;
323 srcbox.y0 = y;
324 srcbox.x1 = srcbox.x0 + width - bwidget->panx;
325 srcbox.y1 = srcbox.y0 + height;
326
327 dstbox.x0 = x;
328 dstbox.y0 = y;
329 dstbox.x1 = dstbox.x0 + width - bwidget->panx;
330 dstbox.y1 = dstbox.y0 + height;
331
332 /* move part that remains visible right */
333 nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox);
334
335 /* redraw newly exposed area */
336 bwidget->scrollx += bwidget->panx;
337 fb_queue_redraw(widget, width - bwidget->panx, 0,
338 width, height);
339 }
340
341 bwidget->pan_required = false0;
342 bwidget->panx = 0;
343 bwidget->pany = 0;
344}
345
346static void
347fb_redraw(fbtk_widget_t *widget,
348 struct browser_widget_s *bwidget,
349 struct browser_window *bw)
350{
351 int x;
352 int y;
353 int caret_x, caret_y, caret_h;
354 struct rect clip;
355 struct redraw_context ctx = {
356 .interactive = true1,
357 .background_images = true1,
358 .plot = &fb_plotters
359 };
360 nsfb_t *nsfb = fbtk_get_nsfb(widget);
361
362 x = fbtk_get_absx(widget);
363 y = fbtk_get_absy(widget);
364
365 /* adjust clipping co-ordinates according to window location */
366 bwidget->redraw_box.y0 += y;
367 bwidget->redraw_box.y1 += y;
368 bwidget->redraw_box.x0 += x;
369 bwidget->redraw_box.x1 += x;
370
371 nsfb_claim(nsfb, &bwidget->redraw_box);
372
373 /* redraw bounding box is relative to window */
374 clip.x0 = bwidget->redraw_box.x0;
375 clip.y0 = bwidget->redraw_box.y0;
376 clip.x1 = bwidget->redraw_box.x1;
377 clip.y1 = bwidget->redraw_box.y1;
378
379 browser_window_redraw(bw,
380 x - bwidget->scrollx,
381 y - bwidget->scrolly,
382 &clip, &ctx);
383
384 if (fbtk_get_caret(widget, &caret_x, &caret_y, &caret_h)) {
385 /* This widget has caret, so render it */
386 nsfb_bbox_t line;
387 nsfb_plot_pen_t pen;
388
389 line.x0 = x - bwidget->scrollx + caret_x;
390 line.y0 = y - bwidget->scrolly + caret_y;
391 line.x1 = x - bwidget->scrollx + caret_x;
392 line.y1 = y - bwidget->scrolly + caret_y + caret_h;
393
394 pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
395 pen.stroke_width = 1;
396 pen.stroke_colour = 0xFF0000FF;
397
398 nsfb_plot_line(nsfb, &line, &pen);
399 }
400
401 nsfb_update(fbtk_get_nsfb(widget), &bwidget->redraw_box);
402
403 bwidget->redraw_box.y0 = bwidget->redraw_box.x0 = INT_MAX2147483647;
404 bwidget->redraw_box.y1 = bwidget->redraw_box.x1 = INT_MIN(-2147483647 -1);
405 bwidget->redraw_required = false0;
406}
407
408static int
409fb_browser_window_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi)
410{
411 struct gui_window *gw = cbi->context;
412 struct browser_widget_s *bwidget;
413
414 bwidget = fbtk_get_userpw(widget);
415 if (bwidget == NULL((void*)0)) {
416 NSLOG(netsurf, INFO,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 417
, }; nslog__log(&_nslog_ctx, "browser widget from widget %p was null"
, widget); } } while(0)
417 "browser widget from widget %p was null", widget)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 417
, }; nslog__log(&_nslog_ctx, "browser widget from widget %p was null"
, widget); } } while(0)
;
418 return -1;
419 }
420
421 if (bwidget->pan_required) {
422 fb_pan(widget, bwidget, gw->bw);
423 }
424
425 if (bwidget->redraw_required) {
426 fb_redraw(widget, bwidget, gw->bw);
427 } else {
428 bwidget->redraw_box.x0 = 0;
429 bwidget->redraw_box.y0 = 0;
430 bwidget->redraw_box.x1 = fbtk_get_width(widget);
431 bwidget->redraw_box.y1 = fbtk_get_height(widget);
432 fb_redraw(widget, bwidget, gw->bw);
433 }
434 return 0;
435}
436
437static int fb_browser_window_destroy(fbtk_widget_t *widget,
438 fbtk_callback_info *cbi)
439{
440 struct browser_widget_s *browser_widget;
441
442 if (widget == NULL((void*)0)) {
443 return 0;
444 }
445
446 /* Free private data */
447 browser_widget = fbtk_get_userpw(widget);
448 free(browser_widget);
449
450 return 0;
451}
452
453static void
454framebuffer_surface_iterator(void *ctx, const char *name, enum nsfb_type_e type)
455{
456 const char *arg0 = ctx;
457
458 fprintf(stderrstderr, "%s: %s\n", arg0, name);
459}
460
461static enum nsfb_type_e fetype = NSFB_SURFACE_COUNT;
462static const char *fename;
463static int febpp;
464static int fewidth;
465static int feheight;
466static const char *feurl;
467
468static void
469framebuffer_pick_default_fename(void *ctx, const char *name, enum nsfb_type_e type)
470{
471 if (type < fetype) {
472 fename = name;
473 }
474}
475
476static bool_Bool
477process_cmdline(int argc, char** argv)
478{
479 int opt;
480 int option_index;
481 static struct option long_options[] = {
482 {0, 0, 0, 0 }
483 }; /* no long options */
484
485 NSLOG(netsurf, INFO, "argc %d, argv %p", argc, argv)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 485
, }; nslog__log(&_nslog_ctx, "argc %d, argv %p", argc, argv
); } } while(0)
;
486
487 nsfb_enumerate_surface_types(framebuffer_pick_default_fename, NULL((void*)0));
488
489 febpp = 32;
490
491 fewidth = nsoption_int(window_width)(nsoptions[NSOPTION_window_width].value.i);
492 if (fewidth <= 0) {
493 fewidth = 800;
494 }
495 feheight = nsoption_int(window_height)(nsoptions[NSOPTION_window_height].value.i);
496 if (feheight <= 0) {
497 feheight = 600;
498 }
499
500 if ((nsoption_charp(homepage_url)(nsoptions[NSOPTION_homepage_url].value.s) != NULL((void*)0)) &&
501 (nsoption_charp(homepage_url)(nsoptions[NSOPTION_homepage_url].value.s)[0] != '\0')) {
502 feurl = nsoption_charp(homepage_url)(nsoptions[NSOPTION_homepage_url].value.s);
503 } else {
504 feurl = NETSURF_HOMEPAGE"about:welcome";
505 }
506
507 while((opt = getopt_long(argc, argv, "f:b:w:h:",
508 long_options, &option_index)) != -1) {
509 switch (opt) {
510 case 'f':
511 fename = optarg;
512 break;
513
514 case 'b':
515 febpp = atoi(optarg);
516 break;
517
518 case 'w':
519 fewidth = atoi(optarg);
520 break;
521
522 case 'h':
523 feheight = atoi(optarg);
524 break;
525
526 default:
527 fprintf(stderrstderr,
528 "Usage: %s [-f frontend] [-b bpp] [-w width] [-h height] <url>\n",
529 argv[0]);
530 return false0;
531 }
532 }
533
534 if (optind < argc) {
535 feurl = argv[optind];
536 }
537
538 if (nsfb_type_from_name(fename) == NSFB_SURFACE_NONE) {
539 if (strcmp(fename, "?") != 0) {
540 fprintf(stderrstderr,
541 "%s: Unknown surface `%s`\n", argv[0], fename);
542 }
543 fprintf(stderrstderr, "%s: Valid surface names are:\n", argv[0]);
544 nsfb_enumerate_surface_types(framebuffer_surface_iterator, argv[0]);
545 return false0;
546 }
547
548 return true1;
549}
550
551/**
552 * Set option defaults for framebuffer frontend
553 *
554 * @param defaults The option table to update.
555 * @return error status.
556 */
557static nserror set_defaults(struct nsoption_s *defaults)
558{
559 /* Set defaults for absent option strings */
560 nsoption_setnull_charp(cookie_file, strdup("~/.netsurf/Cookies"))do { if (nsoptions[NSOPTION_cookie_file].value.s == ((void*)0
)) { nsoption_set_tbl_charp(nsoptions, NSOPTION_cookie_file, strdup
("~/.netsurf/Cookies")); } else { free(strdup("~/.netsurf/Cookies"
)); } } while (0)
;
561 nsoption_setnull_charp(cookie_jar, strdup("~/.netsurf/Cookies"))do { if (nsoptions[NSOPTION_cookie_jar].value.s == ((void*)0)
) { nsoption_set_tbl_charp(nsoptions, NSOPTION_cookie_jar, strdup
("~/.netsurf/Cookies")); } else { free(strdup("~/.netsurf/Cookies"
)); } } while (0)
;
562
563 if (nsoption_charp(cookie_file)(nsoptions[NSOPTION_cookie_file].value.s) == NULL((void*)0) ||
564 nsoption_charp(cookie_jar)(nsoptions[NSOPTION_cookie_jar].value.s) == NULL((void*)0)) {
565 NSLOG(netsurf, INFO, "Failed initialising cookie options")do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 565
, }; nslog__log(&_nslog_ctx, "Failed initialising cookie options"
); } } while(0)
;
566 return NSERROR_BAD_PARAMETER;
567 }
568
569 /* set system colours for framebuffer ui */
570 nsoption_set_colour(sys_colour_ActiveBorder, 0x00000000)nsoptions[NSOPTION_sys_colour_ActiveBorder].value.c = 0x00000000;
571 nsoption_set_colour(sys_colour_ActiveCaption, 0x00ddddcc)nsoptions[NSOPTION_sys_colour_ActiveCaption].value.c = 0x00ddddcc;
572 nsoption_set_colour(sys_colour_AppWorkspace, 0x00eeeeee)nsoptions[NSOPTION_sys_colour_AppWorkspace].value.c = 0x00eeeeee;
573 nsoption_set_colour(sys_colour_Background, 0x00aa0000)nsoptions[NSOPTION_sys_colour_Background].value.c = 0x00aa0000;
574 nsoption_set_colour(sys_colour_ButtonFace, 0x00dddddd)nsoptions[NSOPTION_sys_colour_ButtonFace].value.c = 0x00dddddd;
575 nsoption_set_colour(sys_colour_ButtonHighlight, 0x00cccccc)nsoptions[NSOPTION_sys_colour_ButtonHighlight].value.c = 0x00cccccc;
576 nsoption_set_colour(sys_colour_ButtonShadow, 0x00bbbbbb)nsoptions[NSOPTION_sys_colour_ButtonShadow].value.c = 0x00bbbbbb;
577 nsoption_set_colour(sys_colour_ButtonText, 0x00000000)nsoptions[NSOPTION_sys_colour_ButtonText].value.c = 0x00000000;
578 nsoption_set_colour(sys_colour_CaptionText, 0x00000000)nsoptions[NSOPTION_sys_colour_CaptionText].value.c = 0x00000000;
579 nsoption_set_colour(sys_colour_GrayText, 0x00777777)nsoptions[NSOPTION_sys_colour_GrayText].value.c = 0x00777777;
580 nsoption_set_colour(sys_colour_Highlight, 0x00ee0000)nsoptions[NSOPTION_sys_colour_Highlight].value.c = 0x00ee0000;
581 nsoption_set_colour(sys_colour_HighlightText, 0x00000000)nsoptions[NSOPTION_sys_colour_HighlightText].value.c = 0x00000000;
582 nsoption_set_colour(sys_colour_InactiveBorder, 0x00000000)nsoptions[NSOPTION_sys_colour_InactiveBorder].value.c = 0x00000000;
583 nsoption_set_colour(sys_colour_InactiveCaption, 0x00ffffff)nsoptions[NSOPTION_sys_colour_InactiveCaption].value.c = 0x00ffffff;
584 nsoption_set_colour(sys_colour_InactiveCaptionText, 0x00cccccc)nsoptions[NSOPTION_sys_colour_InactiveCaptionText].value.c = 0x00cccccc;
585 nsoption_set_colour(sys_colour_InfoBackground, 0x00aaaaaa)nsoptions[NSOPTION_sys_colour_InfoBackground].value.c = 0x00aaaaaa;
586 nsoption_set_colour(sys_colour_InfoText, 0x00000000)nsoptions[NSOPTION_sys_colour_InfoText].value.c = 0x00000000;
587 nsoption_set_colour(sys_colour_Menu, 0x00aaaaaa)nsoptions[NSOPTION_sys_colour_Menu].value.c = 0x00aaaaaa;
588 nsoption_set_colour(sys_colour_MenuText, 0x00000000)nsoptions[NSOPTION_sys_colour_MenuText].value.c = 0x00000000;
589 nsoption_set_colour(sys_colour_Scrollbar, 0x00aaaaaa)nsoptions[NSOPTION_sys_colour_Scrollbar].value.c = 0x00aaaaaa;
590 nsoption_set_colour(sys_colour_ThreeDDarkShadow, 0x00555555)nsoptions[NSOPTION_sys_colour_ThreeDDarkShadow].value.c = 0x00555555;
591 nsoption_set_colour(sys_colour_ThreeDFace, 0x00dddddd)nsoptions[NSOPTION_sys_colour_ThreeDFace].value.c = 0x00dddddd;
592 nsoption_set_colour(sys_colour_ThreeDHighlight, 0x00aaaaaa)nsoptions[NSOPTION_sys_colour_ThreeDHighlight].value.c = 0x00aaaaaa;
593 nsoption_set_colour(sys_colour_ThreeDLightShadow, 0x00999999)nsoptions[NSOPTION_sys_colour_ThreeDLightShadow].value.c = 0x00999999;
594 nsoption_set_colour(sys_colour_ThreeDShadow, 0x00777777)nsoptions[NSOPTION_sys_colour_ThreeDShadow].value.c = 0x00777777;
595 nsoption_set_colour(sys_colour_Window, 0x00aaaaaa)nsoptions[NSOPTION_sys_colour_Window].value.c = 0x00aaaaaa;
596 nsoption_set_colour(sys_colour_WindowFrame, 0x00000000)nsoptions[NSOPTION_sys_colour_WindowFrame].value.c = 0x00000000;
597 nsoption_set_colour(sys_colour_WindowText, 0x00000000)nsoptions[NSOPTION_sys_colour_WindowText].value.c = 0x00000000;
598
599 return NSERROR_OK;
600}
601
602
603/**
604 * Ensures output logging stream is correctly configured
605 */
606static bool_Bool nslog_stream_configure(FILE *fptr)
607{
608 /* set log stream to be non-buffering */
609 setbuf(fptr, NULL((void*)0));
610
611 return true1;
612}
613
614static void framebuffer_run(void)
615{
616 nsfb_event_t event;
617 int timeout; /* timeout in miliseconds */
618
619 while (fb_complete != true1) {
620 /* run the scheduler and discover how long to wait for
621 * the next event.
622 */
623 timeout = schedule_run();
624
625 /* if redraws are pending do not wait for event,
626 * return immediately
627 */
628 if (fbtk_get_redraw_pending(fbtk))
629 timeout = 0;
630
631 if (fbtk_event(fbtk, &event, timeout)) {
632 if ((event.type == NSFB_EVENT_CONTROL) &&
633 (event.value.controlcode == NSFB_CONTROL_QUIT))
634 fb_complete = true1;
635 }
636
637 fbtk_redraw(fbtk);
638 }
639}
640
641static void gui_quit(void)
642{
643 NSLOG(netsurf, INFO, "gui_quit")do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 643
, }; nslog__log(&_nslog_ctx, "gui_quit"); } } while(0)
;
644
645 urldb_save_cookies(nsoption_charp(cookie_jar)(nsoptions[NSOPTION_cookie_jar].value.s));
646
647 framebuffer_finalise();
648}
649
650/* called back when click in browser window */
651static int
652fb_browser_window_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
653{
654 struct gui_window *gw = cbi->context;
655 struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
656 browser_mouse_state mouse;
657 int x = cbi->x + bwidget->scrollx;
658 int y = cbi->y + bwidget->scrolly;
659 uint64_t time_now;
660 static struct {
661 enum { CLICK_SINGLE, CLICK_DOUBLE, CLICK_TRIPLE } type;
662 uint64_t time;
663 } last_click;
664
665 if (cbi->event->type != NSFB_EVENT_KEY_DOWN &&
666 cbi->event->type != NSFB_EVENT_KEY_UP)
667 return 0;
668
669 NSLOG(netsurf, DEEPDEBUG, "browser window clicked at %d,%d",do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_DEEPDEBUG, "frontends/framebuffer/gui.c", sizeof
("frontends/framebuffer/gui.c") - 1, __PRETTY_FUNCTION__, sizeof
(__PRETTY_FUNCTION__) - 1, 670, }; nslog__log(&_nslog_ctx
, "browser window clicked at %d,%d", cbi->x, cbi->y); }
} while(0)
670 cbi->x, cbi->y)do { if (NSLOG_LEVEL_DEEPDEBUG >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_DEEPDEBUG, "frontends/framebuffer/gui.c", sizeof
("frontends/framebuffer/gui.c") - 1, __PRETTY_FUNCTION__, sizeof
(__PRETTY_FUNCTION__) - 1, 670, }; nslog__log(&_nslog_ctx
, "browser window clicked at %d,%d", cbi->x, cbi->y); }
} while(0)
;
671
672 switch (cbi->event->type) {
673 case NSFB_EVENT_KEY_DOWN:
674 switch (cbi->event->value.keycode) {
675 case NSFB_KEY_MOUSE_1:
676 browser_window_mouse_click(gw->bw,
677 BROWSER_MOUSE_PRESS_1, x, y);
678 gui_drag.state = GUI_DRAG_PRESSED;
679 gui_drag.button = 1;
680 gui_drag.x = x;
681 gui_drag.y = y;
682 break;
683
684 case NSFB_KEY_MOUSE_3:
685 browser_window_mouse_click(gw->bw,
686 BROWSER_MOUSE_PRESS_2, x, y);
687 gui_drag.state = GUI_DRAG_PRESSED;
688 gui_drag.button = 2;
689 gui_drag.x = x;
690 gui_drag.y = y;
691 break;
692
693 case NSFB_KEY_MOUSE_4:
694 /* scroll up */
695 if (browser_window_scroll_at_point(gw->bw,
696 x, y,
697 0, -100) == false0)
698 widget_scroll_y(gw, -100, false0);
699 break;
700
701 case NSFB_KEY_MOUSE_5:
702 /* scroll down */
703 if (browser_window_scroll_at_point(gw->bw,
704 x, y,
705 0, 100) == false0)
706 widget_scroll_y(gw, 100, false0);
707 break;
708
709 default:
710 break;
711
712 }
713
714 break;
715 case NSFB_EVENT_KEY_UP:
716
717 mouse = 0;
718 nsu_getmonotonic_ms(&time_now);
719
720 switch (cbi->event->value.keycode) {
721 case NSFB_KEY_MOUSE_1:
722 if (gui_drag.state == GUI_DRAG_DRAG) {
723 /* End of a drag, rather than click */
724
725 if (gui_drag.grabbed_pointer) {
726 /* need to ungrab pointer */
727 fbtk_tgrab_pointer(widget);
728 gui_drag.grabbed_pointer = false0;
729 }
730
731 gui_drag.state = GUI_DRAG_NONE;
732
733 /* Tell core */
734 browser_window_mouse_track(gw->bw, 0, x, y);
735 break;
736 }
737 /* This is a click;
738 * clear PRESSED state and pass to core */
739 gui_drag.state = GUI_DRAG_NONE;
740 mouse = BROWSER_MOUSE_CLICK_1;
741 break;
742
743 case NSFB_KEY_MOUSE_3:
744 if (gui_drag.state == GUI_DRAG_DRAG) {
745 /* End of a drag, rather than click */
746 gui_drag.state = GUI_DRAG_NONE;
747
748 if (gui_drag.grabbed_pointer) {
749 /* need to ungrab pointer */
750 fbtk_tgrab_pointer(widget);
751 gui_drag.grabbed_pointer = false0;
752 }
753
754 /* Tell core */
755 browser_window_mouse_track(gw->bw, 0, x, y);
756 break;
757 }
758 /* This is a click;
759 * clear PRESSED state and pass to core */
760 gui_drag.state = GUI_DRAG_NONE;
761 mouse = BROWSER_MOUSE_CLICK_2;
762 break;
763
764 default:
765 break;
766
767 }
768
769 /* Determine if it's a double or triple click, allowing
770 * 0.5 seconds (500ms) between clicks
771 */
772 if ((time_now < (last_click.time + 500)) &&
773 (cbi->event->value.keycode != NSFB_KEY_MOUSE_4) &&
774 (cbi->event->value.keycode != NSFB_KEY_MOUSE_5)) {
775 if (last_click.type == CLICK_SINGLE) {
776 /* Set double click */
777 mouse |= BROWSER_MOUSE_DOUBLE_CLICK;
778 last_click.type = CLICK_DOUBLE;
779
780 } else if (last_click.type == CLICK_DOUBLE) {
781 /* Set triple click */
782 mouse |= BROWSER_MOUSE_TRIPLE_CLICK;
783 last_click.type = CLICK_TRIPLE;
784 } else {
785 /* Set normal click */
786 last_click.type = CLICK_SINGLE;
787 }
788 } else {
789 last_click.type = CLICK_SINGLE;
790 }
791
792 if (mouse) {
793 browser_window_mouse_click(gw->bw, mouse, x, y);
794 }
795
796 last_click.time = time_now;
797
798 break;
799 default:
800 break;
801
802 }
803 return 1;
804}
805
806/* called back when movement in browser window */
807static int
808fb_browser_window_move(fbtk_widget_t *widget, fbtk_callback_info *cbi)
809{
810 browser_mouse_state mouse = 0;
811 struct gui_window *gw = cbi->context;
812 struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
813 int x = cbi->x + bwidget->scrollx;
814 int y = cbi->y + bwidget->scrolly;
815
816 if (gui_drag.state == GUI_DRAG_PRESSED &&
817 (abs(x - gui_drag.x) > 5 ||
818 abs(y - gui_drag.y) > 5)) {
819 /* Drag started */
820 if (gui_drag.button == 1) {
821 browser_window_mouse_click(gw->bw,
822 BROWSER_MOUSE_DRAG_1,
823 gui_drag.x, gui_drag.y);
824 } else {
825 browser_window_mouse_click(gw->bw,
826 BROWSER_MOUSE_DRAG_2,
827 gui_drag.x, gui_drag.y);
828 }
829 gui_drag.grabbed_pointer = fbtk_tgrab_pointer(widget);
830 gui_drag.state = GUI_DRAG_DRAG;
831 }
832
833 if (gui_drag.state == GUI_DRAG_DRAG) {
834 /* set up mouse state */
835 mouse |= BROWSER_MOUSE_DRAG_ON;
836
837 if (gui_drag.button == 1)
838 mouse |= BROWSER_MOUSE_HOLDING_1;
839 else
840 mouse |= BROWSER_MOUSE_HOLDING_2;
841 }
842
843 browser_window_mouse_track(gw->bw, mouse, x, y);
844
845 return 0;
846}
847
848
849static int
850fb_browser_window_input(fbtk_widget_t *widget, fbtk_callback_info *cbi)
851{
852 struct gui_window *gw = cbi->context;
853 static fbtk_modifier_type modifier = FBTK_MOD_CLEAR;
854 int ucs4 = -1;
855
856 NSLOG(netsurf, INFO, "got value %d", cbi->event->value.keycode)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 856
, }; nslog__log(&_nslog_ctx, "got value %d", cbi->event
->value.keycode); } } while(0)
;
857
858 switch (cbi->event->type) {
859 case NSFB_EVENT_KEY_DOWN:
860 switch (cbi->event->value.keycode) {
861
862 case NSFB_KEY_DELETE:
863 browser_window_key_press(gw->bw, NS_KEY_DELETE_RIGHT);
864 break;
865
866 case NSFB_KEY_PAGEUP:
867 if (browser_window_key_press(gw->bw,
868 NS_KEY_PAGE_UP) == false0)
869 widget_scroll_y(gw, -fbtk_get_height(
870 gw->browser), false0);
871 break;
872
873 case NSFB_KEY_PAGEDOWN:
874 if (browser_window_key_press(gw->bw,
875 NS_KEY_PAGE_DOWN) == false0)
876 widget_scroll_y(gw, fbtk_get_height(
877 gw->browser), false0);
878 break;
879
880 case NSFB_KEY_RIGHT:
881 if (modifier & FBTK_MOD_RCTRL ||
882 modifier & FBTK_MOD_LCTRL) {
883 /* CTRL held */
884 if (browser_window_key_press(gw->bw,
885 NS_KEY_LINE_END) == false0)
886 widget_scroll_x(gw, INT_MAX2147483647, true1);
887
888 } else if (modifier & FBTK_MOD_RSHIFT ||
889 modifier & FBTK_MOD_LSHIFT) {
890 /* SHIFT held */
891 if (browser_window_key_press(gw->bw,
892 NS_KEY_WORD_RIGHT) == false0)
893 widget_scroll_x(gw, fbtk_get_width(
894 gw->browser), false0);
895
896 } else {
897 /* no modifier */
898 if (browser_window_key_press(gw->bw,
899 NS_KEY_RIGHT) == false0)
900 widget_scroll_x(gw, 100, false0);
901 }
902 break;
903
904 case NSFB_KEY_LEFT:
905 if (modifier & FBTK_MOD_RCTRL ||
906 modifier & FBTK_MOD_LCTRL) {
907 /* CTRL held */
908 if (browser_window_key_press(gw->bw,
909 NS_KEY_LINE_START) == false0)
910 widget_scroll_x(gw, 0, true1);
911
912 } else if (modifier & FBTK_MOD_RSHIFT ||
913 modifier & FBTK_MOD_LSHIFT) {
914 /* SHIFT held */
915 if (browser_window_key_press(gw->bw,
916 NS_KEY_WORD_LEFT) == false0)
917 widget_scroll_x(gw, -fbtk_get_width(
918 gw->browser), false0);
919
920 } else {
921 /* no modifier */
922 if (browser_window_key_press(gw->bw,
923 NS_KEY_LEFT) == false0)
924 widget_scroll_x(gw, -100, false0);
925 }
926 break;
927
928 case NSFB_KEY_UP:
929 if (browser_window_key_press(gw->bw,
930 NS_KEY_UP) == false0)
931 widget_scroll_y(gw, -100, false0);
932 break;
933
934 case NSFB_KEY_DOWN:
935 if (browser_window_key_press(gw->bw,
936 NS_KEY_DOWN) == false0)
937 widget_scroll_y(gw, 100, false0);
938 break;
939
940 case NSFB_KEY_MINUS:
941 if (modifier & FBTK_MOD_RCTRL ||
942 modifier & FBTK_MOD_LCTRL) {
943 browser_window_set_scale(gw->bw, -0.1, false0);
944 }
945 break;
946
947 case NSFB_KEY_EQUALS: /* PLUS */
948 if (modifier & FBTK_MOD_RCTRL ||
949 modifier & FBTK_MOD_LCTRL) {
950 browser_window_set_scale(gw->bw, 0.1, false0);
951 }
952 break;
953
954 case NSFB_KEY_0:
955 if (modifier & FBTK_MOD_RCTRL ||
956 modifier & FBTK_MOD_LCTRL) {
957 browser_window_set_scale(gw->bw, 1.0, true1);
958 }
959 break;
960
961 case NSFB_KEY_RSHIFT:
962 modifier |= FBTK_MOD_RSHIFT;
963 break;
964
965 case NSFB_KEY_LSHIFT:
966 modifier |= FBTK_MOD_LSHIFT;
967 break;
968
969 case NSFB_KEY_RCTRL:
970 modifier |= FBTK_MOD_RCTRL;
971 break;
972
973 case NSFB_KEY_LCTRL:
974 modifier |= FBTK_MOD_LCTRL;
975 break;
976
977 case NSFB_KEY_y:
978 case NSFB_KEY_z:
979 if (cbi->event->value.keycode == NSFB_KEY_z &&
980 (modifier & FBTK_MOD_RCTRL ||
981 modifier & FBTK_MOD_LCTRL) &&
982 (modifier & FBTK_MOD_RSHIFT ||
983 modifier & FBTK_MOD_LSHIFT)) {
984 /* Z pressed with CTRL and SHIFT held */
985 browser_window_key_press(gw->bw, NS_KEY_REDO);
986 break;
987
988 } else if (cbi->event->value.keycode == NSFB_KEY_z &&
989 (modifier & FBTK_MOD_RCTRL ||
990 modifier & FBTK_MOD_LCTRL)) {
991 /* Z pressed with CTRL held */
992 browser_window_key_press(gw->bw, NS_KEY_UNDO);
993 break;
994
995 } else if (cbi->event->value.keycode == NSFB_KEY_y &&
996 (modifier & FBTK_MOD_RCTRL ||
997 modifier & FBTK_MOD_LCTRL)) {
998 /* Y pressed with CTRL held */
999 browser_window_key_press(gw->bw, NS_KEY_REDO);
1000 break;
1001 }
1002 /* Z or Y pressed but not undo or redo; */
1003 fallthrough__attribute__((__fallthrough__));
1004
1005 default:
1006 ucs4 = fbtk_keycode_to_ucs4(cbi->event->value.keycode,
1007 modifier);
1008 if (ucs4 != -1)
1009 browser_window_key_press(gw->bw, ucs4);
1010 break;
1011 }
1012 break;
1013
1014 case NSFB_EVENT_KEY_UP:
1015 switch (cbi->event->value.keycode) {
1016 case NSFB_KEY_RSHIFT:
1017 modifier &= ~FBTK_MOD_RSHIFT;
1018 break;
1019
1020 case NSFB_KEY_LSHIFT:
1021 modifier &= ~FBTK_MOD_LSHIFT;
1022 break;
1023
1024 case NSFB_KEY_RCTRL:
1025 modifier &= ~FBTK_MOD_RCTRL;
1026 break;
1027
1028 case NSFB_KEY_LCTRL:
1029 modifier &= ~FBTK_MOD_LCTRL;
1030 break;
1031
1032 default:
1033 break;
1034 }
1035 break;
1036
1037 default:
1038 break;
1039 }
1040
1041 return 0;
1042}
1043
1044static void
1045fb_update_back_forward(struct gui_window *gw)
1046{
1047 struct browser_window *bw = gw->bw;
1048
1049 fbtk_set_bitmap(gw->back,
1050 (browser_window_back_available(bw)) ?
1051 &left_arrow : &left_arrow_g);
1052 fbtk_set_bitmap(gw->forward,
1053 (browser_window_forward_available(bw)) ?
1054 &right_arrow : &right_arrow_g);
1055}
1056
1057/* left icon click routine */
1058static int
1059fb_leftarrow_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1060{
1061 struct gui_window *gw = cbi->context;
1062 struct browser_window *bw = gw->bw;
1063
1064 if (cbi->event->type != NSFB_EVENT_KEY_UP)
1065 return 0;
1066
1067 if (browser_window_back_available(bw))
1068 browser_window_history_back(bw, false0);
1069
1070 fb_update_back_forward(gw);
1071
1072 return 1;
1073}
1074
1075/* right arrow icon click routine */
1076static int
1077fb_rightarrow_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1078{
1079 struct gui_window *gw = cbi->context;
1080 struct browser_window *bw = gw->bw;
1081
1082 if (cbi->event->type != NSFB_EVENT_KEY_UP)
1083 return 0;
1084
1085 if (browser_window_forward_available(bw))
1086 browser_window_history_forward(bw, false0);
1087
1088 fb_update_back_forward(gw);
1089 return 1;
1090
1091}
1092
1093/* reload icon click routine */
1094static int
1095fb_reload_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1096{
1097 struct browser_window *bw = cbi->context;
1098
1099 if (cbi->event->type != NSFB_EVENT_KEY_UP)
1100 return 0;
1101
1102 browser_window_reload(bw, true1);
1103 return 1;
1104}
1105
1106/* stop icon click routine */
1107static int
1108fb_stop_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1109{
1110 struct browser_window *bw = cbi->context;
1111
1112 if (cbi->event->type != NSFB_EVENT_KEY_UP)
1113 return 0;
1114
1115 browser_window_stop(bw);
1116 return 0;
1117}
1118
1119static int
1120fb_osk_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1121{
1122
1123 if (cbi->event->type != NSFB_EVENT_KEY_UP)
1124 return 0;
1125
1126 map_osk();
1127
1128 return 0;
1129}
1130
1131/* close browser window icon click routine */
1132static int
1133fb_close_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1134{
1135 if (cbi->event->type != NSFB_EVENT_KEY_UP)
1136 return 0;
1137
1138 fb_complete = true1;
1139
1140 return 0;
1141}
1142
1143static int
1144fb_scroll_callback(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1145{
1146 struct gui_window *gw = cbi->context;
1147
1148 switch (cbi->type) {
1149 case FBTK_CBT_SCROLLY:
1150 widget_scroll_y(gw, cbi->y, true1);
1151 break;
1152
1153 case FBTK_CBT_SCROLLX:
1154 widget_scroll_x(gw, cbi->x, true1);
1155 break;
1156
1157 default:
1158 break;
1159 }
1160 return 0;
1161}
1162
1163static int
1164fb_url_enter(void *pw, char *text)
1165{
1166 struct browser_window *bw = pw;
1167 nsurl *url;
1168 nserror error;
1169
1170 error = nsurl_create(text, &url);
1171 if (error != NSERROR_OK) {
1172 fb_warn_user("Errorcode:", messages_get_errorcode(error));
1173 } else {
1174 browser_window_navigate(bw, url, NULL((void*)0), BW_NAVIGATE_HISTORY,
1175 NULL((void*)0), NULL((void*)0), NULL((void*)0));
1176 nsurl_unref(url);
1177 }
1178
1179 return 0;
1180}
1181
1182static int
1183fb_url_move(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1184{
1185 framebuffer_set_cursor(&caret_image);
1186 return 0;
1187}
1188
1189static int
1190set_ptr_default_move(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1191{
1192 framebuffer_set_cursor(&pointer_image);
1193 return 0;
1194}
1195
1196static int
1197fb_localhistory_btn_clik(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1198{
1199 struct gui_window *gw = cbi->context;
1200
1201 if (cbi->event->type != NSFB_EVENT_KEY_UP)
1202 return 0;
1203
1204 fb_local_history_present(fbtk, gw->bw);
1205
1206 return 0;
1207}
1208
1209
1210/** Create a toolbar window and populate it with buttons.
1211 *
1212 * The toolbar layout uses a character to define buttons type and position:
1213 * b - back
1214 * l - local history
1215 * f - forward
1216 * s - stop
1217 * r - refresh
1218 * u - url bar expands to fit remaining space
1219 * t - throbber/activity indicator
1220 * c - close the current window
1221 *
1222 * The default layout is "blfsrut" there should be no more than a
1223 * single url bar entry or behaviour will be undefined.
1224 *
1225 * @param gw Parent window
1226 * @param toolbar_height The height in pixels of the toolbar
1227 * @param padding The padding in pixels round each element of the toolbar
1228 * @param frame_col Frame colour.
1229 * @param toolbar_layout A string defining which buttons and controls
1230 * should be added to the toolbar. May be empty
1231 * string to disable the bar..
1232 *
1233 */
1234static fbtk_widget_t *
1235create_toolbar(struct gui_window *gw,
1236 int toolbar_height,
1237 int padding,
1238 colour frame_col,
1239 const char *toolbar_layout)
1240{
1241 fbtk_widget_t *toolbar;
1242 fbtk_widget_t *widget;
1243
1244 int xpos; /* The position of the next widget. */
1245 int xlhs = 0; /* extent of the left hand side widgets */
1246 int xdir = 1; /* the direction of movement + or - 1 */
1247 const char *itmtype; /* type of the next item */
1248
1249 if (toolbar_layout == NULL((void*)0)) {
1250 toolbar_layout = NSFB_TOOLBAR_DEFAULT_LAYOUT"blfsrutc";
1251 }
1252
1253 NSLOG(netsurf, INFO, "Using toolbar layout %s", toolbar_layout)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 1253
, }; nslog__log(&_nslog_ctx, "Using toolbar layout %s", toolbar_layout
); } } while(0)
;
1254
1255 itmtype = toolbar_layout;
1256
1257 /* check for the toolbar being disabled */
1258 if ((*itmtype == 0) || (*itmtype == 'q')) {
1259 return NULL((void*)0);
1260 }
1261
1262 toolbar = fbtk_create_window(gw->window, 0, 0, 0,
1263 toolbar_height,
1264 frame_col);
1265
1266 if (toolbar == NULL((void*)0)) {
1267 return NULL((void*)0);
1268 }
1269
1270 fbtk_set_handler(toolbar,
1271 FBTK_CBT_POINTERENTER,
1272 set_ptr_default_move,
1273 NULL((void*)0));
1274
1275
1276 xpos = padding;
1277
1278 /* loop proceeds creating widget on the left hand side until
1279 * it runs out of layout or encounters a url bar declaration
1280 * wherupon it works backwards from the end of the layout
1281 * untill the space left is for the url bar
1282 */
1283 while ((itmtype >= toolbar_layout) &&
1284 (*itmtype != 0) &&
1285 (xdir !=0)) {
1286
1287 NSLOG(netsurf, INFO, "toolbar adding %c", *itmtype)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 1287
, }; nslog__log(&_nslog_ctx, "toolbar adding %c", *itmtype
); } } while(0)
;
1288
1289
1290 switch (*itmtype) {
1291
1292 case 'b': /* back */
1293 widget = fbtk_create_button(toolbar,
1294 (xdir == 1) ? xpos :
1295 xpos - left_arrow.width,
1296 padding,
1297 left_arrow.width,
1298 -padding,
1299 frame_col,
1300 &left_arrow,
1301 fb_leftarrow_click,
1302 gw);
1303 gw->back = widget; /* keep reference */
1304 break;
1305
1306 case 'l': /* local history */
1307 widget = fbtk_create_button(toolbar,
1308 (xdir == 1) ? xpos :
1309 xpos - history_image.width,
1310 padding,
1311 history_image.width,
1312 -padding,
1313 frame_col,
1314 &history_image,
1315 fb_localhistory_btn_clik,
1316 gw);
1317 gw->history = widget;
1318 break;
1319
1320 case 'f': /* forward */
1321 widget = fbtk_create_button(toolbar,
1322 (xdir == 1)?xpos :
1323 xpos - right_arrow.width,
1324 padding,
1325 right_arrow.width,
1326 -padding,
1327 frame_col,
1328 &right_arrow,
1329 fb_rightarrow_click,
1330 gw);
1331 gw->forward = widget;
1332 break;
1333
1334 case 'c': /* close the current window */
1335 widget = fbtk_create_button(toolbar,
1336 (xdir == 1)?xpos :
1337 xpos - stop_image_g.width,
1338 padding,
1339 stop_image_g.width,
1340 -padding,
1341 frame_col,
1342 &stop_image_g,
1343 fb_close_click,
1344 gw->bw);
1345 gw->close = widget;
1346 break;
1347
1348 case 's': /* stop */
1349 widget = fbtk_create_button(toolbar,
1350 (xdir == 1)?xpos :
1351 xpos - stop_image.width,
1352 padding,
1353 stop_image.width,
1354 -padding,
1355 frame_col,
1356 &stop_image,
1357 fb_stop_click,
1358 gw->bw);
1359 gw->stop = widget;
1360 break;
1361
1362 case 'r': /* reload */
1363 widget = fbtk_create_button(toolbar,
1364 (xdir == 1)?xpos :
1365 xpos - reload.width,
1366 padding,
1367 reload.width,
1368 -padding,
1369 frame_col,
1370 &reload,
1371 fb_reload_click,
1372 gw->bw);
1373 gw->reload = widget;
1374 break;
1375
1376 case 't': /* throbber/activity indicator */
1377 widget = fbtk_create_bitmap(toolbar,
1378 (xdir == 1)?xpos :
1379 xpos - throbber0.width,
1380 padding,
1381 throbber0.width,
1382 -padding,
1383 frame_col,
1384 &throbber0);
1385 gw->throbber = widget;
1386 break;
1387
1388
1389 case 'u': /* url bar*/
1390 if (xdir == -1) {
1391 /* met the u going backwards add url
1392 * now we know available extent
1393 */
1394
1395 widget = fbtk_create_writable_text(toolbar,
1396 xlhs,
1397 padding,
1398 xpos - xlhs,
1399 -padding,
1400 FB_COLOUR_WHITE0xFFFFFFFF,
1401 FB_COLOUR_BLACK0xFF000000,
1402 true1,
1403 fb_url_enter,
1404 gw->bw);
1405
1406 fbtk_set_handler(widget,
1407 FBTK_CBT_POINTERENTER,
1408 fb_url_move, gw->bw);
1409
1410 gw->url = widget; /* keep reference */
1411
1412 /* toolbar is complete */
1413 xdir = 0;
1414 break;
1415 }
1416 /* met url going forwards, note position and
1417 * reverse direction
1418 */
1419 itmtype = toolbar_layout + strlen(toolbar_layout);
1420 xdir = -1;
1421 xlhs = xpos;
1422 xpos = (2 * fbtk_get_width(toolbar));
1423 widget = toolbar;
1424 break;
1425
1426 default:
1427 widget = NULL((void*)0);
1428 xdir = 0;
1429 NSLOG(netsurf, INFO,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 1431
, }; nslog__log(&_nslog_ctx, "Unknown element %c in toolbar layout"
, *itmtype); } } while(0)
1430 "Unknown element %c in toolbar layout",do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 1431
, }; nslog__log(&_nslog_ctx, "Unknown element %c in toolbar layout"
, *itmtype); } } while(0)
1431 *itmtype)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 1431
, }; nslog__log(&_nslog_ctx, "Unknown element %c in toolbar layout"
, *itmtype); } } while(0)
;
1432 break;
1433
1434 }
1435
1436 if (widget != NULL((void*)0)) {
1437 xpos += (xdir * (fbtk_get_width(widget) + padding));
1438 }
1439
1440 NSLOG(netsurf, INFO, "xpos is %d", xpos)do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 1440
, }; nslog__log(&_nslog_ctx, "xpos is %d", xpos); } } while
(0)
;
1441
1442 itmtype += xdir;
1443 }
1444
1445 fbtk_set_mapping(toolbar, true1);
1446
1447 return toolbar;
1448}
1449
1450
1451/** Resize a toolbar.
1452 *
1453 * @param gw Parent window
1454 * @param toolbar_height The height in pixels of the toolbar
1455 * @param padding The padding in pixels round each element of the toolbar
1456 * @param toolbar_layout A string defining which buttons and controls
1457 * should be added to the toolbar. May be empty
1458 * string to disable the bar.
1459 */
1460static void
1461resize_toolbar(struct gui_window *gw,
1462 int toolbar_height,
1463 int padding,
1464 const char *toolbar_layout)
1465{
1466 fbtk_widget_t *widget;
1467
1468 int xpos; /* The position of the next widget. */
1469 int xlhs = 0; /* extent of the left hand side widgets */
1470 int xdir = 1; /* the direction of movement + or - 1 */
1471 const char *itmtype; /* type of the next item */
1472 int x = 0, y = 0, w = 0, h = 0;
1473
1474 if (gw->toolbar == NULL((void*)0)) {
1475 return;
1476 }
1477
1478 if (toolbar_layout == NULL((void*)0)) {
1479 toolbar_layout = NSFB_TOOLBAR_DEFAULT_LAYOUT"blfsrutc";
1480 }
1481
1482 itmtype = toolbar_layout;
1483
1484 if (*itmtype == 0) {
1485 return;
1486 }
1487
1488 fbtk_set_pos_and_size(gw->toolbar, 0, 0, 0, toolbar_height);
1489
1490 xpos = padding;
1491
1492 /* loop proceeds creating widget on the left hand side until
1493 * it runs out of layout or encounters a url bar declaration
1494 * wherupon it works backwards from the end of the layout
1495 * untill the space left is for the url bar
1496 */
1497 while (itmtype >= toolbar_layout && xdir != 0) {
1498
1499 switch (*itmtype) {
1500 case 'b': /* back */
1501 widget = gw->back;
1502 x = (xdir == 1) ? xpos : xpos - left_arrow.width;
1503 y = padding;
1504 w = left_arrow.width;
1505 h = -padding;
1506 break;
1507
1508 case 'l': /* local history */
1509 widget = gw->history;
1510 x = (xdir == 1) ? xpos : xpos - history_image.width;
1511 y = padding;
1512 w = history_image.width;
1513 h = -padding;
1514 break;
1515
1516 case 'f': /* forward */
1517 widget = gw->forward;
1518 x = (xdir == 1) ? xpos : xpos - right_arrow.width;
1519 y = padding;
1520 w = right_arrow.width;
1521 h = -padding;
1522 break;
1523
1524 case 'c': /* close the current window */
1525 widget = gw->close;
1526 x = (xdir == 1) ? xpos : xpos - stop_image_g.width;
1527 y = padding;
1528 w = stop_image_g.width;
1529 h = -padding;
1530 break;
1531
1532 case 's': /* stop */
1533 widget = gw->stop;
1534 x = (xdir == 1) ? xpos : xpos - stop_image.width;
1535 y = padding;
1536 w = stop_image.width;
1537 h = -padding;
1538 break;
1539
1540 case 'r': /* reload */
1541 widget = gw->reload;
1542 x = (xdir == 1) ? xpos : xpos - reload.width;
1543 y = padding;
1544 w = reload.width;
1545 h = -padding;
1546 break;
1547
1548 case 't': /* throbber/activity indicator */
1549 widget = gw->throbber;
1550 x = (xdir == 1) ? xpos : xpos - throbber0.width;
1551 y = padding;
1552 w = throbber0.width;
1553 h = -padding;
1554 break;
1555
1556
1557 case 'u': /* url bar*/
1558 if (xdir == -1) {
1559 /* met the u going backwards add url
1560 * now we know available extent
1561 */
1562 widget = gw->url;
1563 x = xlhs;
1564 y = padding;
1565 w = xpos - xlhs;
1566 h = -padding;
1567
1568 /* toolbar is complete */
1569 xdir = 0;
1570 break;
1571 }
1572 /* met url going forwards, note position and
1573 * reverse direction
1574 */
1575 itmtype = toolbar_layout + strlen(toolbar_layout);
1576 xdir = -1;
1577 xlhs = xpos;
1578 w = fbtk_get_width(gw->toolbar);
1579 xpos = 2 * w;
1580 widget = gw->toolbar;
1581 break;
1582
1583 default:
1584 widget = NULL((void*)0);
1585 break;
1586
1587 }
1588
1589 if (widget != NULL((void*)0)) {
1590 if (widget != gw->toolbar)
1591 fbtk_set_pos_and_size(widget, x, y, w, h);
1592 xpos += xdir * (w + padding);
1593 }
1594
1595 itmtype += xdir;
1596 }
1597}
1598
1599/** Routine called when "stripped of focus" event occours for browser widget.
1600 *
1601 * @param widget The widget reciving "stripped of focus" event.
1602 * @param cbi The callback parameters.
1603 * @return The callback result.
1604 */
1605static int
1606fb_browser_window_strip_focus(fbtk_widget_t *widget, fbtk_callback_info *cbi)
1607{
1608 fbtk_set_caret(widget, false0, 0, 0, 0, NULL((void*)0));
1609
1610 return 0;
1611}
1612
1613static void
1614create_browser_widget(struct gui_window *gw, int toolbar_height, int furniture_width)
1615{
1616 struct browser_widget_s *browser_widget;
1617 browser_widget = calloc(1, sizeof(struct browser_widget_s));
1618
1619 gw->browser = fbtk_create_user(gw->window,
1620 0,
1621 toolbar_height,
1622 -furniture_width,
1623 -furniture_width,
1624 browser_widget);
1625
1626 fbtk_set_handler(gw->browser, FBTK_CBT_REDRAW, fb_browser_window_redraw, gw);
1627 fbtk_set_handler(gw->browser, FBTK_CBT_DESTROY, fb_browser_window_destroy, gw);
1628 fbtk_set_handler(gw->browser, FBTK_CBT_INPUT, fb_browser_window_input, gw);
1629 fbtk_set_handler(gw->browser, FBTK_CBT_CLICK, fb_browser_window_click, gw);
1630 fbtk_set_handler(gw->browser, FBTK_CBT_STRIP_FOCUS, fb_browser_window_strip_focus, gw);
1631 fbtk_set_handler(gw->browser, FBTK_CBT_POINTERMOVE, fb_browser_window_move, gw);
1632}
1633
1634static void
1635resize_browser_widget(struct gui_window *gw, int x, int y,
1636 int width, int height)
1637{
1638 fbtk_set_pos_and_size(gw->browser, x, y, width, height);
1639 browser_window_schedule_reformat(gw->bw);
1640}
1641
1642static void
1643create_normal_browser_window(struct gui_window *gw, int furniture_width)
1644{
1645 fbtk_widget_t *widget;
1646 fbtk_widget_t *toolbar;
1647 int statusbar_width = 0;
1648 int toolbar_height = nsoption_int(fb_toolbar_size)(nsoptions[NSOPTION_fb_toolbar_size].value.i);
1649
1650 NSLOG(netsurf, INFO, "Normal window")do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 1650
, }; nslog__log(&_nslog_ctx, "Normal window"); } } while(
0)
;
1651
1652 gw->window = fbtk_create_window(fbtk, 0, 0, 0, 0, 0);
1653
1654 statusbar_width = nsoption_int(toolbar_status_size)(nsoptions[NSOPTION_toolbar_status_size].value.i) *
1655 fbtk_get_width(gw->window) / 10000;
1656
1657 /* toolbar */
1658 toolbar = create_toolbar(gw,
1659 toolbar_height,
1660 2,
1661 FB_FRAME_COLOUR0xFFDDDDDD,
1662 nsoption_charp(fb_toolbar_layout)(nsoptions[NSOPTION_fb_toolbar_layout].value.s));
1663 gw->toolbar = toolbar;
1664
1665 /* set the actually created toolbar height */
1666 if (toolbar != NULL((void*)0)) {
1667 toolbar_height = fbtk_get_height(toolbar);
1668 } else {
1669 toolbar_height = 0;
1670 }
1671
1672 /* status bar */
1673 gw->status = fbtk_create_text(gw->window,
1674 0,
1675 fbtk_get_height(gw->window) - furniture_width,
1676 statusbar_width, furniture_width,
1677 FB_FRAME_COLOUR0xFFDDDDDD, FB_COLOUR_BLACK0xFF000000,
1678 false0);
1679 fbtk_set_handler(gw->status, FBTK_CBT_POINTERENTER, set_ptr_default_move, NULL((void*)0));
1680
1681 NSLOG(netsurf, INFO, "status bar %p at %d,%d", gw->status,do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 1682
, }; nslog__log(&_nslog_ctx, "status bar %p at %d,%d", gw
->status, fbtk_get_absx(gw->status), fbtk_get_absy(gw->
status)); } } while(0)
1682 fbtk_get_absx(gw->status), fbtk_get_absy(gw->status))do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 1682
, }; nslog__log(&_nslog_ctx, "status bar %p at %d,%d", gw
->status, fbtk_get_absx(gw->status), fbtk_get_absy(gw->
status)); } } while(0)
;
1683
1684 /* create horizontal scrollbar */
1685 gw->hscroll = fbtk_create_hscroll(gw->window,
1686 statusbar_width,
1687 fbtk_get_height(gw->window) - furniture_width,
1688 fbtk_get_width(gw->window) - statusbar_width - furniture_width,
1689 furniture_width,
1690 FB_SCROLL_COLOUR0xFFAAAAAA,
1691 FB_FRAME_COLOUR0xFFDDDDDD,
1692 fb_scroll_callback,
1693 gw);
1694
1695 /* fill bottom right area */
1696
1697 if (nsoption_bool(fb_osk)(nsoptions[NSOPTION_fb_osk].value.b) == true1) {
1698 widget = fbtk_create_text_button(gw->window,
Value stored to 'widget' is never read
1699 fbtk_get_width(gw->window) - furniture_width,
1700 fbtk_get_height(gw->window) - furniture_width,
1701 furniture_width,
1702 furniture_width,
1703 FB_FRAME_COLOUR0xFFDDDDDD, FB_COLOUR_BLACK0xFF000000,
1704 fb_osk_click,
1705 NULL((void*)0));
1706 widget = fbtk_create_button(gw->window,
1707 fbtk_get_width(gw->window) - furniture_width,
1708 fbtk_get_height(gw->window) - furniture_width,
1709 furniture_width,
1710 furniture_width,
1711 FB_FRAME_COLOUR0xFFDDDDDD,
1712 &osk_image,
1713 fb_osk_click,
1714 NULL((void*)0));
1715 } else {
1716 widget = fbtk_create_fill(gw->window,
1717 fbtk_get_width(gw->window) - furniture_width,
1718 fbtk_get_height(gw->window) - furniture_width,
1719 furniture_width,
1720 furniture_width,
1721 FB_FRAME_COLOUR0xFFDDDDDD);
1722
1723 fbtk_set_handler(widget, FBTK_CBT_POINTERENTER, set_ptr_default_move, NULL((void*)0));
1724 }
1725
1726 gw->bottom_right = widget;
1727
1728 /* create vertical scrollbar */
1729 gw->vscroll = fbtk_create_vscroll(gw->window,
1730 fbtk_get_width(gw->window) - furniture_width,
1731 toolbar_height,
1732 furniture_width,
1733 fbtk_get_height(gw->window) - toolbar_height - furniture_width,
1734 FB_SCROLL_COLOUR0xFFAAAAAA,
1735 FB_FRAME_COLOUR0xFFDDDDDD,
1736 fb_scroll_callback,
1737 gw);
1738
1739 /* browser widget */
1740 create_browser_widget(gw, toolbar_height, nsoption_int(fb_furniture_size)(nsoptions[NSOPTION_fb_furniture_size].value.i));
1741
1742 /* Give browser_window's user widget input focus */
1743 fbtk_set_focus(gw->browser);
1744}
1745
1746static void
1747resize_normal_browser_window(struct gui_window *gw, int furniture_width)
1748{
1749 bool_Bool resized;
1750 int width, height;
1751 int statusbar_width;
1752 int toolbar_height = fbtk_get_height(gw->toolbar);
1753
1754 /* Resize the main window widget */
1755 resized = fbtk_set_pos_and_size(gw->window, 0, 0, 0, 0);
1756 if (!resized)
1757 return;
1758
1759 width = fbtk_get_width(gw->window);
1760 height = fbtk_get_height(gw->window);
1761 statusbar_width = nsoption_int(toolbar_status_size)(nsoptions[NSOPTION_toolbar_status_size].value.i) * width / 10000;
1762
1763 resize_toolbar(gw, toolbar_height, 2,
1764 nsoption_charp(fb_toolbar_layout)(nsoptions[NSOPTION_fb_toolbar_layout].value.s));
1765 fbtk_set_pos_and_size(gw->status,
1766 0, height - furniture_width,
1767 statusbar_width, furniture_width);
1768 fbtk_reposition_hscroll(gw->hscroll,
1769 statusbar_width, height - furniture_width,
1770 width - statusbar_width - furniture_width,
1771 furniture_width);
1772 fbtk_set_pos_and_size(gw->bottom_right,
1773 width - furniture_width, height - furniture_width,
1774 furniture_width, furniture_width);
1775 fbtk_reposition_vscroll(gw->vscroll,
1776 width - furniture_width,
1777 toolbar_height, furniture_width,
1778 height - toolbar_height - furniture_width);
1779 resize_browser_widget(gw,
1780 0, toolbar_height,
1781 width - furniture_width,
1782 height - furniture_width - toolbar_height);
1783}
1784
1785static void gui_window_add_to_window_list(struct gui_window *gw)
1786{
1787 gw->next = NULL((void*)0);
1788 gw->prev = NULL((void*)0);
1789
1790 if (window_list == NULL((void*)0)) {
1791 window_list = gw;
1792 } else {
1793 window_list->prev = gw;
1794 gw->next = window_list;
1795 window_list = gw;
1796 }
1797}
1798
1799static void gui_window_remove_from_window_list(struct gui_window *gw)
1800{
1801 struct gui_window *list;
1802
1803 for (list = window_list; list != NULL((void*)0); list = list->next) {
1804 if (list != gw)
1805 continue;
1806
1807 if (list == window_list) {
1808 window_list = list->next;
1809 if (window_list != NULL((void*)0))
1810 window_list->prev = NULL((void*)0);
1811 } else {
1812 list->prev->next = list->next;
1813 if (list->next != NULL((void*)0)) {
1814 list->next->prev = list->prev;
1815 }
1816 }
1817 break;
1818 }
1819}
1820
1821
1822static struct gui_window *
1823gui_window_create(struct browser_window *bw,
1824 struct gui_window *existing,
1825 gui_window_create_flags flags)
1826{
1827 struct gui_window *gw;
1828
1829 gw = calloc(1, sizeof(struct gui_window));
1830
1831 if (gw == NULL((void*)0))
1832 return NULL((void*)0);
1833
1834 /* associate the gui window with the underlying browser window
1835 */
1836 gw->bw = bw;
1837
1838 create_normal_browser_window(gw, nsoption_int(fb_furniture_size)(nsoptions[NSOPTION_fb_furniture_size].value.i));
1839
1840 /* map and request redraw of gui window */
1841 fbtk_set_mapping(gw->window, true1);
1842
1843 /* Add it to the window list */
1844 gui_window_add_to_window_list(gw);
1845
1846 return gw;
1847}
1848
1849static void
1850gui_window_destroy(struct gui_window *gw)
1851{
1852 gui_window_remove_from_window_list(gw);
1853
1854 fbtk_destroy_widget(gw->window);
1855
1856 free(gw);
1857}
1858
1859
1860/**
1861 * Invalidates an area of a framebuffer browser window
1862 *
1863 * \param g The netsurf window being invalidated.
1864 * \param rect area to redraw or NULL for the entire window area
1865 * \return NSERROR_OK on success or appropriate error code
1866 */
1867static nserror
1868fb_window_invalidate_area(struct gui_window *g, const struct rect *rect)
1869{
1870 struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser);
1871
1872 if (rect != NULL((void*)0)) {
1873 fb_queue_redraw(g->browser,
1874 rect->x0 - bwidget->scrollx,
1875 rect->y0 - bwidget->scrolly,
1876 rect->x1 - bwidget->scrollx,
1877 rect->y1 - bwidget->scrolly);
1878 } else {
1879 fb_queue_redraw(g->browser,
1880 0,
1881 0,
1882 fbtk_get_width(g->browser),
1883 fbtk_get_height(g->browser));
1884 }
1885 return NSERROR_OK;
1886}
1887
1888static bool_Bool
1889gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
1890{
1891 struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser);
1892
1893 *sx = bwidget->scrollx;
1894 *sy = bwidget->scrolly;
1895
1896 return true1;
1897}
1898
1899/**
1900 * Set the scroll position of a framebuffer browser window.
1901 *
1902 * Scrolls the viewport to ensure the specified rectangle of the
1903 * content is shown. The framebuffer implementation scrolls the contents so
1904 * the specified point in the content is at the top of the viewport.
1905 *
1906 * \param gw gui_window to scroll
1907 * \param rect The rectangle to ensure is shown.
1908 * \return NSERROR_OK on success or apropriate error code.
1909 */
1910static nserror
1911gui_window_set_scroll(struct gui_window *gw, const struct rect *rect)
1912{
1913 struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser);
1914
1915 assert(bwidget)((bwidget) ? (void) (0) : __assert_fail ("bwidget", "frontends/framebuffer/gui.c"
, 1915, __extension__ __PRETTY_FUNCTION__))
;
1916
1917 widget_scroll_x(gw, rect->x0, true1);
1918 widget_scroll_y(gw, rect->y0, true1);
1919
1920 return NSERROR_OK;
1921}
1922
1923
1924/**
1925 * Find the current dimensions of a framebuffer browser window content area.
1926 *
1927 * \param gw The gui window to measure content area of.
1928 * \param width receives width of window
1929 * \param height receives height of window
1930 * \return NSERROR_OK on sucess and width and height updated.
1931 */
1932static nserror
1933gui_window_get_dimensions(struct gui_window *gw, int *width, int *height)
1934{
1935 *width = fbtk_get_width(gw->browser);
1936 *height = fbtk_get_height(gw->browser);
1937
1938 return NSERROR_OK;
1939}
1940
1941static void
1942gui_window_update_extent(struct gui_window *gw)
1943{
1944 int w, h;
1945 browser_window_get_extents(gw->bw, true1, &w, &h);
1946
1947 fbtk_set_scroll_parameters(gw->hscroll, 0, w,
1948 fbtk_get_width(gw->browser), 100);
1949
1950 fbtk_set_scroll_parameters(gw->vscroll, 0, h,
1951 fbtk_get_height(gw->browser), 100);
1952}
1953
1954static void
1955gui_window_set_status(struct gui_window *g, const char *text)
1956{
1957 fbtk_set_text(g->status, text);
1958}
1959
1960static void
1961gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape)
1962{
1963 switch (shape) {
1964 case GUI_POINTER_POINT:
1965 framebuffer_set_cursor(&hand_image);
1966 break;
1967
1968 case GUI_POINTER_CARET:
1969 framebuffer_set_cursor(&caret_image);
1970 break;
1971
1972 case GUI_POINTER_MENU:
1973 framebuffer_set_cursor(&menu_image);
1974 break;
1975
1976 case GUI_POINTER_PROGRESS:
1977 framebuffer_set_cursor(&progress_image);
1978 break;
1979
1980 case GUI_POINTER_MOVE:
1981 framebuffer_set_cursor(&move_image);
1982 break;
1983
1984 default:
1985 framebuffer_set_cursor(&pointer_image);
1986 break;
1987 }
1988}
1989
1990static nserror
1991gui_window_set_url(struct gui_window *g, nsurl *url)
1992{
1993 fbtk_set_text(g->url, nsurl_access(url));
1994 return NSERROR_OK;
1995}
1996
1997static void
1998throbber_advance(void *pw)
1999{
2000 struct gui_window *g = pw;
2001 struct fbtk_bitmap *image;
2002
2003 switch (g->throbber_index) {
2004 case 0:
2005 image = &throbber1;
2006 g->throbber_index = 1;
2007 break;
2008
2009 case 1:
2010 image = &throbber2;
2011 g->throbber_index = 2;
2012 break;
2013
2014 case 2:
2015 image = &throbber3;
2016 g->throbber_index = 3;
2017 break;
2018
2019 case 3:
2020 image = &throbber4;
2021 g->throbber_index = 4;
2022 break;
2023
2024 case 4:
2025 image = &throbber5;
2026 g->throbber_index = 5;
2027 break;
2028
2029 case 5:
2030 image = &throbber6;
2031 g->throbber_index = 6;
2032 break;
2033
2034 case 6:
2035 image = &throbber7;
2036 g->throbber_index = 7;
2037 break;
2038
2039 case 7:
2040 image = &throbber8;
2041 g->throbber_index = 0;
2042 break;
2043
2044 default:
2045 return;
2046 }
2047
2048 if (g->throbber_index >= 0) {
2049 fbtk_set_bitmap(g->throbber, image);
2050 framebuffer_schedule(100, throbber_advance, g);
2051 }
2052}
2053
2054static void
2055gui_window_start_throbber(struct gui_window *g)
2056{
2057 g->throbber_index = 0;
2058 framebuffer_schedule(100, throbber_advance, g);
2059}
2060
2061static void
2062gui_window_stop_throbber(struct gui_window *gw)
2063{
2064 gw->throbber_index = -1;
2065 fbtk_set_bitmap(gw->throbber, &throbber0);
2066
2067 fb_update_back_forward(gw);
2068
2069}
2070
2071static void
2072gui_window_remove_caret_cb(fbtk_widget_t *widget)
2073{
2074 struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
2075 int c_x, c_y, c_h;
2076
2077 if (fbtk_get_caret(widget, &c_x, &c_y, &c_h)) {
2078 /* browser window already had caret:
2079 * redraw its area to remove it first */
2080 fb_queue_redraw(widget,
2081 c_x - bwidget->scrollx,
2082 c_y - bwidget->scrolly,
2083 c_x + 1 - bwidget->scrollx,
2084 c_y + c_h - bwidget->scrolly);
2085 }
2086}
2087
2088static void
2089gui_window_place_caret(struct gui_window *g, int x, int y, int height,
2090 const struct rect *clip)
2091{
2092 struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser);
2093
2094 /* set new pos */
2095 fbtk_set_caret(g->browser, true1, x, y, height,
2096 gui_window_remove_caret_cb);
2097
2098 /* redraw new caret pos */
2099 fb_queue_redraw(g->browser,
2100 x - bwidget->scrollx,
2101 y - bwidget->scrolly,
2102 x + 1 - bwidget->scrollx,
2103 y + height - bwidget->scrolly);
2104}
2105
2106static void
2107gui_window_remove_caret(struct gui_window *g)
2108{
2109 int c_x, c_y, c_h;
2110
2111 if (fbtk_get_caret(g->browser, &c_x, &c_y, &c_h)) {
2112 /* browser window owns the caret, so can remove it */
2113 fbtk_set_caret(g->browser, false0, 0, 0, 0, NULL((void*)0));
2114 }
2115}
2116
2117/**
2118 * process miscellaneous window events
2119 *
2120 * \param gw The window receiving the event.
2121 * \param event The event code.
2122 * \return NSERROR_OK when processed ok
2123 */
2124static nserror
2125gui_window_event(struct gui_window *gw, enum gui_window_event event)
2126{
2127 switch (event) {
2128 case GW_EVENT_UPDATE_EXTENT:
2129 gui_window_update_extent(gw);
2130 break;
2131
2132 case GW_EVENT_REMOVE_CARET:
2133 gui_window_remove_caret(gw);
2134 break;
2135
2136 case GW_EVENT_START_THROBBER:
2137 gui_window_start_throbber(gw);
2138 break;
2139
2140 case GW_EVENT_STOP_THROBBER:
2141 gui_window_stop_throbber(gw);
2142 break;
2143
2144 default:
2145 break;
2146 }
2147 return NSERROR_OK;
2148}
2149
2150static struct gui_window_table framebuffer_window_table = {
2151 .create = gui_window_create,
2152 .destroy = gui_window_destroy,
2153 .invalidate = fb_window_invalidate_area,
2154 .get_scroll = gui_window_get_scroll,
2155 .set_scroll = gui_window_set_scroll,
2156 .get_dimensions = gui_window_get_dimensions,
2157 .event = gui_window_event,
2158
2159 .set_url = gui_window_set_url,
2160 .set_status = gui_window_set_status,
2161 .set_pointer = gui_window_set_pointer,
2162 .place_caret = gui_window_place_caret,
2163};
2164
2165
2166static struct gui_misc_table framebuffer_misc_table = {
2167 .schedule = framebuffer_schedule,
2168
2169 .quit = gui_quit,
2170};
2171
2172/**
2173 * Entry point from OS.
2174 *
2175 * /param argc The number of arguments in the string vector.
2176 * /param argv The argument string vector.
2177 * /return The return code to the OS
2178 */
2179int
2180main(int argc, char** argv)
2181{
2182 struct browser_window *bw;
2183 char *options;
2184 char *messages;
2185 nsurl *url;
2186 nserror ret;
2187 nsfb_t *nsfb;
2188 struct netsurf_table framebuffer_table = {
2189 .misc = &framebuffer_misc_table,
2190 .window = &framebuffer_window_table,
2191 .clipboard = framebuffer_clipboard_table,
2192 .fetch = framebuffer_fetch_table,
2193 .utf8 = framebuffer_utf8_table,
2194 .bitmap = framebuffer_bitmap_table,
2195 .layout = framebuffer_layout_table,
2196 };
2197
2198 ret = netsurf_register(&framebuffer_table);
2199 if (ret != NSERROR_OK) {
2200 die("NetSurf operation table failed registration");
2201 }
2202
2203 respaths = fb_init_resource_path(NETSURF_FB_RESPATH"${HOME}/.netsurf/:${NETSURFRES}:/var/lib/jenkins/artifacts-x86_64-linux-gnu/share/netsurf:./frontends/framebuffer/res"":"NETSURF_FB_FONTPATH"/usr/share/fonts/truetype/dejavu:/usr/share/fonts/truetype/msttcorefonts");
2204
2205 /* initialise logging. Not fatal if it fails but not much we
2206 * can do about it either.
2207 */
2208 nslog_init(nslog_stream_configure, &argc, argv);
2209
2210 /* user options setup */
2211 ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
2212 if (ret != NSERROR_OK) {
2213 die("Options failed to initialise");
2214 }
2215 options = filepath_find(respaths, "Choices");
2216 nsoption_read(options, nsoptions);
2217 free(options);
2218 nsoption_commandline(&argc, argv, nsoptions);
2219
2220 /* message init */
2221 messages = filepath_find(respaths, "Messages");
2222 ret = messages_add_from_file(messages);
2223 free(messages);
2224 if (ret != NSERROR_OK) {
2225 fprintf(stderrstderr, "Message translations failed to load\n");
2226 }
2227
2228 /* common initialisation */
2229 ret = netsurf_init(NULL((void*)0));
2230 if (ret != NSERROR_OK) {
2231 die("NetSurf failed to initialise");
2232 }
2233
2234 /* Override, since we have no support for non-core SELECT menu */
2235 nsoption_set_bool(core_select_menu, true)nsoptions[NSOPTION_core_select_menu].value.b = 1;
2236
2237 if (process_cmdline(argc,argv) != true1)
2238 die("unable to process command line.\n");
2239
2240 nsfb = framebuffer_initialise(fename, fewidth, feheight, febpp);
2241 if (nsfb == NULL((void*)0))
2242 die("Unable to initialise framebuffer");
2243
2244 framebuffer_set_cursor(&pointer_image);
2245
2246 if (fb_font_init() == false0)
2247 die("Unable to initialise the font system");
2248
2249 fbtk = fbtk_init(nsfb);
2250
2251 fbtk_enable_oskb(fbtk);
2252
2253 urldb_load_cookies(nsoption_charp(cookie_file)(nsoptions[NSOPTION_cookie_file].value.s));
2254
2255 /* create an initial browser window */
2256
2257 NSLOG(netsurf, INFO, "calling browser_window_create")do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 2257
, }; nslog__log(&_nslog_ctx, "calling browser_window_create"
); } } while(0)
;
2258
2259 ret = nsurl_create(feurl, &url);
2260 if (ret == NSERROR_OK) {
2261 ret = browser_window_create(BW_CREATE_HISTORY,
2262 url,
2263 NULL((void*)0),
2264 NULL((void*)0),
2265 &bw);
2266 nsurl_unref(url);
2267 }
2268 if (ret != NSERROR_OK) {
2269 fb_warn_user("Errorcode:", messages_get_errorcode(ret));
2270 } else {
2271 framebuffer_run();
2272
2273 browser_window_destroy(bw);
2274 }
2275
2276 netsurf_exit();
2277
2278 if (fb_font_finalise() == false0)
2279 NSLOG(netsurf, INFO, "Font finalisation failed.")do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/framebuffer/gui.c", sizeof("frontends/framebuffer/gui.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 2279
, }; nslog__log(&_nslog_ctx, "Font finalisation failed.")
; } } while(0)
;
2280
2281 /* finalise options */
2282 nsoption_finalise(nsoptions, nsoptions_default);
2283
2284 /* finalise logging */
2285 nslog_finalise();
2286
2287 return 0;
2288}
2289
2290void gui_resize(fbtk_widget_t *root, int width, int height)
2291{
2292 struct gui_window *gw;
2293 nsfb_t *nsfb = fbtk_get_nsfb(root);
2294
2295 /* Enforce a minimum */
2296 if (width < 300)
2297 width = 300;
2298 if (height < 200)
2299 height = 200;
2300
2301 if (framebuffer_resize(nsfb, width, height, febpp) == false0) {
2302 return;
2303 }
2304
2305 fbtk_set_pos_and_size(root, 0, 0, width, height);
2306
2307 fewidth = width;
2308 feheight = height;
2309
2310 for (gw = window_list; gw != NULL((void*)0); gw = gw->next) {
2311 resize_normal_browser_window(gw,
2312 nsoption_int(fb_furniture_size)(nsoptions[NSOPTION_fb_furniture_size].value.i));
2313 }
2314
2315 fbtk_request_redraw(root);
2316}
2317
2318
2319/*
2320 * Local Variables:
2321 * c-basic-offset:8
2322 * End:
2323 */