Bug Summary

File:frontends/monkey/browser.c
Warning:line 410, column 14
Value stored to 'state' during its initialization 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 browser.c -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 -fdebug-compilation-dir=/var/lib/jenkins/workspace/scan-build-netsurf -fcoverage-compilation-dir=/var/lib/jenkins/workspace/scan-build-netsurf -resource-dir /usr/lib/llvm-19/lib/clang/19 -isystem /usr/include/mit-krb5 -I . -I include -I build/Linux-monkey -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 -I /usr/include/p11-kit-1 -D WITH_CURL -D WITH_OPENSSL -I /var/lib/jenkins/artifacts-x86_64-linux-gnu/include -D UTF8PROC_EXPORTS -D WITH_UTF8PROC -I /usr/include/webp -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_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 monkey -D nsmonkey -D MONKEY_RESPATH="/var/lib/jenkins/artifacts-x86_64-linux-gnu/share/netsurf/" -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-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../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 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -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/2025-11-30-120038-3051857-1 -x c frontends/monkey/browser.c
1/*
2 * Copyright 2011 Daniel Silverstone <dsilvers@digital-scurf.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/* Browser-related callbacks */
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include "utils/utils.h"
26#include "utils/ring.h"
27#include "utils/log.h"
28#include "utils/messages.h"
29#include "utils/nsurl.h"
30#include "netsurf/mouse.h"
31#include "netsurf/window.h"
32#include "netsurf/browser_window.h"
33#include "netsurf/plotters.h"
34
35#include "monkey/output.h"
36#include "monkey/browser.h"
37#include "monkey/plot.h"
38
39static uint32_t win_ctr = 0;
40
41static struct gui_window *gw_ring = NULL((void*)0);
42
43/* exported function documented in monkey/browser.h */
44nserror monkey_warn_user(const char *warning, const char *detail)
45{
46 moutf(MOUT_WARNING, "%s %s", warning, detail);
47 return NSERROR_OK;
48}
49
50struct gui_window *
51monkey_find_window_by_num(uint32_t win_num)
52{
53 struct gui_window *ret = NULL((void*)0);
54
55 RING_ITERATE_START(struct gui_window, gw_ring, c_ring)if (gw_ring != ((void*)0)) { struct gui_window *c_ring = gw_ring
; do { do {
{
56 if (c_ring->win_num == win_num) {
57 ret = c_ring;
58 RING_ITERATE_STOP(gw_ring, c_ring)goto iteration_end_ring_c_ring;
59 }
60 } RING_ITERATE_END(gw_ring, c_ring)} while (0); c_ring = c_ring->r_next; } while (c_ring != gw_ring
); } iteration_end_ring_c_ring:
;
61
62 return ret;
63}
64
65void
66monkey_kill_browser_windows(void)
67{
68 while (gw_ring != NULL((void*)0)) {
69 browser_window_destroy(gw_ring->bw);
70 }
71}
72
73static struct gui_window *
74gui_window_create(struct browser_window *bw,
75 struct gui_window *existing,
76 gui_window_create_flags flags)
77{
78 struct gui_window *ret = calloc(1, sizeof(*ret));
79 if (ret == NULL((void*)0))
80 return NULL((void*)0);
81
82 ret->win_num = win_ctr++;
83 ret->bw = bw;
84
85 ret->width = 800;
86 ret->height = 600;
87
88 moutf(MOUT_WINDOW,
89 "NEW WIN %u FOR %p EXISTING %p NEWTAB %s CLONE %s",
90 ret->win_num, bw, existing,
91 flags & GW_CREATE_TAB ? "TRUE" : "FALSE",
92 flags & GW_CREATE_CLONE ? "TRUE" : "FALSE");
93 moutf(MOUT_WINDOW,
94 "SIZE WIN %u WIDTH %d HEIGHT %d",
95 ret->win_num, ret->width, ret->height);
96
97 RING_INSERT(gw_ring, ret)if (gw_ring) { ret->r_next = gw_ring; ret->r_prev = gw_ring
->r_prev; gw_ring->r_prev = ret; ret->r_prev->r_next
= ret; } else gw_ring = ret->r_prev = ret->r_next = ret
;
98
99 return ret;
100}
101
102static void
103gui_window_destroy(struct gui_window *g)
104{
105 moutf(MOUT_WINDOW, "DESTROY WIN %u", g->win_num);
106 RING_REMOVE(gw_ring, g)if (g->r_next != g ) { g->r_next->r_prev = g->r_prev
; g->r_prev->r_next = g->r_next; if (gw_ring == g) gw_ring
= g->r_next; } else { gw_ring = 0; } g->r_next = g->
r_prev = 0
;
107 free(g);
108}
109
110static void
111gui_window_set_title(struct gui_window *g, const char *title)
112{
113 moutf(MOUT_WINDOW, "TITLE WIN %u STR %s", g->win_num, title);
114}
115
116/**
117 * Find the current dimensions of a monkey browser window content area.
118 *
119 * \param g The gui window to measure content area of.
120 * \param width receives width of window
121 * \param height receives height of window
122 * \return NSERROR_OK on sucess and width and height updated.
123 */
124static nserror
125gui_window_get_dimensions(struct gui_window *g, int *width, int *height)
126{
127 *width = g->width;
128 *height = g->height;
129
130 moutf(MOUT_WINDOW,
131 "GET_DIMENSIONS WIN %u WIDTH %d HEIGHT %d",
132 g->win_num, *width, *height);
133
134 return NSERROR_OK;
135}
136
137static void
138gui_window_new_content(struct gui_window *g)
139{
140 moutf(MOUT_WINDOW, "NEW_CONTENT WIN %u", g->win_num);
141}
142
143static void
144gui_window_set_icon(struct gui_window *g, struct hlcache_handle *icon)
145{
146 moutf(MOUT_WINDOW, "NEW_ICON WIN %u", g->win_num);
147}
148
149static void
150gui_window_start_throbber(struct gui_window *g)
151{
152 moutf(MOUT_WINDOW, "START_THROBBER WIN %u", g->win_num);
153}
154
155static void
156gui_window_stop_throbber(struct gui_window *g)
157{
158 moutf(MOUT_WINDOW, "STOP_THROBBER WIN %u", g->win_num);
159}
160
161
162/**
163 * Set the scroll position of a monkey browser window.
164 *
165 * Scrolls the viewport to ensure the specified rectangle of the
166 * content is shown.
167 *
168 * \param gw gui window to scroll
169 * \param rect The rectangle to ensure is shown.
170 * \return NSERROR_OK on success or apropriate error code.
171 */
172static nserror
173gui_window_set_scroll(struct gui_window *gw, const struct rect *rect)
174{
175 gw->scrollx = rect->x0;
176 gw->scrolly = rect->y0;
177
178 moutf(MOUT_WINDOW, "SET_SCROLL WIN %u X %d Y %d",
179 gw->win_num, rect->x0, rect->y0);
180 return NSERROR_OK;
181}
182
183
184/**
185 * Invalidates an area of a monkey browser window
186 *
187 * \param gw gui_window
188 * \param rect area to redraw or NULL for the entire window area
189 * \return NSERROR_OK on success or appropriate error code
190 */
191static nserror
192monkey_window_invalidate_area(struct gui_window *gw, const struct rect *rect)
193{
194 if (rect != NULL((void*)0)) {
195 moutf(MOUT_WINDOW,
196 "INVALIDATE_AREA WIN %u X %d Y %d WIDTH %d HEIGHT %d",
197 gw->win_num,
198 rect->x0, rect->y0,
199 (rect->x1 - rect->x0), (rect->y1 - rect->y0));
200 } else {
201 moutf(MOUT_WINDOW, "INVALIDATE_AREA WIN %u ALL", gw->win_num);
202 }
203
204 return NSERROR_OK;
205}
206
207static void
208gui_window_update_extent(struct gui_window *g)
209{
210 int width, height;
211
212 if (browser_window_get_extents(g->bw, false0, &width, &height) != NSERROR_OK)
213 return;
214
215 moutf(MOUT_WINDOW, "UPDATE_EXTENT WIN %u WIDTH %d HEIGHT %d",
216 g->win_num, width, height);
217}
218
219static void
220gui_window_set_status(struct gui_window *g, const char *text)
221{
222 moutf(MOUT_WINDOW, "SET_STATUS WIN %u STR %s", g->win_num, text);
223}
224
225static void
226gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape)
227{
228 const char *ptr_name = "UNKNOWN";
229
230 switch (shape) {
231 case GUI_POINTER_POINT:
232 ptr_name = "POINT";
233 break;
234 case GUI_POINTER_CARET:
235 ptr_name = "CARET";
236 break;
237 case GUI_POINTER_UP:
238 ptr_name = "UP";
239 break;
240 case GUI_POINTER_DOWN:
241 ptr_name = "DOWN";
242 break;
243 case GUI_POINTER_LEFT:
244 ptr_name = "LEFT";
245 break;
246 case GUI_POINTER_RIGHT:
247 ptr_name = "RIGHT";
248 break;
249 case GUI_POINTER_LD:
250 ptr_name = "LD";
251 break;
252 case GUI_POINTER_RD:
253 ptr_name = "RD";
254 break;
255 case GUI_POINTER_LU:
256 ptr_name = "LU";
257 break;
258 case GUI_POINTER_RU:
259 ptr_name = "RU";
260 break;
261 case GUI_POINTER_CROSS:
262 ptr_name = "CROSS";
263 break;
264 case GUI_POINTER_MOVE:
265 ptr_name = "MOVE";
266 break;
267 case GUI_POINTER_WAIT:
268 ptr_name = "WAIT";
269 break;
270 case GUI_POINTER_HELP:
271 ptr_name = "HELP";
272 break;
273 case GUI_POINTER_MENU:
274 ptr_name = "MENU";
275 break;
276 case GUI_POINTER_PROGRESS:
277 ptr_name = "PROGRESS";
278 break;
279 case GUI_POINTER_NO_DROP:
280 ptr_name = "NO_DROP";
281 break;
282 case GUI_POINTER_NOT_ALLOWED:
283 ptr_name = "NOT_ALLOWED";
284 break;
285 case GUI_POINTER_DEFAULT:
286 ptr_name = "DEFAULT";
287 break;
288 default:
289 break;
290 }
291
292 moutf(MOUT_WINDOW, "SET_POINTER WIN %u POINTER %s",
293 g->win_num, ptr_name);
294}
295
296static nserror
297gui_window_set_url(struct gui_window *g, nsurl *url)
298{
299 moutf(MOUT_WINDOW, "SET_URL WIN %u URL %s",
300 g->win_num, nsurl_access(url));
301 return NSERROR_OK;
302}
303
304static bool_Bool
305gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
306{
307 moutf(MOUT_WINDOW, "GET_SCROLL WIN %u X %d Y %d",
308 g->win_num, g->scrollx, g->scrolly);
309 *sx = g->scrollx;
310 *sy = g->scrolly;
311 return true1;
312}
313
314static bool_Bool
315gui_window_scroll_start(struct gui_window *g)
316{
317 moutf(MOUT_WINDOW, "SCROLL_START WIN %u", g->win_num);
318 g->scrollx = g->scrolly = 0;
319 return true1;
320}
321
322
323static void
324gui_window_place_caret(struct gui_window *g, int x, int y, int height,
325 const struct rect *clip)
326{
327 moutf(MOUT_WINDOW, "PLACE_CARET WIN %u X %d Y %d HEIGHT %d",
328 g->win_num, x, y, height);
329}
330
331static void
332gui_window_remove_caret(struct gui_window *g)
333{
334 moutf(MOUT_WINDOW, "REMOVE_CARET WIN %u", g->win_num);
335}
336
337static bool_Bool
338gui_window_drag_start(struct gui_window *g, gui_drag_type type,
339 const struct rect *rect)
340{
341 moutf(MOUT_WINDOW, "SCROLL_START WIN %u TYPE %i", g->win_num, type);
342 return false0;
343}
344
345static nserror
346gui_window_save_link(struct gui_window *g, nsurl *url, const char *title)
347{
348 moutf(MOUT_WINDOW, "SAVE_LINK WIN %u URL %s TITLE %s",
349 g->win_num, nsurl_access(url), title);
350 return NSERROR_OK;
351}
352
353static void
354gui_window_console_log(struct gui_window *g,
355 browser_window_console_source src,
356 const char *msg,
357 size_t msglen,
358 browser_window_console_flags flags)
359{
360 bool_Bool foldable = !!(flags & BW_CS_FLAG_FOLDABLE);
361 const char *src_text;
362 const char *level_text;
363
364 switch (src) {
365 case BW_CS_INPUT:
366 src_text = "client-input";
367 break;
368 case BW_CS_SCRIPT_ERROR:
369 src_text = "scripting-error";
370 break;
371 case BW_CS_SCRIPT_CONSOLE:
372 src_text = "scripting-console";
373 break;
374 default:
375 assert(0 && "Unknown scripting source")((0 && "Unknown scripting source") ? (void) (0) : __assert_fail
("0 && \"Unknown scripting source\"", "frontends/monkey/browser.c"
, 375, __extension__ __PRETTY_FUNCTION__))
;
376 src_text = "unknown";
377 break;
378 }
379
380 switch (flags & BW_CS_FLAG_LEVEL_MASK) {
381 case BW_CS_FLAG_LEVEL_DEBUG:
382 level_text = "DEBUG";
383 break;
384 case BW_CS_FLAG_LEVEL_LOG:
385 level_text = "LOG";
386 break;
387 case BW_CS_FLAG_LEVEL_INFO:
388 level_text = "INFO";
389 break;
390 case BW_CS_FLAG_LEVEL_WARN:
391 level_text = "WARN";
392 break;
393 case BW_CS_FLAG_LEVEL_ERROR:
394 level_text = "ERROR";
395 break;
396 default:
397 assert(0 && "Unknown console logging level")((0 && "Unknown console logging level") ? (void) (0) :
__assert_fail ("0 && \"Unknown console logging level\""
, "frontends/monkey/browser.c", 397, __extension__ __PRETTY_FUNCTION__
))
;
398 level_text = "unknown";
399 break;
400 }
401
402 moutf(MOUT_WINDOW, "CONSOLE_LOG WIN %u SOURCE %s %sFOLDABLE %s %.*s",
403 g->win_num, src_text, foldable ? "" : "NOT-", level_text,
404 (int)msglen, msg);
405}
406
407static void
408gui_window_report_page_info(struct gui_window *g)
1
[debug] analyzing from gui_window_report_page_info
409{
410 const char *state = "***WAH***";
2
Value stored to 'state' during its initialization is never read
411
412 switch (browser_window_get_page_info_state(g->bw)) {
413 case PAGE_STATE_UNKNOWN:
414 state = "UNKNOWN";
415 break;
416
417 case PAGE_STATE_INTERNAL:
418 state = "INTERNAL";
419 break;
420
421 case PAGE_STATE_LOCAL:
422 state = "LOCAL";
423 break;
424
425 case PAGE_STATE_INSECURE:
426 state = "INSECURE";
427 break;
428
429 case PAGE_STATE_SECURE_OVERRIDE:
430 state = "SECURE_OVERRIDE";
431 break;
432
433 case PAGE_STATE_SECURE_ISSUES:
434 state = "SECURE_ISSUES";
435 break;
436
437 case PAGE_STATE_SECURE:
438 state = "SECURE";
439 break;
440
441 default:
442 assert(0 && "Monkey needs some lovin' here")((0 && "Monkey needs some lovin' here") ? (void) (0) :
__assert_fail ("0 && \"Monkey needs some lovin' here\""
, "frontends/monkey/browser.c", 442, __extension__ __PRETTY_FUNCTION__
))
;
443 break;
444 }
445 moutf(MOUT_WINDOW, "PAGE_STATUS WIN %u STATUS %s",
446 g->win_num, state);
447}
448
449/**** Handlers ****/
450
451static void
452monkey_window_handle_new(int argc, char **argv)
453{
454 nsurl *url = NULL((void*)0);
455 nserror error = NSERROR_OK;
456
457 if (argc > 3)
458 return;
459
460 if (argc == 3) {
461 error = nsurl_create(argv[2], &url);
462 }
463 if (error == NSERROR_OK) {
464 error = browser_window_create(BW_CREATE_HISTORY,
465 url,
466 NULL((void*)0),
467 NULL((void*)0),
468 NULL((void*)0));
469 if (url != NULL((void*)0)) {
470 nsurl_unref(url);
471 }
472 }
473 if (error != NSERROR_OK) {
474 monkey_warn_user(messages_get_errorcode(error), 0);
475 }
476}
477
478static void
479monkey_window_handle_destroy(int argc, char **argv)
480{
481 struct gui_window *gw;
482 uint32_t nr = atoi((argc > 2) ? argv[2] : "-1");
483
484 gw = monkey_find_window_by_num(nr);
485
486 if (gw == NULL((void*)0)) {
487 moutf(MOUT_ERROR, "WINDOW NUM BAD");
488 } else {
489 browser_window_destroy(gw->bw);
490 }
491}
492
493static void
494monkey_window_handle_go(int argc, char **argv)
495{
496 struct gui_window *gw;
497 nsurl *url;
498 nsurl *ref_url = NULL((void*)0);
499 nserror error;
500
501 if (argc < 4 || argc > 5) {
502 moutf(MOUT_ERROR, "WINDOW GO ARGS BAD");
503 return;
504 }
505
506 gw = monkey_find_window_by_num(atoi(argv[2]));
507
508 if (gw == NULL((void*)0)) {
509 moutf(MOUT_ERROR, "WINDOW NUM BAD");
510 return;
511 }
512
513 error = nsurl_create(argv[3], &url);
514 if (error == NSERROR_OK) {
515 if (argc == 5) {
516 error = nsurl_create(argv[4], &ref_url);
517 }
518
519 if (error == NSERROR_OK) {
520 error = browser_window_navigate(gw->bw,
521 url,
522 ref_url,
523 BW_NAVIGATE_HISTORY,
524 NULL((void*)0),
525 NULL((void*)0),
526 NULL((void*)0));
527 if (ref_url != NULL((void*)0)) {
528 nsurl_unref(ref_url);
529 }
530 }
531 nsurl_unref(url);
532 }
533
534 if (error != NSERROR_OK) {
535 monkey_warn_user(messages_get_errorcode(error), 0);
536 }
537}
538
539/**
540 * handle WINDOW STOP command
541 */
542static void
543monkey_window_handle_stop(int argc, char **argv)
544{
545 struct gui_window *gw;
546 if (argc != 3) {
547 moutf(MOUT_ERROR, "WINDOW STOP ARGS BAD\n");
548 return;
549 }
550
551 gw = monkey_find_window_by_num(atoi(argv[2]));
552
553 if (gw == NULL((void*)0)) {
554 moutf(MOUT_ERROR, "WINDOW NUM BAD");
555 } else {
556 browser_window_stop(gw->bw);
557 }
558}
559
560
561static void
562monkey_window_handle_redraw(int argc, char **argv)
563{
564 struct gui_window *gw;
565 struct rect clip;
566 struct redraw_context ctx = {
567 .interactive = true1,
568 .background_images = true1,
569 .plot = monkey_plotters
570 };
571
572 if (argc != 3 && argc != 7) {
573 moutf(MOUT_ERROR, "WINDOW REDRAW ARGS BAD");
574 return;
575 }
576
577 gw = monkey_find_window_by_num(atoi(argv[2]));
578
579 if (gw == NULL((void*)0)) {
580 moutf(MOUT_ERROR, "WINDOW NUM BAD");
581 return;
582 }
583
584 clip.x0 = 0;
585 clip.y0 = 0;
586 clip.x1 = gw->width;
587 clip.y1 = gw->height;
588
589 if (argc == 7) {
590 clip.x0 = atoi(argv[3]);
591 clip.y0 = atoi(argv[4]);
592 clip.x1 = atoi(argv[5]);
593 clip.y1 = atoi(argv[6]);
594 }
595
596 NSLOG(netsurf, INFO, "Issue redraw")do { if (NSLOG_LEVEL_INFO >= NSLOG_LEVEL_VERBOSE) { static
nslog_entry_context_t _nslog_ctx = { &__nslog_category_netsurf
, NSLOG_LEVEL_INFO, "frontends/monkey/browser.c", sizeof("frontends/monkey/browser.c"
) - 1, __PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1, 596
, }; nslog__log(&_nslog_ctx, "Issue redraw"); } } while(0
)
;
597 moutf(MOUT_WINDOW, "REDRAW WIN %d START", atoi(argv[2]));
598 browser_window_redraw(gw->bw, gw->scrollx, gw->scrolly, &clip, &ctx);
599 moutf(MOUT_WINDOW, "REDRAW WIN %d STOP", atoi(argv[2]));
600}
601
602static void
603monkey_window_handle_reload(int argc, char **argv)
604{
605 struct gui_window *gw;
606 if (argc != 3 && argc != 4) {
607 moutf(MOUT_ERROR, "WINDOW RELOAD ARGS BAD\n");
608 return;
609 }
610
611 gw = monkey_find_window_by_num(atoi(argv[2]));
612
613 if (gw == NULL((void*)0)) {
614 moutf(MOUT_ERROR, "WINDOW NUM BAD");
615 } else {
616 browser_window_reload(gw->bw, argc == 4);
617 }
618}
619
620static void
621monkey_window_handle_exec(int argc, char **argv)
622{
623 struct gui_window *gw;
624 if (argc < 5) {
625 moutf(MOUT_ERROR, "WINDOW EXEC ARGS BAD\n");
626 }
627
628 gw = monkey_find_window_by_num(atoi(argv[2]));
629
630 if (gw == NULL((void*)0)) {
631 moutf(MOUT_ERROR, "WINDOW NUM BAD");
632 } else {
633 /* Gather argv[4] onward into a string to pass to js_exec */
634 int total = 1;
635 for (int i = 4; i < argc; ++i) {
636 total += strlen(argv[i]) + 1;
637 }
638 char *cmd = calloc(total, 1);
639 if (cmd == NULL((void*)0)) {
640 moutf(MOUT_ERROR, "JS WIN %d RET ENOMEM", atoi(argv[2]));
641 return;
642 }
643 strcpy(cmd, argv[4]);
644 for (int i = 5; i < argc; ++i) {
645 strcat(cmd, " ");
646 strcat(cmd, argv[i]);
647 }
648 /* Now execute the JS */
649
650 moutf(MOUT_WINDOW, "JS WIN %d RET %s", atoi(argv[2]),
651 browser_window_exec(gw->bw, cmd, total - 1) ? "TRUE" : "FALSE");
652
653 free(cmd);
654 }
655}
656
657
658static void
659monkey_window_handle_click(int argc, char **argv)
660{
661 /* `WINDOW CLICK WIN` _%id%_ `X` _%num%_ `Y` _%num%_ `BUTTON` _%str%_ `KIND` _%str%_ */
662 /* 0 1 2 3 4 5 6 7 8 9 10 11 */
663 struct gui_window *gw;
664 if (argc != 12) {
665 moutf(MOUT_ERROR, "WINDOW CLICK ARGS BAD\n");
666 }
667
668 gw = monkey_find_window_by_num(atoi(argv[2]));
669
670 if (gw == NULL((void*)0)) {
671 moutf(MOUT_ERROR, "WINDOW NUM BAD");
672 } else {
673 int x = atoi(argv[5]);
674 int y = atoi(argv[7]);
675 browser_mouse_state mouse;
676 const char *button = argv[9];
677 const char *kind = argv[11];
678 if (strcmp(button, "LEFT") == 0) {
679 mouse = BROWSER_MOUSE_CLICK_1;
680 } else if (strcmp(button, "RIGHT") == 0) {
681 mouse = BROWSER_MOUSE_CLICK_2;
682 } else {
683 moutf(MOUT_ERROR, "WINDOW BUTTON BAD");
684 return;
685 }
686 if (strcmp(kind, "SINGLE") == 0) {
687 /* Nothing */
688 } else if (strcmp(kind, "DOUBLE") == 0) {
689 mouse |= BROWSER_MOUSE_DOUBLE_CLICK;
690 } else if (strcmp(kind, "TRIPLE") == 0) {
691 mouse |= BROWSER_MOUSE_TRIPLE_CLICK;
692 } else {
693 moutf(MOUT_ERROR, "WINDOW KIND BAD");
694 return;
695 }
696 browser_window_mouse_click(gw->bw, mouse, x, y);
697 }
698}
699
700void
701monkey_window_handle_command(int argc, char **argv)
702{
703 if (argc == 1)
704 return;
705
706 if (strcmp(argv[1], "NEW") == 0) {
707 monkey_window_handle_new(argc, argv);
708 } else if (strcmp(argv[1], "DESTROY") == 0) {
709 monkey_window_handle_destroy(argc, argv);
710 } else if (strcmp(argv[1], "GO") == 0) {
711 monkey_window_handle_go(argc, argv);
712 } else if (strcmp(argv[1], "STOP") == 0) {
713 monkey_window_handle_stop(argc, argv);
714 } else if (strcmp(argv[1], "REDRAW") == 0) {
715 monkey_window_handle_redraw(argc, argv);
716 } else if (strcmp(argv[1], "RELOAD") == 0) {
717 monkey_window_handle_reload(argc, argv);
718 } else if (strcmp(argv[1], "EXEC") == 0) {
719 monkey_window_handle_exec(argc, argv);
720 } else if (strcmp(argv[1], "CLICK") == 0) {
721 monkey_window_handle_click(argc, argv);
722 } else {
723 moutf(MOUT_ERROR, "WINDOW COMMAND UNKNOWN %s\n", argv[1]);
724 }
725
726}
727
728/**
729 * process miscellaneous window events
730 *
731 * \param gw The window receiving the event.
732 * \param event The event code.
733 * \return NSERROR_OK when processed ok
734 */
735static nserror
736gui_window_event(struct gui_window *gw, enum gui_window_event event)
737{
738 switch (event) {
739 case GW_EVENT_UPDATE_EXTENT:
740 gui_window_update_extent(gw);
741 break;
742
743 case GW_EVENT_REMOVE_CARET:
744 gui_window_remove_caret(gw);
745 break;
746
747 case GW_EVENT_SCROLL_START:
748 gui_window_scroll_start(gw);
749 break;
750
751 case GW_EVENT_NEW_CONTENT:
752 gui_window_new_content(gw);
753 break;
754
755 case GW_EVENT_START_THROBBER:
756 gui_window_start_throbber(gw);
757 break;
758
759 case GW_EVENT_STOP_THROBBER:
760 gui_window_stop_throbber(gw);
761 break;
762
763 case GW_EVENT_PAGE_INFO_CHANGE:
764 gui_window_report_page_info(gw);
765 break;
766
767 default:
768 break;
769 }
770 return NSERROR_OK;
771}
772
773static struct gui_window_table window_table = {
774 .create = gui_window_create,
775 .destroy = gui_window_destroy,
776 .invalidate = monkey_window_invalidate_area,
777 .get_scroll = gui_window_get_scroll,
778 .set_scroll = gui_window_set_scroll,
779 .get_dimensions = gui_window_get_dimensions,
780 .event = gui_window_event,
781
782 .set_title = gui_window_set_title,
783 .set_url = gui_window_set_url,
784 .set_icon = gui_window_set_icon,
785 .set_status = gui_window_set_status,
786 .set_pointer = gui_window_set_pointer,
787 .place_caret = gui_window_place_caret,
788 .drag_start = gui_window_drag_start,
789 .save_link = gui_window_save_link,
790
791 .console_log = gui_window_console_log,
792};
793
794struct gui_window_table *monkey_window_table = &window_table;