NetSurf
browser_history.c
Go to the documentation of this file.
1/*
2 * Copyright 2006 James Bursa <bursa@users.sourceforge.net>
3 * Copyright 2005 Richard Wilson <info@tinct.net>
4 *
5 * This file is part of NetSurf, http://www.netsurf-browser.org/
6 *
7 * NetSurf is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * NetSurf is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20/**
21 * \file
22 * Browser history tree implementation.
23 */
24
25#include <assert.h>
26#include <stdbool.h>
27#include <stdlib.h>
28#include <string.h>
29#include <time.h>
30
31#include "utils/log.h"
32#include "utils/utils.h"
33#include "netsurf/layout.h"
34#include "netsurf/content.h"
35#include "netsurf/window.h"
37#include "content/hlcache.h"
38#include "content/urldb.h"
39#include "netsurf/bitmap.h"
40#include "utils/corestrings.h"
41
46
47/**
48 * Clone a history entry
49 *
50 * \param history opaque history structure, as returned by history_create()
51 * \param entry entry to clone
52 * \return A cloned history entry or NULL on error
53 */
54static struct history_entry *
56 struct history_entry *entry)
57{
58 struct history_entry *child;
59 struct history_entry *new_child;
60 struct history_entry *prev = NULL;
61 struct history_entry *new_entry;
62
63 assert(entry);
64 assert(entry->page.url);
65 assert(entry->page.title);
66
67 /* clone the entry */
68 new_entry = calloc(1, sizeof *entry);
69 if (!new_entry) {
70 return NULL;
71 }
72
73 /* copy page information */
74 new_entry->page.title = strdup(entry->page.title);
75 if (new_entry->page.title == NULL) {
76 free(new_entry);
77 return NULL;
78 }
79
80 new_entry->page.url = nsurl_ref(entry->page.url);
81 if (new_entry->page.url == NULL) {
82 free(new_entry->page.title);
83 free(new_entry);
84 return NULL;
85 }
86
87 if (entry->page.frag_id == NULL) {
88 new_entry->page.frag_id = NULL;
89 } else {
90 new_entry->page.frag_id = lwc_string_ref(entry->page.frag_id);
91 if (new_entry->page.frag_id == NULL) {
92 nsurl_unref(new_entry->page.url);
93 free(new_entry);
94 return NULL;
95 }
96 }
97
98 if (entry->page.bitmap == NULL) {
99 new_entry->page.bitmap = NULL;
100 } else {
101 /* create a new bitmap and copy original into it */
102 unsigned char *bmsrc_data;
103 unsigned char *bmdst_data;
104 size_t bmsize;
105
106 new_entry->page.bitmap = guit->bitmap->create(
110
111 if (new_entry->page.bitmap != NULL) {
112 bmsrc_data = guit->bitmap->get_buffer(entry->page.bitmap);
113 bmdst_data = guit->bitmap->get_buffer(new_entry->page.bitmap);
114 bmsize = guit->bitmap->get_rowstride(new_entry->page.bitmap) *
115 guit->bitmap->get_height(new_entry->page.bitmap);
116 memcpy(bmdst_data, bmsrc_data, bmsize);
117 }
118 }
119
120 /* copy tree values */
121 new_entry->back = entry->back;
122 new_entry->next = entry->next;
123 new_entry->forward = entry->forward;
124 new_entry->forward_pref = entry->forward_pref;
125 new_entry->forward_last = entry->forward_last;
126
127 /* recurse for all children */
128 for (child = new_entry->forward; child != NULL; child = child->next) {
130 if (new_child == NULL) {
131 nsurl_unref(new_entry->page.url);
132 lwc_string_unref(new_entry->page.frag_id);
133 free(new_entry->page.title);
134 if (entry->page.bitmap != NULL) {
135 guit->bitmap->destroy(entry->page.bitmap);
136 }
137 free(new_entry);
138 return NULL;
139 }
140
141 new_child->back = new_entry;
142 if (prev)
143 prev->next = new_child;
144 if (new_entry->forward == child)
145 new_entry->forward = new_child;
146 if (new_entry->forward_pref == child)
147 new_entry->forward_pref = new_child;
148 if (new_entry->forward_last == child)
149 new_entry->forward_last = new_child;
150 prev = new_child;
151 }
152
153 /* update references */
154 if (history->current == entry) {
155 history->current = new_entry;
156 }
157
158 return new_entry;
159}
160
161
162/**
163 * Free an entry in the tree recursively.
164 */
165
167{
168 if (entry != NULL) {
171
172 nsurl_unref(entry->page.url);
173 lwc_string_unref(entry->page.frag_id);
174 free(entry->page.title);
175 if (entry->page.bitmap != NULL) {
176 guit->bitmap->destroy(entry->page.bitmap);
177 }
178 free(entry);
179 }
180}
181
182
183/**
184 * Recursively position a subtree.
185 *
186 * \param history history being laid out
187 * \param entry subtree to position
188 * \param x x position for entry
189 * \param y smallest available y
190 * \return greatest y used by subtree
191 */
192
194 struct history_entry *entry, int x, int y)
195{
196 struct history_entry *child;
197 int y1 = y;
198
201
202 if (!entry->forward) {
203 entry->x = x;
204 entry->y = y;
205 return y + LOCAL_HISTORY_HEIGHT;
206 }
207
208 /* layout child subtrees below each other */
209 for (child = entry->forward; child; child = child->next) {
212 if (child->next)
214 }
215
216 /* place ourselves in the middle */
217 entry->x = x;
218 entry->y = (y + y1) / 2 - LOCAL_HISTORY_HEIGHT / 2;
219
220 return y1;
221}
222
223
224/**
225 * Compute node positions.
226 *
227 * \param history history to layout
228 *
229 * Each node's x and y are filled in.
230 */
231
233{
234 if (!history)
235 return;
236
237 history->width = 0;
238 if (history->start)
243 else
244 history->height = 0;
245
248}
249
250
251
252
253
254/**
255 * Enumerate subentries in history
256 * See also history_enumerate()
257 *
258 * \param bw The browser window to enumerate history of
259 * \param entry entry to start enumeration at
260 * \param cb callback function
261 * \param ud context pointer passed to cb
262 * \return true to continue enumeration, false to cancel
263 */
265 const struct browser_window *bw,
266 const struct history_entry *entry,
268 void *ud)
269{
270 const struct history_entry *child;
271
272 if (!cb(bw, entry->x, entry->y,
273 entry->x + LOCAL_HISTORY_WIDTH,
274 entry->y + LOCAL_HISTORY_HEIGHT,
275 entry, ud))
276 return false;
277
278 for (child = entry->forward; child; child = child->next) {
280 cb, ud))
281 return false;
282 }
283
284 return true;
285}
286
287
288/* -------------------------------------------------------------------------- */
289
290
291/* exported interface documented in desktop/browser_history.h */
293{
294 struct history *history;
295
296 bw->history = NULL;
297
298 history = calloc(1, sizeof *history);
299 if (history == NULL) {
300 return NSERROR_NOMEM;
301 }
302
305
306 bw->history = history;
307
308 return NSERROR_OK;
309}
310
311
312/* exported interface documented in desktop/browser_history.h */
314 struct browser_window *clone)
315{
316 struct history *new_history;
317
318 clone->history = NULL;
319
320 if (existing == NULL || existing->history == NULL ||
321 existing->history->start == NULL)
322 /* Nothing to clone, create new history for clone window */
323 return browser_window_history_create(clone);
324
325 /* Make cloned history */
326 new_history = malloc(sizeof *new_history);
327 if (!new_history)
328 return NSERROR_NOMEM;
329
330 clone->history = new_history;
331 memcpy(new_history, existing->history, sizeof *new_history);
332
333 new_history->start = browser_window_history__clone_entry(new_history,
334 new_history->start);
335 if (!new_history->start) {
336 NSLOG(netsurf, INFO, "Insufficient memory to clone history");
338 clone->history = NULL;
339 return NSERROR_NOMEM;
340 }
341
342 return NSERROR_OK;
343}
344
345
346/* exported interface documented in desktop/browser_history.h */
349 struct hlcache_handle *content,
350 lwc_string *frag_id)
351{
352 struct history *history;
353 struct history_entry *entry;
354 char *title;
355 nserror ret;
356
357 assert(bw);
358 assert(bw->history);
359 assert(content);
360
361 history = bw->history;
362
363 entry = malloc(sizeof *entry);
364 if (entry == NULL) {
365 return NSERROR_NOMEM;
366 }
367
368 /* page information */
369 title = strdup(content_get_title(content));
370 if (title == NULL) {
371 free(entry);
372 return NSERROR_NOMEM;
373 }
374
376 entry->page.frag_id = frag_id ? lwc_string_ref(frag_id) : NULL;
377 entry->page.title = title;
378 entry->page.scroll_x = 0.0f;
379 entry->page.scroll_y = 0.0f;
380
381 /* create thumbnail for localhistory view */
382 NSLOG(netsurf, DEBUG,
383 "Creating thumbnail for %s", nsurl_access(entry->page.url));
384
385 entry->page.bitmap = guit->bitmap->create(
388 if (entry->page.bitmap != NULL) {
389 ret = guit->bitmap->render(entry->page.bitmap, content);
390 if (ret != NSERROR_OK) {
391 /* Thumbnail render failed */
392 NSLOG(netsurf, WARNING, "Thumbnail render failed");
393 }
394 }
395
396 /* insert into tree */
397 entry->back = history->current;
398 entry->next = NULL;
399 entry->forward = entry->forward_pref = entry->forward_last = NULL;
400 entry->children = 0;
401
402 if (history->current) {
404 history->current->forward_last->next = entry;
405 } else {
406 history->current->forward = entry;
407 }
408 history->current->forward_pref = entry;
409 history->current->forward_last = entry;
411 } else {
412 history->start = entry;
413 }
414 history->current = entry;
415
417
418 return NSERROR_OK;
419}
420
421
422/* exported interface documented in desktop/browser_history.h */
424 struct hlcache_handle *content)
425{
426 struct history *history;
427 char *title;
428 int sx, sy;
429
430 assert(bw != NULL);
431
432 history = bw->history;
433
434 if ((history == NULL) || (history->current == NULL)) {
435 return NSERROR_INVALID;
436 }
437
438 assert(history->current->page.url);
439 assert(history->current->page.title);
440
441 title = strdup(content_get_title(content));
442 if (title == NULL) {
443 return NSERROR_NOMEM;
444 }
445 NSLOG(netsurf, INFO, "Updating history entry for %s", title);
446 free(history->current->page.title);
447 history->current->page.title = title;
448
449 if (history->current->page.bitmap != NULL) {
451 }
452
453 if ((bw->window != NULL) &&
454 guit->window->get_scroll(bw->window, &sx, &sy)) {
455 int content_height = content_get_height(content);
456 int content_width = content_get_width(content);
457 /* clamp width and height values */
458 if (content_height < 1) {
459 content_height = 1;
460 }
461 if (content_width < 1) {
462 content_width = 1;
463 }
464 /* Successfully got scroll offsets, update the entry */
466 (float)sx / (float)content_width;
468 (float)sy / (float)content_height;
469 NSLOG(netsurf, INFO, "Updated scroll offsets to %g by %g",
472 }
473 return NSERROR_OK;
474}
475
476/* exported interface documented in desktop/browser_private.h */
479 float *sx, float *sy)
480{
481 struct history *history;
482
483 assert(bw != NULL);
484
485 history = bw->history;
486
487 if ((history== NULL) || (history->current == NULL)) {
488 return NSERROR_INVALID;
489 }
490
493
494 return NSERROR_OK;
495}
496
497/* exported interface documented in desktop/browser_history.h */
499{
500 assert(bw != NULL);
501
502 if (bw->history == NULL)
503 return;
504
506 free(bw->history);
507
508 bw->history = NULL;
509}
510
511
512
513/* exported interface documented in desktop/browser_history.h */
515{
516 if (bw != NULL && bw->internal_nav) {
517 /* All internal nav back operations ignore new_window */
518 if (bw->current_parameters.url != NULL) {
519 /* There are some internal parameters, restart from there */
521 } else {
522 /* No internal parameters, just navigate to about:blank */
524 bw,
525 corestring_nsurl_about_blank,
526 NULL, /* Referer */
528 NULL, /* Post */
529 NULL, /* Post */
530 NULL /* parent fetch */);
531 }
532 }
533
534 if (!bw || !bw->history || !bw->history->current ||
535 !bw->history->current->back) {
537 }
539 new_window);
540}
541
542
543
544/* exported interface documented in desktop/browser_history.h */
546 bool new_window)
547{
548 if (!bw || !bw->history || !bw->history->current ||
551 }
553 new_window);
554}
555
556
557/* exported interface documented in desktop/browser_history.h */
559{
560 return (bw && bw->history && bw->history->current &&
561 bw->history->current->back);
562}
563
564
565/* exported interface documented in desktop/browser_history.h */
567{
568 return (bw && bw->history && bw->history->current &&
570}
571
572/* exported interface documented in desktop/browser_history.h */
575 struct bitmap **bitmap_out)
576{
577 struct bitmap *bitmap;
578
579 if (!bw || !bw->history || !bw->history->current) {
580 return NSERROR_INVALID;
581 }
582
583 if (bw->history->current->page.bitmap == NULL) {
585 } else {
587 }
588
589 *bitmap_out = bitmap;
590
591 return NSERROR_OK;
592}
593
594/* exported interface documented in desktop/browser_history.h */
596 struct history_entry *entry, bool new_window)
597{
598 struct history *history;
599 nsurl *url;
600 struct history_entry *current;
601 nserror error;
602
603 assert(bw != NULL);
604 history = bw->history;
605
606 if (entry->page.frag_id) {
607 error = nsurl_refragment(entry->page.url,
608 entry->page.frag_id, &url);
609
610 if (error != NSERROR_OK) {
611 return error;
612 }
613 } else {
614 url = nsurl_ref(entry->page.url);
615 }
616
617 if (new_window) {
618 current = history->current;
619 history->current = entry;
620
622 url, NULL, bw, NULL);
623 history->current = current;
624 } else {
625 if (bw->current_content != NULL) {
627 }
628 history->current = entry;
629 error = browser_window_navigate(bw, url, NULL,
631 NULL, NULL, NULL);
632 }
633
634 nsurl_unref(url);
635
636 return error;
637}
638
639
640/* exported interface documented in desktop/browser_history.h */
642 browser_window_history_enumerate_cb cb, void *user_data)
643{
644 struct history_entry *e;
645
646 if (bw == NULL || bw->history == NULL || bw->history->current == NULL)
647 return;
648
649 e = bw->history->current->forward_pref;
650 for (; e != NULL; e = e->forward_pref) {
651 if (!cb(bw, e->x, e->y, e->x + LOCAL_HISTORY_WIDTH,
653 e, user_data))
654 break;
655 }
656}
657
658
659/* exported interface documented in desktop/browser_history.h */
661 browser_window_history_enumerate_cb cb, void *user_data)
662{
663 struct history_entry *e;
664
665 if (bw == NULL || bw->history == NULL || bw->history->current == NULL)
666 return;
667
668 for (e = bw->history->current->back; e != NULL; e = e->back) {
669 if (!cb(bw, e->x, e->y, e->x + LOCAL_HISTORY_WIDTH,
671 e, user_data))
672 break;
673 }
674}
675
676
677/* exported interface documented in desktop/browser_history.h */
679 browser_window_history_enumerate_cb cb, void *user_data)
680{
681 if (bw == NULL || bw->history == NULL)
682 return;
684 bw->history->start, cb, user_data);
685}
686
687
688/* exported interface documented in desktop/browser_history.h */
690{
691 return nsurl_ref(entry->page.url);
692}
693
694
695/* exported interface documented in desktop/browser_history.h */
697 const struct history_entry *entry)
698{
699 return (entry->page.frag_id) ? lwc_string_data(entry->page.frag_id) : 0;
700}
701
702
703/* exported interface documented in desktop/browser_history.h */
705 const struct history_entry *entry)
706{
707 return entry->page.title;
708}
nserror browser_window_history_add(struct browser_window *bw, struct hlcache_handle *content, lwc_string *frag_id)
Insert a url into the history tree.
static void browser_window_history__layout(struct history *history)
Compute node positions.
void browser_window_history_enumerate_back(const struct browser_window *bw, browser_window_history_enumerate_cb cb, void *user_data)
Enumerate all entries that will be reached by the 'back' button.
nserror browser_window_history_update(struct browser_window *bw, struct hlcache_handle *content)
Update the thumbnail and scroll offsets for the current entry.
nserror browser_window_history_get_thumbnail(struct browser_window *bw, struct bitmap **bitmap_out)
Get the thumbnail bitmap for the current history entry.
static struct history_entry * browser_window_history__clone_entry(struct history *history, struct history_entry *entry)
Clone a history entry.
nserror browser_window_history_forward(struct browser_window *bw, bool new_window)
Go forward in the history.
nserror browser_window_history_create(struct browser_window *bw)
Create a new history tree for a browser window window.
nsurl * browser_window_history_entry_get_url(const struct history_entry *entry)
Returns the URL to a history entry.
nserror browser_window_history_get_scroll(struct browser_window *bw, float *sx, float *sy)
Retrieve the stored scroll offsets for the current history entry.
nserror browser_window_history_go(struct browser_window *bw, struct history_entry *entry, bool new_window)
Navigate to specified history entry, optionally in new window.
static bool browser_window_history__enumerate_entry(const struct browser_window *bw, const struct history_entry *entry, browser_window_history_enumerate_cb cb, void *ud)
Enumerate subentries in history See also history_enumerate()
static int browser_window_history__layout_subtree(struct history *history, struct history_entry *entry, int x, int y)
Recursively position a subtree.
void browser_window_history_enumerate_forward(const struct browser_window *bw, browser_window_history_enumerate_cb cb, void *user_data)
Enumerate all entries that will be reached by the 'forward' button.
static void browser_window_history__free_entry(struct history_entry *entry)
Free an entry in the tree recursively.
const char * browser_window_history_entry_get_title(const struct history_entry *entry)
Returns the title of a history entry.
nserror browser_window_history_clone(const struct browser_window *existing, struct browser_window *clone)
Clone a bw's history tree for new bw.
void browser_window_history_enumerate(const struct browser_window *bw, browser_window_history_enumerate_cb cb, void *user_data)
Enumerate all entries in the history.
bool browser_window_history_forward_available(struct browser_window *bw)
Check whether it is pssible to go forwards in the history.
const char * browser_window_history_entry_get_fragment_id(const struct history_entry *entry)
Returns the URL to a history entry.
bool browser_window_history_back_available(struct browser_window *bw)
Check whether it is pssible to go back in the history.
nserror browser_window_history_back(struct browser_window *bw, bool new_window)
Go back in the history.
void browser_window_history_destroy(struct browser_window *bw)
Free a history structure.
Interface to browser history operations.
bool(* browser_window_history_enumerate_cb)(const struct browser_window *bw, int x0, int y0, int x1, int y1, const struct history_entry *entry, void *user_data)
Callback function type for history enumeration.
Browser window private structure.
nserror browser_window__reload_current_parameters(struct browser_window *bw)
Navigate a browser window to the current parameters.
Browser window creation and manipulation interface.
nserror browser_window_navigate(struct browser_window *bw, struct nsurl *url, struct nsurl *referrer, enum browser_window_nav_flags flags, char *post_urlenc, struct fetch_multipart_data *post_multipart, struct hlcache_handle *parent)
Start fetching a page in a browser window.
nserror browser_window_create(enum browser_window_create_flags flags, struct nsurl *url, struct nsurl *referrer, struct browser_window *existing, struct browser_window **bw)
Create and open a new root browser window with the given page.
@ BW_CREATE_CLONE
New gui_window to be clone of "existing" gui_window.
@ BW_NAVIGATE_HISTORY
this will form a new history node (don't set for back/reload/etc)
@ BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE
suppress initial history updates (used by back/fwd/etc)
Useful interned string pointers (interface).
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_BAD_PARAMETER
Bad Parameter.
Definition: errors.h:48
@ NSERROR_INVALID
Invalid data.
Definition: errors.h:49
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_OK
No error.
Definition: errors.h:30
struct netsurf_table * guit
The global interface table.
Definition: gui_factory.c:50
Interface to core interface table.
High-level resource cache interface.
Generic bitmap handling interface.
@ BITMAP_CLEAR
memory should be wiped to 0
Definition: bitmap.h:39
@ BITMAP_OPAQUE
image is opaque
Definition: bitmap.h:38
Public content interface.
struct nsurl * hlcache_handle_get_url(const struct hlcache_handle *handle)
Retrieve the URL associated with a high level cache handle.
const char * content_get_title(struct hlcache_handle *h)
Retrieve title associated with content.
Definition: content.c:1098
int content_get_height(struct hlcache_handle *h)
Retrieve height of content.
Definition: content.c:1167
struct bitmap * content_get_bitmap(struct hlcache_handle *h)
Retrieve the bitmap contained in an image content.
Definition: content.c:1256
int content_get_width(struct hlcache_handle *h)
Retrieve width of content.
Definition: content.c:1150
Interface to platform-specific layout operation table.
Interface to platform-specific graphical user interface window operations.
Interface to browser history private operations.
#define LOCAL_HISTORY_RIGHT_MARGIN
#define LOCAL_HISTORY_WIDTH
#define LOCAL_HISTORY_BOTTOM_MARGIN
#define LOCAL_HISTORY_HEIGHT
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
void nsurl_unref(nsurl *url)
Drop a reference to a NetSurf URL object.
nserror nsurl_refragment(const nsurl *url, lwc_string *frag, nsurl **new_url)
Create a NetSurf URL object, adding a fragment to an existing URL object.
const char * nsurl_access(const nsurl *url)
Access a NetSurf URL object as a string.
nsurl * nsurl_ref(nsurl *url)
Increment the reference count to a NetSurf URL object.
struct nsurl nsurl
NetSurf URL object.
Definition: nsurl.h:31
Interface to utility string handling.
RISC OS wimp toolkit bitmap.
Definition: bitmap.c:68
struct nsurl * url
The URL to fetch.
Browser window data.
struct gui_window * window
Platform specific window data only valid at top level.
struct history * history
local history handle.
struct hlcache_handle * current_content
Content handle of page currently displayed which must have READY or DONE status or NULL for no conten...
bool internal_nav
Internal navigation, do not update URL etc.
struct browser_fetch_parameters current_parameters
The fetch parameters for the current content.
Content which corresponds to a single URL.
int(* get_height)(void *bitmap)
Get the bitmap height.
Definition: bitmap.h:193
void(* destroy)(void *bitmap)
Destroy a bitmap.
Definition: bitmap.h:143
void *(* create)(int width, int height, enum gui_bitmap_flags flags)
Create a new bitmap.
Definition: bitmap.h:136
nserror(* render)(struct bitmap *bitmap, struct hlcache_handle *content)
Render content into a bitmap.
Definition: bitmap.h:208
size_t(* get_rowstride)(void *bitmap)
Get the number of bytes per row of the image.
Definition: bitmap.h:177
unsigned char *(* get_buffer)(void *bitmap)
Get the image buffer from a bitmap.
Definition: bitmap.h:169
bool(* get_scroll)(struct gui_window *gw, int *sx, int *sy)
Get the scroll position of a browser window.
Definition: window.h:205
A node in the history tree.
int x
Position of node.
struct history_entry * forward_last
Last child.
struct history_entry * back
Parent.
unsigned int children
Number of children.
struct history_entry * forward
First child.
struct history_entry * next
Next sibling.
struct history_page page
struct history_entry * forward_pref
Child in direction of current entry.
int y
Position of node.
float scroll_y
Scroll Y offset when visited.
lwc_string * frag_id
float scroll_x
Scroll X offset when visited.
struct bitmap * bitmap
Thumbnail bitmap, or NULL.
char * title
Fragment identifier, or NULL.
struct nsurl * url
Page URL, never NULL.
History tree for a window.
int width
Width of layout.
int height
Height of layout.
struct history_entry * current
Current position in tree.
struct history_entry * start
First page in tree (page that window opened with).
High-level cache handle.
Definition: hlcache.c:66
struct gui_window_table * window
Window table.
Definition: gui_table.h:66
struct gui_bitmap_table * bitmap
Bitmap table.
Definition: gui_table.h:153
Interface to time operations.
Unified URL information database internal interface.
Interface to a number of general purpose functionality.
static nserror bitmap(const struct redraw_context *ctx, struct bitmap *bitmap, int x, int y, int width, int height, colour bg, bitmap_flags_t flags)
Plot a bitmap.
Definition: plot.c:857