Bug 620: Reset form fields to default values on reload
[elinks.git] / src / document / document.c
bloba6d55e194c8321155f0e594871aa969222bc9490
1 /** The document base functionality
2 * @file */
4 #ifdef HAVE_CONFIG_H
5 #include "config.h"
6 #endif
8 #include <errno.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
13 #include "elinks.h"
15 #include "cache/cache.h"
16 #include "config/options.h"
17 #include "document/document.h"
18 #include "document/forms.h"
19 #include "document/html/frames.h"
20 #include "document/html/parser.h"
21 #include "document/html/parser/parse.h"
22 #include "document/html/renderer.h"
23 #include "document/options.h"
24 #include "document/refresh.h"
25 #include "main/module.h"
26 #include "main/object.h"
27 #include "protocol/uri.h"
28 #include "terminal/draw.h"
29 #include "util/color.h"
30 #include "util/error.h"
31 #include "util/lists.h"
32 #include "util/memory.h"
33 #include "util/string.h"
34 #include "viewer/text/link.h"
37 static INIT_LIST_OF(struct document, format_cache);
39 struct document *
40 init_document(struct cache_entry *cached, struct document_options *options)
42 struct document *document = mem_calloc(1, sizeof(*document));
44 if (!document) return NULL;
46 document->uri = get_uri_reference(cached->uri);
48 object_lock(cached);
49 document->id = cached->id;
50 document->cached = cached;
52 init_list(document->forms);
53 init_list(document->tags);
54 init_list(document->nodes);
56 #ifdef CONFIG_ECMASCRIPT
57 init_list(document->onload_snippets);
58 #endif
60 object_nolock(document, "document");
61 object_lock(document);
63 copy_opt(&document->options, options);
65 add_to_list(format_cache, document);
67 return document;
70 static void
71 free_frameset_desc(struct frameset_desc *frameset_desc)
73 int i;
75 for (i = 0; i < frameset_desc->n; i++) {
76 struct frame_desc *frame_desc = &frameset_desc->frame_desc[i];
78 if (frame_desc->subframe)
79 free_frameset_desc(frame_desc->subframe);
80 mem_free_if(frame_desc->name);
81 if (frame_desc->uri)
82 done_uri(frame_desc->uri);
85 mem_free(frameset_desc);
88 void
89 done_link_members(struct link *link)
91 if (link->event_hooks) {
92 struct script_event_hook *evhook, *safety;
94 foreachsafe (evhook, safety, *link->event_hooks) {
95 mem_free_if(evhook->src);
96 mem_free(evhook);
98 mem_free(link->event_hooks);
100 mem_free_if(get_link_name(link));
101 mem_free_if(link->where);
102 mem_free_if(link->target);
103 mem_free_if(link->title);
104 mem_free_if(link->where_img);
105 mem_free_if(link->points);
108 void
109 done_document(struct document *document)
111 assert(document);
112 if_assert_failed return;
114 assertm(!is_object_used(document), "Attempt to free locked formatted data.");
115 if_assert_failed return;
117 assert(document->cached);
118 object_unlock(document->cached);
120 if (document->uri) done_uri(document->uri);
121 mem_free_if(document->title);
122 if (document->frame_desc) free_frameset_desc(document->frame_desc);
123 if (document->refresh) done_document_refresh(document->refresh);
125 if (document->links) {
126 int pos;
128 for (pos = 0; pos < document->nlinks; pos++)
129 done_link_members(&document->links[pos]);
131 mem_free(document->links);
134 if (document->data) {
135 int pos;
137 for (pos = 0; pos < document->height; pos++)
138 mem_free_if(document->data[pos].chars);
140 mem_free(document->data);
143 mem_free_if(document->lines1);
144 mem_free_if(document->lines2);
145 done_document_options(&document->options);
147 while (!list_empty(document->forms)) {
148 done_form(document->forms.next);
151 #ifdef CONFIG_CSS
152 free_uri_list(&document->css_imports);
153 #endif
154 #ifdef CONFIG_ECMASCRIPT
155 free_string_list(&document->onload_snippets);
156 free_uri_list(&document->ecmascript_imports);
157 kill_timer(&document->timeout);
158 #endif
160 free_list(document->tags);
161 free_list(document->nodes);
163 mem_free_if(document->search);
164 mem_free_if(document->slines1);
165 mem_free_if(document->slines2);
167 del_from_list(document);
168 mem_free(document);
171 void
172 release_document(struct document *document)
174 assert(document);
175 if_assert_failed return;
177 if (document->refresh) kill_document_refresh(document->refresh);
178 #ifdef CONFIG_ECMASCRIPT
179 kill_timer(&document->timeout);
180 #endif
181 object_unlock(document);
182 move_to_top_of_list(format_cache, document);
186 find_tag(struct document *document, unsigned char *name, int namelen)
188 struct tag *tag;
190 foreach (tag, document->tags)
191 if (!strlcasecmp(tag->name, -1, name, namelen))
192 return tag->y;
194 return -1;
197 /* Formatted document cache management */
199 /* ECMAScript doesn't like anything like CSS since it doesn't modify the
200 * formatted document (yet). */
202 #if CONFIG_CSS
203 unsigned long
204 get_document_css_magic(struct document *document)
206 unsigned long css_magic = 0;
207 struct uri *uri;
208 int index;
210 foreach_uri (uri, index, &document->css_imports) {
211 struct cache_entry *cached = find_in_cache(uri);
213 if (cached) css_magic += cached->id + cached->data_size;
216 return css_magic;
219 #define check_document_css_magic(document) \
220 ((document)->css_magic == get_document_css_magic(document))
221 #else
222 #define check_document_css_magic(document) 1
223 #endif
225 void
226 update_cached_document_options(void)
228 struct document *document;
229 struct active_link_options active_link;
231 memset(&active_link, 0, sizeof(active_link)); /* Safer. */
232 active_link.fg = get_opt_color("document.browse.links.active_link.colors.text");
233 active_link.bg = get_opt_color("document.browse.links.active_link.colors.background");
234 active_link.color = get_opt_bool("document.browse.links.active_link.enable_color");
235 active_link.invert = get_opt_bool("document.browse.links.active_link.invert");
236 active_link.underline = get_opt_bool("document.browse.links.active_link.underline");
237 active_link.bold = get_opt_bool("document.browse.links.active_link.bold");
239 foreach (document, format_cache) {
240 copy_struct(&document->options.active_link, &active_link);
244 struct document *
245 get_cached_document(struct cache_entry *cached, struct document_options *options)
247 struct document *document, *next;
249 foreachsafe (document, next, format_cache) {
250 if (!compare_uri(document->uri, cached->uri, 0)
251 || compare_opt(&document->options, options))
252 continue;
254 if (options->no_cache
255 || cached->id != document->id
256 || !check_document_css_magic(document)) {
257 if (!is_object_used(document)) {
258 done_document(document);
260 continue;
263 /* Reactivate */
264 move_to_top_of_list(format_cache, document);
266 object_lock(document);
268 return document;
271 return NULL;
274 void
275 shrink_format_cache(int whole)
277 struct document *document, *next;
278 int format_cache_size = get_opt_int("document.cache.format.size");
279 int format_cache_entries = 0;
281 foreachsafe (document, next, format_cache) {
282 if (is_object_used(document)) continue;
284 format_cache_entries++;
286 /* Destroy obsolete renderer documents which are already
287 * out-of-sync. */
288 if (document->cached->id == document->id)
289 continue;
291 done_document(document);
292 format_cache_entries--;
295 assertm(format_cache_entries >= 0, "format_cache_entries underflow on entry");
296 if_assert_failed format_cache_entries = 0;
298 foreachbacksafe (document, next, format_cache) {
299 if (is_object_used(document)) continue;
301 /* If we are not purging the whole format cache, stop
302 * once we are below the maximum number of entries. */
303 if (!whole && format_cache_entries <= format_cache_size)
304 break;
306 done_document(document);
307 format_cache_entries--;
310 assertm(format_cache_entries >= 0, "format_cache_entries underflow");
311 if_assert_failed format_cache_entries = 0;
315 get_format_cache_size(void)
317 return list_size(&format_cache);
321 get_format_cache_used_count(void)
323 struct document *document;
324 int i = 0;
326 foreach (document, format_cache)
327 i += is_object_used(document);
328 return i;
332 get_format_cache_refresh_count(void)
334 struct document *document;
335 int i = 0;
337 foreach (document, format_cache)
338 if (document->refresh
339 && document->refresh->timer != TIMER_ID_UNDEF)
340 i++;
341 return i;
344 static void
345 init_documents(struct module *module)
347 init_tags_lookup();
350 static void
351 done_documents(struct module *module)
353 free_tags_lookup();
354 free_table_cache();
357 struct module document_module = struct_module(
358 /* Because this module is listed in main_modules rather than
359 * in builtin_modules, its name does not appear in the user
360 * interface and so need not be translatable. */
361 /* name: */ "Document",
362 /* options: */ NULL,
363 /* hooks: */ NULL,
364 /* submodules: */ NULL,
365 /* data: */ NULL,
366 /* init: */ init_documents,
367 /* done: */ done_documents