summaryrefslogtreecommitdiffstats
path: root/khtml/misc
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitce4a32fe52ef09d8f5ff1dd22c001110902b60a2 (patch)
tree5ac38a06f3dde268dc7927dc155896926aaf7012 /khtml/misc
downloadtdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.tar.gz
tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'khtml/misc')
-rw-r--r--khtml/misc/Makefile.am43
-rw-r--r--khtml/misc/arena.cpp333
-rw-r--r--khtml/misc/arena.h123
-rw-r--r--khtml/misc/blocked_icon.cpp41
-rw-r--r--khtml/misc/blocked_icon.pngbin0 -> 599 bytes
-rw-r--r--khtml/misc/decoder.cpp790
-rw-r--r--khtml/misc/decoder.h115
-rw-r--r--khtml/misc/guess_ja.cpp379
-rw-r--r--khtml/misc/guess_ja.h122
-rw-r--r--khtml/misc/helper.cpp144
-rw-r--r--khtml/misc/helper.h55
-rw-r--r--khtml/misc/htmlattrs.c1019
-rw-r--r--khtml/misc/htmlattrs.h168
-rw-r--r--khtml/misc/htmlattrs.in157
-rw-r--r--khtml/misc/htmlhashes.cpp45
-rw-r--r--khtml/misc/htmlhashes.h14
-rw-r--r--khtml/misc/htmltags.c687
-rw-r--r--khtml/misc/htmltags.h119
-rw-r--r--khtml/misc/htmltags.in102
-rw-r--r--khtml/misc/khtmllayout.h112
-rw-r--r--khtml/misc/loader.cpp1679
-rw-r--r--khtml/misc/loader.h522
-rw-r--r--khtml/misc/loader_client.h35
-rw-r--r--khtml/misc/loader_jpeg.cpp548
-rw-r--r--khtml/misc/loader_jpeg.h50
-rw-r--r--khtml/misc/makeattrs113
-rw-r--r--khtml/misc/maketags124
-rw-r--r--khtml/misc/multimap.h345
-rw-r--r--khtml/misc/seed.h46
-rw-r--r--khtml/misc/shared.h228
-rw-r--r--khtml/misc/stringit.cpp138
-rw-r--r--khtml/misc/stringit.h203
32 files changed, 8599 insertions, 0 deletions
diff --git a/khtml/misc/Makefile.am b/khtml/misc/Makefile.am
new file mode 100644
index 000000000..b874f9039
--- /dev/null
+++ b/khtml/misc/Makefile.am
@@ -0,0 +1,43 @@
+# This file is part of the KDE libraries
+# Copyright (C) 1997 Martin Jones (mjones@kde.org)
+# (C) 1997 Torben Weis (weis@kde.org)
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with this library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+KDE_CXXFLAGS = $(WOVERLOADED_VIRTUAL)
+
+noinst_LTLIBRARIES = libkhtmlmisc.la
+libkhtmlmisc_la_SOURCES = \
+ decoder.cpp loader.cpp loader_jpeg.cpp guess_ja.cpp\
+ htmlhashes.cpp helper.cpp arena.cpp stringit.cpp
+libkhtmlmisc_la_LIBADD = $(LIBJPEG)
+libkhtmlmisc_la_LDFLAGS = $(USER_LDFLAGS)
+libkhtmlmisc_la_METASOURCES = AUTO
+
+noinst_HEADERS = \
+ decoder.h khtmllayout.h loader_jpeg.h loader.h guess_ja.h\
+ stringit.h htmlhashes.h helper.h shared.h arena.h
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/dcop -I$(top_srcdir)/kio -I$(top_srcdir)/libltdl \
+ -I$(top_srcdir)/khtml -I$(top_srcdir)/kutils $(all_includes)
+
+SRCDOC_DEST=$(kde_htmldir)/en/kdelibs/khtml
+
+## generate lib documentation
+srcdoc:
+ $(mkinstalldirs) $(SRCDOC_DEST)
+ kdoc -H -d $(SRCDOC_DEST) kdecore -lqt
+
diff --git a/khtml/misc/arena.cpp b/khtml/misc/arena.cpp
new file mode 100644
index 000000000..5efcaf98d
--- /dev/null
+++ b/khtml/misc/arena.cpp
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 1998-2000 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ * Nick Blievers <nickb@adacel.com.au>
+ * Jeff Hostetler <jeff@nerdone.com>
+ * Tom Rini <trini@kernel.crashing.org>
+ * Raffaele Sena <raff@netwinder.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+/*
+ * Lifetime-based fast allocation, inspired by much prior art, including
+ * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
+ * David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <kglobal.h>
+#include "arena.h"
+
+#ifdef HAVE_GETPAGESIZE
+#include <unistd.h>
+#define POOL_SIZE kMax(8192u, 2*( unsigned ) getpagesize())
+#else
+#define POOL_SIZE 8192
+#endif
+
+//#define DEBUG_ARENA_MALLOC
+#ifdef DEBUG_ARENA_MALLOC
+#include <assert.h>
+#include <stdio.h>
+#endif
+
+namespace khtml {
+
+#ifdef DEBUG_ARENA_MALLOC
+static int i = 0;
+#endif
+
+#define FREELIST_MAX 50
+#define LARGE_ALLOCATION_CEIL(pool) (pool)->arenasize * 256
+#define MAX_DISCRETE_ALLOCATION(pool) (pool)->arenasize * 32
+static Arena *arena_freelist = 0;
+static int freelist_count = 0;
+
+#define ARENA_DEFAULT_ALIGN sizeof(double)
+#define BIT(n) ((unsigned int)1 << (n))
+#define BITMASK(n) (BIT(n) - 1)
+#define CEILING_LOG2(_log2,_n) \
+ unsigned int j_ = (unsigned int)(_n); \
+ (_log2) = 0; \
+ if ((j_) & ((j_)-1)) \
+ (_log2) += 1; \
+ if ((j_) >> 16) \
+ (_log2) += 16, (j_) >>= 16; \
+ if ((j_) >> 8) \
+ (_log2) += 8, (j_) >>= 8; \
+ if ((j_) >> 4) \
+ (_log2) += 4, (j_) >>= 4; \
+ if ((j_) >> 2) \
+ (_log2) += 2, (j_) >>= 2; \
+ if ((j_) >> 1) \
+ (_log2) += 1;
+
+int CeilingLog2(unsigned int i) {
+ int log2;
+ CEILING_LOG2(log2,i);
+ return log2;
+}
+
+void InitArenaPool(ArenaPool *pool, const char* /*name*/,
+ unsigned int /*size*/, unsigned int align)
+{
+ unsigned int size = POOL_SIZE;
+ if (align == 0)
+ align = ARENA_DEFAULT_ALIGN;
+ pool->mask = BITMASK(CeilingLog2(align));
+ pool->first.next = NULL;
+ pool->first.base = pool->first.avail = pool->first.limit =
+ (uword)ARENA_ALIGN(pool, &pool->first + 1);
+ pool->current = &pool->first;
+ pool->arenasize = size;
+ pool->largealloc = LARGE_ALLOCATION_CEIL(pool);
+ pool->cumul = 0;
+}
+
+
+/*
+ ** ArenaAllocate() -- allocate space from an arena pool
+ **
+ ** Description: ArenaAllocate() allocates space from an arena
+ ** pool.
+ **
+ ** First try to satisfy the request from arenas starting at
+ ** pool->current.
+ **
+ ** If there is not enough space in the arena pool->current, try
+ ** to claim an arena, on a first fit basis, from the global
+ ** freelist (arena_freelist).
+ **
+ ** If no arena in arena_freelist is suitable, then try to
+ ** allocate a new arena from the heap.
+ **
+ ** Returns: pointer to allocated space or NULL
+ **
+ */
+void* ArenaAllocate(ArenaPool *pool, unsigned int nb)
+{
+ Arena *a;
+ char *rp; /* returned pointer */
+
+#ifdef DEBUG_ARENA_MALLOC
+ assert((nb & pool->mask) == 0);
+#endif
+
+ nb = (uword)ARENA_ALIGN(pool, nb); /* force alignment */
+
+ /* attempt to allocate from arenas at pool->current */
+ {
+ a = pool->current;
+ do {
+ if ( a->avail +nb <= a->limit ) {
+ pool->current = a;
+ rp = (char *)a->avail;
+ a->avail += nb;
+ VALGRIND_MEMPOOL_ALLOC(a->base, rp, nb);
+ return rp;
+ }
+ } while( NULL != (a = a->next) );
+ }
+
+ /* attempt to allocate from arena_freelist */
+ {
+ Arena *p; /* previous pointer, for unlinking from freelist */
+
+ for ( a = p = arena_freelist; a != NULL ; p = a, a = a->next ) {
+ if ( a->base +nb <= a->limit ) {
+ if ( p == arena_freelist )
+ arena_freelist = a->next;
+ else
+ p->next = a->next;
+ a->avail = a->base;
+ rp = (char *)a->avail;
+ a->avail += nb;
+ VALGRIND_MEMPOOL_ALLOC(a->base, rp, nb);
+ /* the newly allocated arena is linked after pool->current
+ * and becomes pool->current */
+ a->next = pool->current->next;
+ pool->current->next = a;
+ pool->current = a;
+ if ( 0 == pool->first.next )
+ pool->first.next = a;
+ freelist_count--;
+ return(rp);
+ }
+ }
+ }
+
+ /* attempt to allocate from the heap */
+ {
+ unsigned int sz;
+#ifdef HAVE_MMAP
+ if (pool->cumul > pool->largealloc) {
+ // High memory pressure. Switch to a fractional allocation strategy
+ // so that malloc gets a chance to successfully trim us down when it's over.
+ sz = kMin(pool->cumul/25, MAX_DISCRETE_ALLOCATION(pool));
+ } else
+#endif
+ sz = pool->arenasize > nb ? pool->arenasize : nb;
+ sz += sizeof *a + pool->mask; /* header and alignment slop */
+ pool->cumul += sz;
+#ifdef DEBUG_ARENA_MALLOC
+ i++;
+ printf("Malloc: %d\n", i);
+#endif
+ a = (Arena*)malloc(sz);
+ if (a) {
+ a->limit = (uword)a + sz;
+ a->base = a->avail = (uword)ARENA_ALIGN(pool, a + 1);
+ VALGRIND_CREATE_MEMPOOL(a->base, 0, 0);
+ rp = (char *)a->avail;
+ a->avail += nb;
+ VALGRIND_MEMPOOL_ALLOC(a->base, rp, nb);
+
+ /* the newly allocated arena is linked after pool->current
+ * and becomes pool->current */
+ a->next = pool->current->next;
+ pool->current->next = a;
+ pool->current = a;
+ if ( !pool->first.next )
+ pool->first.next = a;
+ return(rp);
+ }
+ }
+
+ /* we got to here, and there's no memory to allocate */
+ return(0);
+} /* --- end ArenaAllocate() --- */
+
+/*
+ * Free tail arenas linked after head, which may not be the true list head.
+ * Reset pool->current to point to head in case it pointed at a tail arena.
+ */
+static void FreeArenaList(ArenaPool *pool, Arena *head, bool reallyFree)
+{
+ Arena **ap, *a;
+
+ ap = &head->next;
+ a = *ap;
+ if (!a)
+ return;
+
+#ifdef DEBUG_ARENA_MALLOC
+ do {
+ assert(a->base <= a->avail && a->avail <= a->limit);
+ a->avail = a->base;
+ CLEAR_UNUSED(a);
+ } while ((a = a->next) != 0);
+ a = *ap;
+#endif
+
+ if (freelist_count >= FREELIST_MAX)
+ reallyFree = true;
+
+ if (reallyFree) {
+ do {
+ *ap = a->next;
+ VALGRIND_DESTROY_MEMPOOL(a->base);
+ CLEAR_ARENA(a);
+#ifdef DEBUG_ARENA_MALLOC
+ if (a) {
+ i--;
+ printf("Free: %d\n", i);
+ }
+#endif
+ free(a); a = 0;
+ } while ((a = *ap) != 0);
+ } else {
+ /* Insert as much of the arena chain as we can hold at the front of the freelist. */
+ do {
+ ap = &(*ap)->next;
+ freelist_count++;
+ } while (*ap && freelist_count < FREELIST_MAX);
+
+ /* Get rid of excess */
+ if (*ap) {
+ Arena *xa, *n;
+ for (xa = *ap; xa; xa = n) {
+ VALGRIND_DESTROY_MEMPOOL(xa->base);
+ n = xa->next;
+#ifdef DEBUG_ARENA_MALLOC
+ i--;
+ printf("Free: %d\n", i);
+#endif
+ CLEAR_ARENA(xa);
+ free(xa);
+ }
+ }
+ *ap = arena_freelist;
+ arena_freelist = a;
+ head->next = 0;
+ }
+ pool->current = head;
+}
+
+void ArenaRelease(ArenaPool *pool, char *mark)
+{
+ Arena *a;
+
+ for (a = pool->first.next; a; a = a->next) {
+ if (UPTRDIFF(mark, a->base) < UPTRDIFF(a->avail, a->base)) {
+ a->avail = (uword)ARENA_ALIGN(pool, mark);
+ FreeArenaList(pool, a, false);
+ return;
+ }
+ }
+}
+
+void FreeArenaPool(ArenaPool *pool)
+{
+ FreeArenaList(pool, &pool->first, false);
+}
+
+void FinishArenaPool(ArenaPool *pool)
+{
+ FreeArenaList(pool, &pool->first, true);
+}
+
+void ArenaFinish()
+{
+ Arena *a, *next;
+#ifdef DEBUG_ARENA_MALLOC
+ printf("releasing global Arena freelist\n");
+#endif
+ for (a = arena_freelist; a; a = next) {
+ next = a->next;
+ free(a); a = 0;
+ }
+ freelist_count = 0;
+ arena_freelist = NULL;
+}
+
+} // namespace
diff --git a/khtml/misc/arena.h b/khtml/misc/arena.h
new file mode 100644
index 000000000..6415b00bb
--- /dev/null
+++ b/khtml/misc/arena.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 1998-2000 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ * Nick Blievers <nickb@adacel.com.au>
+ * Jeff Hostetler <jeff@nerdone.com>
+ * Tom Rini <trini@kernel.crashing.org>
+ * Raffaele Sena <raff@netwinder.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#ifndef ARENA_H
+#define ARENA_H
+
+
+#if defined(HAVE_VALGRIND_MEMCHECK_H) && !defined(NDEBUG)
+
+#include <valgrind/memcheck.h>
+#define VALGRIND_SUPPORT
+
+#else
+
+#define VALGRIND_CREATE_MEMPOOL(base, redZone, zeroed)
+#define VALGRIND_DESTROY_MEMPOOL(base)
+#define VALGRIND_MEMPOOL_ALLOC(base, addr, size)
+#define VALGRIND_MEMPOOL_FREE(base, addr)
+
+#endif
+
+
+#define ARENA_ALIGN_MASK 3
+
+typedef unsigned long uword;
+
+namespace khtml {
+
+struct Arena {
+ Arena* next; // next arena
+ uword base; // aligned base address
+ uword limit; // end of arena (1+last byte)
+ uword avail; // points to next available byte in arena
+};
+
+struct ArenaPool {
+ Arena first; // first arena in pool list.
+ Arena* current; // current arena.
+ unsigned int arenasize;
+ unsigned int largealloc; // threshold for fractional allocation strategy
+ unsigned int cumul; // total bytes in pool.
+ uword mask; // Mask (power-of-2 - 1)
+};
+
+void InitArenaPool(ArenaPool *pool, const char *name,
+ unsigned int size, unsigned int align);
+void FinishArenaPool(ArenaPool *pool);
+void FreeArenaPool(ArenaPool *pool);
+void* ArenaAllocate(ArenaPool *pool, unsigned int nb);
+void ArenaFinish(void);
+
+#define ARENA_ALIGN(pool, n) (((uword)(n) + ARENA_ALIGN_MASK) & ~ARENA_ALIGN_MASK)
+#define INIT_ARENA_POOL(pool, name, size) \
+ InitArenaPool(pool, name, size, ARENA_ALIGN_MASK + 1)
+
+#define ARENA_ALLOCATE(p, pool, nb) \
+ Arena *_a = (pool)->current; \
+ unsigned int _nb = ARENA_ALIGN(pool, nb); \
+ uword _p = _a->avail; \
+ uword _q = _p + _nb; \
+ if (_q > _a->limit) \
+ _p = (uword)ArenaAllocate(pool, _nb); \
+ else { \
+ VALGRIND_MEMPOOL_ALLOC(_a->base, p, nb); \
+ _a->avail = _q; \
+ } \
+ p = (void *)_p;
+
+
+#define ARENA_MARK(pool) ((void *) (pool)->current->avail)
+#define UPTRDIFF(p,q) ((uword)(p) - (uword)(q))
+
+#ifdef DEBUG
+#define FREE_PATTERN 0xDA
+#define CLEAR_UNUSED(a) (assert((a)->avail <= (a)->limit), \
+ memset((void*)(a)->avail, FREE_PATTERN, \
+ (a)->limit - (a)->avail))
+#define CLEAR_ARENA(a) memset((void*)(a), FREE_PATTERN, \
+ (a)->limit - (uword)(a))
+#else
+#define CLEAR_UNUSED(a)
+#define CLEAR_ARENA(a)
+#endif
+
+
+} // namespace
+
+#endif
diff --git a/khtml/misc/blocked_icon.cpp b/khtml/misc/blocked_icon.cpp
new file mode 100644
index 000000000..4136cd9cf
--- /dev/null
+++ b/khtml/misc/blocked_icon.cpp
@@ -0,0 +1,41 @@
+static const unsigned int blocked_icon_len = 599;
+
+static const unsigned char blocked_icon_data[] = {
+0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
+0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x08,0x06,0x00,0x00,0x00,0xaa,0x69,0x71,
+0xde,0x00,0x00,0x00,0x06,0x62,0x4b,0x47,0x44,0x00,0xff,0x00,0xff,0x00,0xff,0xa0,
+0xbd,0xa7,0x93,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,
+0x00,0x0b,0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x01,0xf7,0x49,0x44,0x41,0x54,
+0x78,0xda,0xed,0x9b,0xd1,0x8e,0x84,0x30,0x08,0x45,0x07,0xb2,0x3f,0x36,0x5f,0xbe,
+0x9f,0xc6,0x3e,0xb9,0x31,0xc6,0x28,0x70,0x01,0x21,0xd5,0xe7,0xc9,0x94,0x73,0x4a,
+0x5b,0xac,0x2d,0x89,0xc8,0x67,0xe5,0x87,0x3f,0x8b,0x3f,0xcb,0x0b,0xf8,0xa9,0x6c,
+0x8c,0x88,0x7e,0xb5,0xbf,0x15,0x91,0x6f,0x49,0x4c,0x99,0x73,0xc0,0x11,0xd8,0xd2,
+0x12,0x15,0x09,0x49,0x11,0xb0,0x81,0x47,0xfe,0x33,0x25,0x89,0x08,0x15,0x90,0x01,
+0x9e,0x2d,0x22,0x44,0x40,0x05,0x78,0x96,0x08,0x48,0xc0,0x13,0xe0,0xd1,0x22,0x78,
+0x32,0xfc,0xbe,0x7d,0xcb,0x0a,0x03,0x0b,0x20,0xa2,0x5f,0x69,0x00,0xbf,0x97,0x20,
+0x4e,0x09,0xe6,0x21,0xb0,0xc1,0xa3,0x29,0xab,0xe9,0x55,0xef,0xff,0x5b,0x86,0x83,
+0x49,0x80,0x17,0x9e,0x8c,0xeb,0xf9,0xbe,0x27,0x25,0x59,0x82,0x5a,0x80,0x15,0xde,
+0x0a,0x1d,0x2d,0x43,0x2b,0x41,0x25,0xc0,0x0b,0x1f,0x59,0xb4,0x78,0xb2,0x4f,0x23,
+0xe1,0x56,0x80,0x65,0xb6,0x4f,0xab,0xd6,0xc0,0xa1,0x77,0x15,0x8f,0x6a,0x15,0x98,
+0x08,0xaf,0x8d,0x9b,0x23,0x1a,0xef,0x08,0xbf,0x97,0x70,0xb5,0x3c,0xc2,0xfb,0x01,
+0x9d,0xe1,0xa1,0x42,0x48,0x13,0xc0,0x14,0xf8,0xab,0x2c,0x80,0x33,0xa0,0x03,0x3c,
+0x45,0x67,0x80,0xb6,0xf7,0xbb,0xc0,0x8b,0xc8,0x97,0x9c,0x59,0xc0,0xc8,0xb8,0xef,
+0x02,0x8f,0xc4,0xc5,0xde,0x40,0xba,0x15,0x39,0x9a,0x78,0xce,0xb2,0xe0,0xf1,0x5d,
+0xe1,0xac,0x0a,0x2f,0xed,0x75,0x38,0xb2,0xf1,0x68,0x78,0xcd,0x5c,0x10,0xbe,0x0a,
+0x4c,0xed,0xf9,0x53,0x01,0x55,0xc5,0xc7,0x93,0xf0,0xc7,0x79,0x80,0xab,0x83,0xc8,
+0x86,0xb7,0x0e,0x03,0x5e,0x31,0xed,0x1f,0x11,0xd0,0x11,0xbe,0x4c,0x40,0x57,0xf8,
+0x12,0x01,0x9d,0xe1,0xd3,0x05,0x74,0x87,0x4f,0x15,0x30,0x01,0x3e,0x4d,0xc0,0x14,
+0xf8,0x14,0x01,0x93,0xe0,0xcd,0x02,0xee,0xf6,0xd7,0x3a,0xc0,0x5b,0x63,0x60,0xf4,
+0x65,0x62,0x5a,0xcf,0x1f,0xdb,0xe4,0x15,0xd3,0x1e,0x9a,0x03,0x8e,0xc3,0xa0,0x13,
+0xbc,0x27,0x16,0x5e,0xb5,0xe7,0xff,0xe3,0x39,0xfb,0x34,0x76,0x07,0x46,0xbb,0x6c,
+0xe8,0x02,0xaf,0xf9,0x84,0x77,0xd6,0xbe,0xeb,0x9c,0x60,0xf6,0x27,0x6b,0xe4,0x5d,
+0x3f,0x64,0x0e,0x40,0x56,0x83,0x27,0xe0,0x91,0x6d,0xfc,0xfc,0x97,0xa1,0x02,0xf8,
+0x94,0x55,0x20,0x22,0x0b,0xaa,0xe0,0x91,0x8f,0x38,0x3c,0xbd,0xe7,0xd1,0x3d,0xcc,
+0x4b,0x01,0xde,0x2c,0xe8,0x04,0x7f,0x17,0x0b,0x6b,0x81,0xa6,0xc2,0xbb,0xea,0x00,
+0xb4,0xe0,0xc9,0x3a,0x23,0x64,0x4d,0xf9,0x90,0x33,0x42,0xa8,0x04,0x54,0x44,0x8b,
+0x53,0x62,0x48,0xe9,0xeb,0x91,0xd1,0xf2,0x9c,0x20,0x2a,0xc1,0x32,0x2e,0xdb,0x9e,
+0x14,0x8d,0x92,0xd0,0x69,0xe9,0x75,0xd5,0x01,0xdb,0xf2,0x48,0x8d,0xc0,0xbd,0xab,
+0x8f,0xbb,0x10,0xda,0x1a,0xa3,0x06,0xf0,0xc8,0x44,0xfb,0xde,0x18,0x79,0xef,0x0c,
+0xbd,0xb7,0xc6,0xde,0x7b,0x83,0x75,0xe3,0x76,0xb5,0x9b,0xa3,0x13,0x9e,0xe5,0x2f,
+0x4f,0xff,0x01,0x14,0x87,0xe1,0xb6,0x01,0xbb,0x79,0x86,0x00,0x00,0x00,0x00,0x49,
+0x45,0x4e,0x44,0xae,0x42,0x60,0x82};
diff --git a/khtml/misc/blocked_icon.png b/khtml/misc/blocked_icon.png
new file mode 100644
index 000000000..0f545c393
--- /dev/null
+++ b/khtml/misc/blocked_icon.png
Binary files differ
diff --git a/khtml/misc/decoder.cpp b/khtml/misc/decoder.cpp
new file mode 100644
index 000000000..56f68b429
--- /dev/null
+++ b/khtml/misc/decoder.cpp
@@ -0,0 +1,790 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ Copyright (C) 2003 Dirk Mueller (mueller@kde.org)
+ Copyright (C) 2003 Apple Computer, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+//----------------------------------------------------------------------------
+//
+// KDE HTML Widget -- decoder for input stream
+
+#undef DECODE_DEBUG
+//#define DECODE_DEBUG
+
+#include <assert.h>
+
+#include "decoder.h"
+#include "guess_ja.h"
+
+using namespace khtml;
+
+#include "htmlhashes.h"
+
+#include <qregexp.h>
+#include <qtextcodec.h>
+
+#include <kglobal.h>
+#include <kcharsets.h>
+
+#include <ctype.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+
+
+Decoder::Decoder()
+{
+ // latin1
+ m_codec = QTextCodec::codecForMib(4);
+ m_decoder = m_codec->makeDecoder();
+ enc = 0;
+ m_type = DefaultEncoding;
+ body = false;
+ beginning = true;
+ visualRTL = false;
+ m_autoDetectLanguage = SemiautomaticDetection;
+ kc = NULL;
+}
+
+Decoder::~Decoder()
+{
+ delete m_decoder;
+ if (kc)
+ delete kc;
+}
+
+void Decoder::setEncoding(const char *_encoding, EncodingType type)
+{
+#ifdef DECODE_DEBUG
+ kdDebug(6005) << "setEncoding " << _encoding << " " << type << endl;
+#endif
+ enc = _encoding;
+#ifdef DECODE_DEBUG
+ kdDebug(6005) << "old encoding is:" << m_codec->name() << endl;
+#endif
+ enc = enc.lower();
+#ifdef DECODE_DEBUG
+ kdDebug(6005) << "requesting:" << enc << endl;
+#endif
+ if(enc.isNull() || enc.isEmpty())
+ return;
+
+#ifdef APPLE_CHANGES
+ QTextCodec *codec = (type == EncodingFromMetaTag || type == EncodingFromXMLHeader)
+ ? QTextCodec::codecForNameEightBitOnly(enc)
+ : QTextCodec::codecForName(enc);
+ if (codec) {
+ enc = codec->name();
+ visualRTL = codec->usesVisualOrdering();
+ }
+#else
+ if(enc == "visual") // hebrew visually ordered
+ enc = "iso8859-8";
+ bool b;
+ QTextCodec *codec = KGlobal::charsets()->codecForName(enc, b);
+ if (!b)
+ codec = 0;
+
+ if (type == EncodingFromMetaTag || type == EncodingFromXMLHeader) {
+ //Sometimes the codec specified is absurd, i.e. UTF-16 despite
+ //us decoding a meta tag as ASCII. In that case, ignore it.
+ if (codec &&
+ (codec->mibEnum() == 1000)) //UTF16 or similar.
+ codec = 0;
+ }
+
+ if (codec && codec->mibEnum() == 11) {
+ //We do NOT want to use Qt's QHebrewCodec, since it tries to reorder itself.
+ codec = QTextCodec::codecForName("iso8859-8-i");
+
+ // visually ordered unless one of the following
+ if( !(enc == "iso-8859-8-i" || enc == "iso_8859-8-i"
+ || enc == "csiso88598i" || enc == "logical") )
+ visualRTL = true;
+ }
+#endif
+
+ if( codec ) { // in case the codec didn't exist, we keep the old one (fixes some sites specifying invalid codecs)
+ m_codec = codec;
+ m_type = type;
+ delete m_decoder;
+ m_decoder = m_codec->makeDecoder();
+ }
+
+#ifdef DECODE_DEBUG
+ kdDebug(6005) << "Decoder::encoding used is" << m_codec->name() << endl;
+#endif
+}
+
+const char *Decoder::encoding() const
+{
+ return enc;
+}
+
+// Other browsers allow comments in the head section, so we need to also.
+// It's important not to look for tags inside the comments.
+static void skipComment(const char *&ptr, const char *pEnd)
+{
+ const char *p = ptr;
+ // Allow <!-->; other browsers do.
+ if (*p == '>') {
+ p++;
+ } else {
+ while (p != pEnd) {
+ if (*p == '-') {
+ // This is the real end of comment, "-->".
+ if (p[1] == '-' && p[2] == '>') {
+ p += 3;
+ break;
+ }
+ // This is the incorrect end of comment that other browsers allow, "--!>".
+ if (p[1] == '-' && p[2] == '!' && p[3] == '>') {
+ p += 4;
+ break;
+ }
+ }
+ p++;
+ }
+ }
+ ptr = p;
+}
+
+// Returns the position of the encoding string.
+static int findXMLEncoding(const QCString &str, int &encodingLength)
+{
+ int len = str.length();
+
+ int pos = str.find("encoding");
+ if (pos == -1)
+ return -1;
+ pos += 8;
+
+ // Skip spaces and stray control characters.
+ while (pos < len && str[pos] <= ' ')
+ ++pos;
+
+ //Bail out if nothing after
+ if (pos >= len)
+ return -1;
+
+ // Skip equals sign.
+ if (str[pos] != '=')
+ return -1;
+ ++pos;
+
+ // Skip spaces and stray control characters.
+ while (pos < len && str[pos] <= ' ')
+ ++pos;
+
+ //Bail out if nothing after
+ if (pos >= len)
+ return -1;
+
+ // Skip quotation mark.
+ char quoteMark = str[pos];
+ if (quoteMark != '"' && quoteMark != '\'')
+ return -1;
+ ++pos;
+
+ // Find the trailing quotation mark.
+ int end = pos;
+ while (end < len && str[end] != quoteMark)
+ ++end;
+
+ if (end >= len)
+ return -1;
+
+ encodingLength = end - pos;
+ return pos;
+}
+
+QString Decoder::decode(const char *data, int len)
+{
+ // Check for UTF-16 or UTF-8 BOM mark at the beginning, which is a sure sign of a Unicode encoding.
+ int bufferLength = buffer.length();
+ const int maximumBOMLength = 10;
+ if (beginning && bufferLength + len >= maximumBOMLength) {
+ // If the user has chosen utf16 we still need to auto-detect the endianness
+ if ((m_type != UserChosenEncoding) || (m_codec->mibEnum() == 1000)) {
+ // Extract the first three bytes.
+ // Handle the case where some of bytes are already in the buffer.
+ const uchar *udata = (const uchar *)data;
+ uchar c1 = bufferLength >= 1 ? (uchar)buffer[0] : *udata++;
+ uchar c2 = bufferLength >= 2 ? (uchar)buffer[1] : *udata++;
+ uchar c3 = bufferLength >= 3 ? (uchar)buffer[2] : *udata++;
+
+ // Check for the BOM
+ const char *autoDetectedEncoding;
+ if ((c1 == 0xFE && c2 == 0xFF) || (c1 == 0xFF && c2 == 0xFE)) {
+ autoDetectedEncoding = "ISO-10646-UCS-2";
+ } else if (c1 == 0xEF && c2 == 0xBB && c3 == 0xBF) {
+ autoDetectedEncoding = "UTF-8";
+ } else if (c1 == 0x00 || c2 == 0x00) {
+ uchar c4 = bufferLength >= 4 ? (uchar)buffer[3] : *udata++;
+ uchar c5 = bufferLength >= 5 ? (uchar)buffer[4] : *udata++;
+ uchar c6 = bufferLength >= 6 ? (uchar)buffer[5] : *udata++;
+ uchar c7 = bufferLength >= 7 ? (uchar)buffer[6] : *udata++;
+ uchar c8 = bufferLength >= 8 ? (uchar)buffer[7] : *udata++;
+ uchar c9 = bufferLength >= 9 ? (uchar)buffer[8] : *udata++;
+ uchar c10 = bufferLength >= 10 ? (uchar)buffer[9] : *udata++;
+ int nul_count_even = (c2 != 0) + (c4 != 0) + (c6 != 0) + (c8 != 0) + (c10 != 0);
+ int nul_count_odd = (c1 != 0) + (c3 != 0) + (c5 != 0) + (c7 != 0) + (c9 != 0);
+ if ((nul_count_even == 0 && nul_count_odd == 5) ||
+ (nul_count_even == 5 && nul_count_odd == 0))
+ autoDetectedEncoding = "ISO-10646-UCS-2";
+ else
+ autoDetectedEncoding = 0;
+ } else {
+ autoDetectedEncoding = 0;
+ }
+
+ // If we found a BOM, use the encoding it implies.
+ if (autoDetectedEncoding != 0) {
+ m_type = AutoDetectedEncoding;
+ m_codec = QTextCodec::codecForName(autoDetectedEncoding);
+ assert(m_codec);
+ enc = m_codec->name();
+ delete m_decoder;
+ m_decoder = m_codec->makeDecoder();
+ if (m_codec->mibEnum() == 1000 && c2 == 0x00)
+ {
+ // utf16LE, we need to put the decoder in LE mode
+ char reverseUtf16[3] = {0xFF, 0xFE, 0x00};
+ m_decoder->toUnicode(reverseUtf16, 2);
+ }
+ }
+ }
+ beginning = false;
+ }
+
+ // this is not completely efficient, since the function might go
+ // through the html head several times...
+
+ bool lookForMetaTag = m_type == DefaultEncoding && !body;
+
+ if (lookForMetaTag) {
+#ifdef DECODE_DEBUG
+ kdDebug(6005) << "looking for charset definition" << endl;
+#endif
+ { // extra level of braces to keep indenting matching original for better diff'ing
+#ifdef APPLE_CHANGES
+ buffer.append(data, len);
+#else
+ if(m_codec->mibEnum() != 1000) { // utf16
+ // replace '\0' by spaces, for buggy pages
+ char *d = const_cast<char *>(data);
+ int i = len - 1;
+ while(i >= 0) {
+ if(d[i] == 0) d[i] = ' ';
+ i--;
+ }
+ }
+ buffer += QCString(data, len+1);
+#endif
+ // we still don't have an encoding, and are in the head
+ // the following tags are allowed in <head>:
+ // SCRIPT|STYLE|META|LINK|OBJECT|TITLE|BASE
+ int invalid = 0; // invalid head tag count
+#ifdef APPLE_CHANGES
+ const char *ptr = buffer.latin1();
+ const char *pEnd = ptr + buffer.length();
+#else
+ const char *ptr = buffer.data();
+ const char *pEnd = ptr + buffer.length();
+#endif
+ while(ptr != pEnd)
+ {
+ if(*ptr == '<') {
+ bool end = false;
+ ptr++;
+
+ // Handle comments.
+ if (ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') {
+ ptr += 3;
+ skipComment(ptr, pEnd);
+ continue;
+ }
+
+ // Handle XML header, which can have encoding in it.
+ if (ptr[0] == '?' && ptr[1] == 'x' && ptr[2] == 'm' && ptr[3] == 'l') {
+ const char *end = ptr;
+ while (*end != '>' && *end != '\0') end++;
+ if (*end == '\0')
+ break;
+ QCString str(ptr, end - ptr + 1); //+1 as it must include the \0 terminator
+ int len;
+ int pos = findXMLEncoding(str, len);
+ if (pos != -1) {
+ setEncoding(str.mid(pos, len), EncodingFromXMLHeader);
+ if (m_type == EncodingFromXMLHeader)
+ goto found;
+ }
+ }
+
+ if(*ptr == '/') ptr++, end=true;
+ char tmp[20];
+ int len = 0;
+ while (
+ ((*ptr >= 'a') && (*ptr <= 'z') ||
+ (*ptr >= 'A') && (*ptr <= 'Z') ||
+ (*ptr >= '0') && (*ptr <= '9'))
+ && len < 19 )
+ {
+ tmp[len] = tolower( *ptr );
+ ptr++;
+ len++;
+ }
+ tmp[len] = 0;
+ int id = khtml::getTagID(tmp, len);
+ if(end) id += ID_CLOSE_TAG;
+
+ switch( id ) {
+ case ID_META:
+ {
+ // found a meta tag...
+ //ptr += 5;
+ const char * end = ptr;
+ while(*end != '>' && *end != '\0') end++;
+ if ( *end == '\0' ) break;
+ QCString str( ptr, (end-ptr)+1);
+ str = str.lower();
+ int pos = 0;
+ //if( (pos = str.find("http-equiv", pos)) == -1) break;
+ //if( (pos = str.find("content-type", pos)) == -1) break;
+ while( pos < ( int ) str.length() ) {
+ if( (pos = str.find("charset", pos)) == -1) break;
+ pos += 7;
+ // skip whitespace..
+ while( pos < (int)str.length() && str[pos] <= ' ' ) pos++;
+ if ( pos == ( int )str.length()) break;
+ if ( str[pos++] != '=' ) continue;
+ while ( pos < ( int )str.length() &&
+ ( str[pos] <= ' ' ) || str[pos] == '=' || str[pos] == '"' || str[pos] == '\'')
+ pos++;
+
+ // end ?
+ if ( pos == ( int )str.length() ) break;
+ uint endpos = pos;
+ while( endpos < str.length() &&
+ (str[endpos] != ' ' && str[endpos] != '"' && str[endpos] != '\''
+ && str[endpos] != ';' && str[endpos] != '>') )
+ endpos++;
+ enc = str.mid(pos, endpos-pos);
+#ifdef DECODE_DEBUG
+ kdDebug( 6005 ) << "Decoder: found charset: " << enc.data() << endl;
+#endif
+ setEncoding(enc, EncodingFromMetaTag);
+ if( m_type == EncodingFromMetaTag ) goto found;
+
+ if ( endpos >= str.length() || str[endpos] == '/' || str[endpos] == '>' ) break;
+
+ pos = endpos + 1;
+ }
+ }
+ case ID_SCRIPT:
+ case (ID_SCRIPT+ID_CLOSE_TAG):
+ case ID_NOSCRIPT:
+ case (ID_NOSCRIPT+ID_CLOSE_TAG):
+ case ID_STYLE:
+ case (ID_STYLE+ID_CLOSE_TAG):
+ case ID_LINK:
+ case (ID_LINK+ID_CLOSE_TAG):
+ case ID_OBJECT:
+ case (ID_OBJECT+ID_CLOSE_TAG):
+ case ID_TITLE:
+ case (ID_TITLE+ID_CLOSE_TAG):
+ case ID_BASE:
+ case (ID_BASE+ID_CLOSE_TAG):
+ case ID_HTML:
+ case ID_HEAD:
+ case 0:
+ case (0 + ID_CLOSE_TAG ):
+ break;
+ case ID_BODY:
+ case (ID_HEAD+ID_CLOSE_TAG):
+ body = true;
+#ifdef DECODE_DEBUG
+ kdDebug( 6005 ) << "Decoder: no charset found. Id=" << id << endl;
+#endif
+ goto found;
+ default:
+ // Invalid tag in head. Let's be a little tolerant
+ invalid++;
+ if (invalid > 2) {
+ body = true;
+#ifdef DECODE_DEBUG
+ kdDebug( 6005 ) << "Decoder: no charset found. Id=" << id << endl;
+#endif
+ goto found;
+ }
+ }
+ }
+ else
+ ptr++;
+ }
+ if (invalid > 0) {
+ body = true;
+ goto found;
+ }
+ return QString::null;
+ }
+ }
+
+ found:
+ if (m_type == DefaultEncoding)
+ {
+#ifdef DECODE_DEBUG
+ kdDebug( 6005 ) << "Decoder: use auto-detect (" << strlen(data) << ")" << endl;
+#endif
+
+ switch ( m_autoDetectLanguage) {
+ case Decoder::Arabic:
+ enc = automaticDetectionForArabic( (const unsigned char*) data, len );
+ break;
+ case Decoder::Baltic:
+ enc = automaticDetectionForBaltic( (const unsigned char*) data, len );
+ break;
+ case Decoder::CentralEuropean:
+ enc = automaticDetectionForCentralEuropean( (const unsigned char*) data, len );
+ break;
+ case Decoder::Russian:
+ case Decoder::Ukrainian:
+ enc = automaticDetectionForCyrillic( (const unsigned char*) data, len, m_autoDetectLanguage );
+ break;
+ case Decoder::Greek:
+ enc = automaticDetectionForGreek( (const unsigned char*) data, len );
+ break;
+ case Decoder::Hebrew:
+ enc = automaticDetectionForHebrew( (const unsigned char*) data, len );
+ break;
+ case Decoder::Japanese:
+ enc = automaticDetectionForJapanese( (const unsigned char*) data, len );
+ break;
+ case Decoder::Turkish:
+ enc = automaticDetectionForTurkish( (const unsigned char*) data, len );
+ break;
+ case Decoder::WesternEuropean:
+ enc = automaticDetectionForWesternEuropean( (const unsigned char*) data, len );
+ break;
+ case Decoder::SemiautomaticDetection:
+ case Decoder::Chinese:
+ case Decoder::Korean:
+ case Decoder::Thai:
+ case Decoder::Unicode:
+ // huh. somethings broken in this code ### FIXME
+ enc = 0; //Reset invalid codec we tried, so we get back to latin1 fallback.
+ break;
+ }
+
+#ifdef DECODE_DEBUG
+ kdDebug( 6005 ) << "Decoder: auto detect encoding is " << enc.data() << endl;
+#endif
+ if ( !enc.isEmpty() )
+ setEncoding( enc.data(), AutoDetectedEncoding);
+ }
+
+
+ // if we still haven't found an encoding latin1 will be used...
+ // this is according to HTML4.0 specs
+ if (!m_codec)
+ {
+ if(enc.isEmpty()) enc = "iso8859-1";
+ m_codec = QTextCodec::codecForName(enc);
+ // be sure not to crash
+ if(!m_codec) {
+ m_codec = QTextCodec::codecForMib(4);
+ enc = "iso8859-1";
+ }
+ delete m_decoder;
+ m_decoder = m_codec->makeDecoder();
+ }
+ QString out;
+
+ if(!buffer.isEmpty() && enc != "ISO-10646-UCS-2") {
+ out = m_decoder->toUnicode(buffer, buffer.length());
+ buffer = "";
+ } else {
+ if(m_codec->mibEnum() != 1000) // utf16
+ {
+ // ### hack for a bug in QTextCodec. It cut's the input stream
+ // in case there are \0 in it. ZDNET has them inside... :-(
+ char *d = const_cast<char *>(data);
+ int i = len - 1;
+ while(i >= 0) {
+ if(*(d+i) == 0) *(d+i) = ' ';
+ i--;
+ }
+ }
+ out = m_decoder->toUnicode(data, len);
+ }
+
+ return out;
+}
+
+QString Decoder::flush() const
+{
+ return m_decoder->toUnicode(buffer, buffer.length());
+}
+
+QCString Decoder::automaticDetectionForArabic( const unsigned char* ptr, int size )
+{
+ for ( int i = 0; i < size; ++i ) {
+ if ( ( ptr[ i ] >= 0x80 && ptr[ i ] <= 0x9F ) || ptr[ i ] == 0xA1 || ptr[ i ] == 0xA2 || ptr[ i ] == 0xA3
+ || ( ptr[ i ] >= 0xA5 && ptr[ i ] <= 0xAB ) || ( ptr[ i ] >= 0xAE && ptr[ i ] <= 0xBA )
+ || ptr[ i ] == 0xBC || ptr[ i ] == 0xBD || ptr[ i ] == 0xBE || ptr[ i ] == 0xC0
+ || ( ptr[ i ] >= 0xDB && ptr[ i ] <= 0xDF ) || ( ptr[ i ] >= 0xF3 ) ) {
+ return "cp1256";
+ }
+ }
+
+ return "iso-8859-6";
+}
+
+QCString Decoder::automaticDetectionForBaltic( const unsigned char* ptr, int size )
+{
+ for ( int i = 0; i < size; ++i ) {
+ if ( ( ptr[ i ] >= 0x80 && ptr[ i ] <= 0x9E ) )
+ return "cp1257";
+
+ if ( ptr[ i ] == 0xA1 || ptr[ i ] == 0xA5 )
+ return "iso-8859-13";
+ }
+
+ return "iso-8859-13";
+}
+
+QCString Decoder::automaticDetectionForCentralEuropean(const unsigned char* ptr, int size )
+{
+ QCString charset = QCString();
+ for ( int i = 0; i < size; ++i ) {
+ if ( ptr[ i ] >= 0x80 && ptr[ i ] <= 0x9F ) {
+ if ( ptr[ i ] == 0x81 || ptr[ i ] == 0x83 || ptr[ i ] == 0x90 || ptr[ i ] == 0x98 )
+ return "ibm852";
+
+ if ( i + 1 > size )
+ return "cp1250";
+ else { // maybe ibm852 ?
+ charset = "cp1250";
+ continue;
+ }
+ }
+ if ( ptr[ i ] == 0xA5 || ptr[ i ] == 0xAE || ptr[ i ] == 0xBE || ptr[ i ] == 0xC3 || ptr[ i ] == 0xD0 || ptr[ i ] == 0xE3 || ptr[ i ] == 0xF0 ) {
+ if ( i + 1 > size )
+ return "iso-8859-2";
+ else { // maybe ibm852 ?
+ if ( charset.isNull() )
+ charset = "iso-8859-2";
+ continue;
+ }
+ }
+ }
+
+ if ( charset.isNull() )
+ charset = "iso-8859-3";
+
+ return charset.data();
+}
+
+QCString Decoder::automaticDetectionForCyrillic( const unsigned char* ptr, int size, AutoDetectLanguage _language )
+{
+ int koi_st=0;
+ int cp1251_st=0;
+
+// int koi_na=0;
+// int cp1251_na=0;
+
+ int koi_o_capital=0;
+ int koi_o=0;
+ int cp1251_o_capital=0;
+ int cp1251_o=0;
+
+ int koi_a_capital=0;
+ int koi_a=0;
+ int cp1251_a_capital=0;
+ int cp1251_a=0;
+
+ int koi_i_capital=0;
+ int koi_i=0;
+ int cp1251_i_capital=0;
+ int cp1251_i=0;
+
+ int cp1251_small_range=0;
+ int koi_small_range=0;
+ int ibm866_small_range=0;
+
+ int i;
+ for (i=1; (i<size) && (cp1251_small_range+koi_small_range<1000) ;++i)
+ {
+ if (ptr[i]>0xdf)
+ {
+ ++cp1251_small_range;
+
+ if (ptr[i]==0xee)//small o
+ ++cp1251_o;
+ else if (ptr[i]==0xe0)//small a
+ ++cp1251_a;
+ else if (ptr[i]==0xe8)//small i
+ ++cp1251_i;
+ else if (ptr[i]==0xf2 && ptr[i-1]==0xf1)//small st
+ ++cp1251_st;
+
+ else if (ptr[i]==0xef)
+ ++koi_o_capital;
+ else if (ptr[i]==0xe1)
+ ++koi_a_capital;
+ else if (ptr[i]==0xe9)
+ ++koi_i_capital;
+
+ }
+ else if (ptr[i]>0xbf)
+ {
+ ++koi_small_range;
+
+ if (ptr[i]==0xcf)//small o
+ ++koi_o;
+ else if (ptr[i]==0xc1)//small a
+ ++koi_a;
+ else if (ptr[i]==0xc9)//small i
+ ++koi_i;
+ else if (ptr[i]==0xd4 && ptr[i-1]==0xd3)//small st
+ ++koi_st;
+
+ else if (ptr[i]==0xce)
+ ++cp1251_o_capital;
+ else if (ptr[i]==0xc0)
+ ++cp1251_a_capital;
+ else if (ptr[i]==0xc8)
+ ++cp1251_i_capital;
+ }
+ else if (ptr[i]>0x9f && ptr[i]<0xaf) //first 16 letterz is 60%
+ ++ibm866_small_range;
+
+ }
+
+ if (ibm866_small_range>cp1251_small_range+koi_small_range)
+ return "ibm866"; //hehe this is a rare case :)
+
+ QCString koi_string = "koi8-u";
+ QCString cp1251_string = "cp1251";
+
+ if (cp1251_st==0 && koi_st>1)
+ return koi_string;
+ if (koi_st==0 && cp1251_st>1)
+ return cp1251_string;
+
+ if (cp1251_st>0 && koi_st>0)
+ {
+ if (cp1251_st/koi_st>2)
+ return cp1251_string;
+ else if (koi_st/cp1251_st>2)
+ return koi_string;
+ }
+
+ if (cp1251_a>koi_a && cp1251_o>koi_o && cp1251_i>koi_i)
+ return cp1251_string;
+ if (koi_a>cp1251_a && koi_o>cp1251_o && koi_i>cp1251_i)
+ return koi_string;
+
+ if (cp1251_a_capital>koi_a_capital && cp1251_o_capital>koi_o_capital && cp1251_i_capital>koi_i_capital)
+ return cp1251_string;
+ if (koi_a_capital>cp1251_a_capital && koi_o_capital>cp1251_o_capital && koi_i_capital>cp1251_i_capital)
+ return koi_string;
+
+ //fallback...
+ if (cp1251_small_range>koi_small_range)
+ return cp1251_string;
+ else
+ return koi_string;
+
+}
+
+QCString Decoder::automaticDetectionForGreek( const unsigned char* ptr, int size )
+{
+ for ( int i = 0; i < size; ++i ) {
+ if ( ptr[ i ] == 0x80 || ( ptr[ i ] >= 0x82 && ptr[ i ] <= 0x87 ) || ptr[ i ] == 0x89 || ptr[ i ] == 0x8B
+ || ( ptr[ i ] >= 0x91 && ptr[ i ] <= 0x97 ) || ptr[ i ] == 0x99 || ptr[ i ] == 0x9B || ptr[ i ] == 0xA4
+ || ptr[ i ] == 0xA5 || ptr[ i ] == 0xAE ) {
+ return "cp1253";
+ }
+ }
+
+ return "iso-8859-7";
+}
+
+QCString Decoder::automaticDetectionForHebrew( const unsigned char* ptr, int size )
+{
+ for ( int i = 0; i < size; ++i ) {
+ if ( ptr[ i ] == 0x80 || ( ptr[ i ] >= 0x82 && ptr[ i ] <= 0x89 ) || ptr[ i ] == 0x8B
+ || ( ptr[ i ] >= 0x91 && ptr[ i ] <= 0x99 ) || ptr[ i ] == 0x9B || ptr[ i ] == 0xA1 || ( ptr[ i ] >= 0xBF && ptr[ i ] <= 0xC9 )
+ || ( ptr[ i ] >= 0xCB && ptr[ i ] <= 0xD8 ) ) {
+ return "cp1255";
+ }
+
+ if ( ptr[ i ] == 0xDF )
+ return "iso-8859-8-i";
+ }
+
+ return "iso-8859-8-i";
+}
+
+QCString Decoder::automaticDetectionForJapanese( const unsigned char* ptr, int size )
+{
+ if (!kc)
+ kc = new JapaneseCode();
+
+ switch ( kc->guess_jp( (const char*)ptr, size ) ) {
+ case JapaneseCode::JIS:
+ return "jis7";
+ case JapaneseCode::EUC:
+ return "eucjp";
+ case JapaneseCode::SJIS:
+ return "sjis";
+ case JapaneseCode::UTF8:
+ return "utf8";
+ default:
+ break;
+ }
+
+ return "";
+}
+
+QCString Decoder::automaticDetectionForTurkish( const unsigned char* ptr, int size )
+{
+ for ( int i = 0; i < size; ++i ) {
+ if ( ptr[ i ] == 0x80 || ( ptr[ i ] >= 0x82 && ptr[ i ] <= 0x8C ) || ( ptr[ i ] >= 0x91 && ptr[ i ] <= 0x9C ) || ptr[ i ] == 0x9F ) {
+ return "cp1254";
+ }
+ }
+
+ return "iso-8859-9";
+}
+
+QCString Decoder::automaticDetectionForWesternEuropean( const unsigned char* ptr, int size )
+{
+ for ( int i = 0; i < size; ++i ) {
+ if ( ptr[ i ] >= 0x80 && ptr[ i ] <= 0x9F )
+ return "cp1252";
+ }
+
+ return "iso-8859-1"; //"iso-8859-15"; Which better at default ?
+}
+
+
+// -----------------------------------------------------------------------------
+#undef DECODE_DEBUG
diff --git a/khtml/misc/decoder.h b/khtml/misc/decoder.h
new file mode 100644
index 000000000..613b14043
--- /dev/null
+++ b/khtml/misc/decoder.h
@@ -0,0 +1,115 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 1999 Lars Knoll (knoll@mpi-hd.mpg.de)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+#ifndef KHTMLDECODER_H
+#define KHTMLDECODER_H
+
+#include <qstring.h>
+class QTextCodec;
+class QTextDecoder;
+
+namespace khtml {
+
+class JapaneseCode;
+
+/**
+ * @internal
+ */
+class Decoder
+{
+public:
+ enum EncodingType {
+ DefaultEncoding,
+ AutoDetectedEncoding,
+ EncodingFromXMLHeader,
+ EncodingFromMetaTag,
+ EncodingFromHTTPHeader,
+ UserChosenEncoding
+ };
+
+ Decoder();
+ ~Decoder();
+
+ void setEncoding(const char *encoding, EncodingType type);
+ const char *encoding() const;
+
+ QString decode(const char *data, int len);
+
+ bool visuallyOrdered() const { return visualRTL; }
+
+ const QTextCodec *codec() const { return m_codec; }
+
+ QString flush() const;
+
+
+ enum AutoDetectLanguage {
+ SemiautomaticDetection,
+ Arabic,
+ Baltic,
+ CentralEuropean,
+ Chinese,
+ Greek,
+ Hebrew,
+ Japanese,
+ Korean,
+ Russian,
+ Thai,
+ Turkish,
+ Ukrainian,
+ Unicode,
+ WesternEuropean
+ };
+
+ void setAutoDetectLanguage( AutoDetectLanguage _language ) { m_autoDetectLanguage = _language; }
+ AutoDetectLanguage autoDetectLanguage() { return m_autoDetectLanguage; }
+
+
+
+private:
+ QCString automaticDetectionForArabic( const unsigned char* str, int size );
+ QCString automaticDetectionForBaltic( const unsigned char* str, int size );
+ QCString automaticDetectionForCentralEuropean( const unsigned char* str, int size );
+ QCString automaticDetectionForCyrillic( const unsigned char* str, int size, AutoDetectLanguage _language );
+ QCString automaticDetectionForGreek( const unsigned char* str, int size );
+ QCString automaticDetectionForHebrew( const unsigned char* str, int size );
+ QCString automaticDetectionForJapanese( const unsigned char* str, int size );
+ QCString automaticDetectionForTurkish( const unsigned char* str, int size );
+ QCString automaticDetectionForWesternEuropean( const unsigned char* str, int size );
+
+ // codec used for decoding. default is Latin1.
+ QTextCodec *m_codec;
+ QTextDecoder *m_decoder; // only used for utf16
+ QCString enc;
+ EncodingType m_type;
+
+ QCString buffer;
+
+ bool body;
+ bool beginning;
+ bool visualRTL;
+
+ AutoDetectLanguage m_autoDetectLanguage;
+
+ JapaneseCode *kc;
+};
+
+}
+#endif
diff --git a/khtml/misc/guess_ja.cpp b/khtml/misc/guess_ja.cpp
new file mode 100644
index 000000000..0846d15eb
--- /dev/null
+++ b/khtml/misc/guess_ja.cpp
@@ -0,0 +1,379 @@
+/*
+ * This file is part of the KDE libraries
+ *
+ * Copyright (c) 2000-2003 Shiro Kawai, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the authors nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+ * original code is here.
+ * http://cvs.sourceforge.net/viewcvs.py/gauche/Gauche/ext/charconv/guess.c?view=markup
+ */
+
+/*
+ * Maybe we should use QTextCodec::heuristicContentMatch()
+ * But it fails detection. It's not useful.
+ */
+#include "decoder.h"
+#include "guess_ja.h"
+
+using namespace khtml;
+
+/* DFA tables */
+const dfa_table guess_eucj_st[] = {
+ { /* state init */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1,
+ },
+ { /* state jis0201_kana */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ },
+ { /* state jis0213_1 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, -1,
+ },
+ { /* state jis0213_2 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, -1,
+ },
+};
+
+guess_arc guess_eucj_ar[7] = {
+ { 0, 1.0 }, /* init -> init */
+ { 1, 0.8 }, /* init -> jis0201_kana */
+ { 3, 0.95 }, /* init -> jis0213_2 */
+ { 2, 1.0 }, /* init -> jis0213_1 */
+ { 0, 1.0 }, /* jis0201_kana -> init */
+ { 0, 1.0 }, /* jis0213_1 -> init */
+ { 0, 1.0 }, /* jis0213_2 -> init */
+};
+
+const dfa_table guess_sjis_st[] = {
+ { /* state init */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ -1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4,
+ },
+ { /* state jis0213 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, -1,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, -1, -1, -1,
+ },
+};
+
+guess_arc guess_sjis_ar[6] = {
+ { 0, 1.0 }, /* init -> init */
+ { 1, 1.0 }, /* init -> jis0213 */
+ { 0, 0.8 }, /* init -> init */
+ { 1, 0.95 }, /* init -> jis0213 */
+ { 0, 0.8 }, /* init -> init */
+ { 0, 1.0 }, /* jis0213 -> init */
+};
+
+const dfa_table guess_utf8_st[] = {
+ { /* state init */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, -1, -1,
+ },
+ { /* state 1byte_more */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ },
+ { /* state 2byte_more */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ },
+ { /* state 3byte_more */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ },
+ { /* state 4byte_more */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ },
+ { /* state 5byte_more */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ },
+};
+
+guess_arc guess_utf8_ar[11] = {
+ { 0, 1.0 }, /* init -> init */
+ { 1, 1.0 }, /* init -> 1byte_more */
+ { 2, 1.0 }, /* init -> 2byte_more */
+ { 3, 1.0 }, /* init -> 3byte_more */
+ { 4, 1.0 }, /* init -> 4byte_more */
+ { 5, 1.0 }, /* init -> 5byte_more */
+ { 0, 1.0 }, /* 1byte_more -> init */
+ { 1, 1.0 }, /* 2byte_more -> 1byte_more */
+ { 2, 1.0 }, /* 3byte_more -> 2byte_more */
+ { 3, 1.0 }, /* 4byte_more -> 3byte_more */
+ { 4, 1.0 }, /* 5byte_more -> 4byte_more */
+};
+
+/* Guessing Routine */
+enum JapaneseCode::Type JapaneseCode::guess_jp(const char *buf, int buflen)
+{
+ int i;
+ guess_dfa *top = NULL;
+
+ for (i=0; i<buflen; i++) {
+ int c = (unsigned char)buf[i];
+
+ /* special treatment of jis escape sequence */
+ if (c == 0x1b || last_JIS_escape) {
+ if (i < buflen-1) {
+ if (last_JIS_escape)
+ c = (unsigned char)buf[i];
+ else
+ c = (unsigned char)buf[++i];
+ last_JIS_escape = false;
+
+ if (c == '$' || c == '(') {
+ return JapaneseCode::JIS;
+ }
+ } else {
+ last_JIS_escape = true;
+ }
+ }
+
+ if (DFA_ALIVE(eucj)) {
+ if (!DFA_ALIVE(sjis) && !DFA_ALIVE(utf8)) return JapaneseCode::EUC;
+ DFA_NEXT(eucj, c);
+ }
+ if (DFA_ALIVE(sjis)) {
+ if (!DFA_ALIVE(eucj) && !DFA_ALIVE(utf8)) return JapaneseCode::SJIS;
+ DFA_NEXT(sjis, c);
+ }
+ if (DFA_ALIVE(utf8)) {
+ if (!DFA_ALIVE(sjis) && !DFA_ALIVE(eucj)) return JapaneseCode::UTF8;
+ DFA_NEXT(utf8, c);
+ }
+
+ if (!DFA_ALIVE(eucj) && !DFA_ALIVE(sjis) && !DFA_ALIVE(utf8)) {
+ /* we ran out the possibilities */
+ return JapaneseCode::ASCII;
+ }
+ }
+
+ /* ascii code check */
+ if (eucj->score == 1.0 && sjis->score == 1.0 && utf8->score == 1.0)
+ return JapaneseCode::ASCII;
+
+ /* Now, we have ambigous code. Pick the highest score. If more than
+ one candidate tie, pick the default encoding. */
+ if (DFA_ALIVE(eucj)) top = eucj;
+ if (DFA_ALIVE(utf8)) {
+ if (top) {
+ if (top->score < utf8->score) top = utf8;
+ } else {
+ top = utf8;
+ }
+ }
+ if (DFA_ALIVE(sjis)) {
+ if (top) {
+ if (top->score <= sjis->score) top = sjis;
+ } else {
+ top = sjis;
+ }
+ }
+
+ if (top == eucj) return JapaneseCode::EUC;
+ if (top == utf8) return JapaneseCode::UTF8;
+ if (top == sjis) return JapaneseCode::SJIS;
+
+ return JapaneseCode::ASCII;
+}
diff --git a/khtml/misc/guess_ja.h b/khtml/misc/guess_ja.h
new file mode 100644
index 000000000..9dee907e6
--- /dev/null
+++ b/khtml/misc/guess_ja.h
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the KDE libraries
+ *
+ * Copyright (c) 2000-2003 Shiro Kawai, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the authors nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+ * original code is here.
+ * http://cvs.sourceforge.net/viewcvs.py/gauche/Gauche/ext/charconv/guess.c?view=markup
+ */
+#ifndef GUESS_JA_H
+#define GUESS_JA_H
+
+namespace khtml {
+ class guess_arc {
+ public:
+ unsigned int next; /* next state */
+ double score; /* score */
+ };
+}
+
+using namespace khtml;
+
+typedef signed char dfa_table[256];
+
+/* DFA tables declared in guess_ja.cpp */
+extern const dfa_table guess_eucj_st[];
+extern guess_arc guess_eucj_ar[7];
+extern const dfa_table guess_sjis_st[];
+extern guess_arc guess_sjis_ar[6];
+extern const dfa_table guess_utf8_st[];
+extern guess_arc guess_utf8_ar[11];
+
+namespace khtml {
+
+ class guess_dfa {
+ public:
+ const dfa_table *states;
+ const guess_arc *arcs;
+ int state;
+ double score;
+
+ guess_dfa (const dfa_table stable[], const guess_arc *atable) :
+ states(stable), arcs(atable)
+ {
+ state = 0;
+ score = 1.0;
+ }
+ };
+
+ class JapaneseCode
+ {
+ public:
+ enum Type {ASCII, JIS, EUC, SJIS, UNICODE, UTF8 };
+ enum Type guess_jp(const char* buf, int buflen);
+
+ JapaneseCode () {
+ eucj = new guess_dfa(guess_eucj_st, guess_eucj_ar);
+ sjis = new guess_dfa(guess_sjis_st, guess_sjis_ar);
+ utf8 = new guess_dfa(guess_utf8_st, guess_utf8_ar);
+ last_JIS_escape = false;
+ }
+
+ ~JapaneseCode () {
+ if (eucj) delete eucj;
+ if (sjis) delete sjis;
+ if (utf8) delete utf8;
+ }
+
+ protected:
+ guess_dfa *eucj;
+ guess_dfa *sjis;
+ guess_dfa *utf8;
+
+ bool last_JIS_escape;
+ };
+}
+
+#define DFA_NEXT(dfa, ch) \
+ do { \
+ int arc__; \
+ if (dfa->state >= 0) { \
+ arc__ = dfa->states[dfa->state][ch]; \
+ if (arc__ < 0) { \
+ dfa->state = -1; \
+ } else { \
+ dfa->state = dfa->arcs[arc__].next; \
+ dfa->score *= dfa->arcs[arc__].score; \
+ } \
+ } \
+ } while (0)
+
+#define DFA_ALIVE(dfa) (dfa->state >= 0)
+
+#endif /* GUESS_JA_H */
diff --git a/khtml/misc/helper.cpp b/khtml/misc/helper.cpp
new file mode 100644
index 000000000..eebba5015
--- /dev/null
+++ b/khtml/misc/helper.cpp
@@ -0,0 +1,144 @@
+/*
+ * This file is part of the CSS implementation for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) David Carson <dacarson@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#include "helper.h"
+#include "khtmllayout.h"
+#include <qmap.h>
+#include <qpainter.h>
+#include <dom/dom_string.h>
+#include <xml/dom_stringimpl.h>
+#include <rendering/render_object.h>
+#include <qptrlist.h>
+#include <kstaticdeleter.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <qtooltip.h>
+
+using namespace DOM;
+using namespace khtml;
+
+namespace khtml {
+ QPainter *printpainter;
+}
+
+void khtml::setPrintPainter( QPainter *printer )
+{
+ printpainter = printer;
+}
+
+
+double calcHue(double temp1, double temp2, double hueVal)
+{
+ if (hueVal < 0)
+ hueVal++;
+ else if (hueVal > 1)
+ hueVal--;
+ if (hueVal * 6 < 1)
+ return temp1 + (temp2 - temp1) * hueVal * 6;
+ if (hueVal * 2 < 1)
+ return temp2;
+ if (hueVal * 3 < 2)
+ return temp1 + (temp2 - temp1) * (2.0 / 3.0 - hueVal) * 6;
+ return temp1;
+}
+
+// Explanation of this algorithm can be found in the CSS3 Color Module
+// specification at http://www.w3.org/TR/css3-color/#hsl-color with further
+// explanation available at http://en.wikipedia.org/wiki/HSL_color_space
+
+// all values are in the range of 0 to 1.0
+QRgb khtml::qRgbaFromHsla(double h, double s, double l, double a)
+{
+ double temp2 = l < 0.5 ? l * (1.0 + s) : l + s - l * s;
+ double temp1 = 2.0 * l - temp2;
+
+ return qRgba(calcHue(temp1, temp2, h + 1.0 / 3.0) * 255, calcHue(temp1, temp2, h) * 255, calcHue(temp1, temp2, h - 1.0 / 3.0) * 255, a * 255);
+}
+
+/** finds out the background color of an element
+ * @param obj render object
+ * @return the background color. It is guaranteed that a valid color is returned.
+ */
+QColor khtml::retrieveBackgroundColor(const RenderObject *obj)
+{
+ QColor result;
+ while (!obj->isCanvas()) {
+ result = obj->style()->backgroundColor();
+ if (result.isValid()) return result;
+
+ obj = obj->container();
+ }/*wend*/
+
+ // everything transparent? Use base then.
+ return obj->style()->palette().active().base();
+}
+
+/** checks whether the given colors have enough contrast
+ * @returns @p true if contrast is ok.
+ */
+bool khtml::hasSufficientContrast(const QColor &c1, const QColor &c2)
+{
+// New version from Germain Garand, better suited for contrast measurement
+#if 1
+
+#define HUE_DISTANCE 40
+#define CONTRAST_DISTANCE 10
+
+ int h1, s1, v1, h2, s2, v2;
+ int hdist = -CONTRAST_DISTANCE;
+ c1.hsv(&h1,&s1,&v1);
+ c2.hsv(&h2,&s2,&v2);
+ if(h1!=-1 && h2!=-1) { // grey values have no hue
+ hdist = kAbs(h1-h2);
+ if (hdist > 180) hdist = 360-hdist;
+ if (hdist < HUE_DISTANCE) {
+ hdist -= HUE_DISTANCE;
+ // see if they are high key or low key colours
+ bool hk1 = h1>=45 && h1<=225;
+ bool hk2 = h2>=45 && h2<=225;
+ if (hk1 && hk2)
+ hdist = (5*hdist)/3;
+ else if (!hk1 && !hk2)
+ hdist = (7*hdist)/4;
+ }
+ hdist = kMin(hdist, HUE_DISTANCE*2);
+ }
+ return hdist + (kAbs(s1-s2)*128)/(160+kMin(s1,s2)) + kAbs(v1-v2) > CONTRAST_DISTANCE;
+
+#undef CONTRAST_DISTANCE
+#undef HUE_DISTANCE
+
+#else // orginal fast but primitive version by me (LS)
+
+// ### arbitrary value, to be adapted if necessary (LS)
+#define CONTRAST_DISTANCE 32
+
+ if (kAbs(c1.red() - c2.red()) > CONTRAST_DISTANCE) return true;
+ if (kAbs(c1.green() - c2.green()) > CONTRAST_DISTANCE) return true;
+ if (kAbs(c1.blue() - c2.blue()) > CONTRAST_DISTANCE) return true;
+
+ return false;
+
+#undef CONTRAST_DISTANCE
+
+#endif
+}
diff --git a/khtml/misc/helper.h b/khtml/misc/helper.h
new file mode 100644
index 000000000..984ddfc11
--- /dev/null
+++ b/khtml/misc/helper.h
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the CSS implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef html_helper_h
+#define html_helper_h
+
+#include <qcolor.h>
+class QPainter;
+#include <qfontmetrics.h>
+#include <qfont.h>
+
+
+
+namespace khtml
+{
+ class RenderObject;
+ const QRgb transparentColor = 0x00000000;
+ const QRgb invertedColor = 0x00000002;
+
+ extern QPainter *printpainter;
+ void setPrintPainter( QPainter *printer );
+
+ bool hasSufficientContrast(const QColor &c1, const QColor &c2);
+ QColor retrieveBackgroundColor(const RenderObject *obj);
+ QRgb qRgbaFromHsla(double h, double s, double l, double a);
+
+ //enumerator for findSelectionNode
+ enum FindSelectionResult { SelectionPointBefore,
+ SelectionPointAfter,
+ SelectionPointInside,
+ // the next two are only used inside one line in RenderText
+ // to get BiDi contexts right.
+ SelectionPointBeforeInLine,
+ SelectionPointAfterInLine };
+}
+
+#endif
diff --git a/khtml/misc/htmlattrs.c b/khtml/misc/htmlattrs.c
new file mode 100644
index 000000000..779792e71
--- /dev/null
+++ b/khtml/misc/htmlattrs.c
@@ -0,0 +1,1019 @@
+/* ANSI-C code produced by gperf version 3.0.3 */
+/* Command-line: gperf -c -a -L ANSI-C -P -G -D -E -C -o -t -k '*' -NfindAttr -Hhash_attr -Wwordlist_attr -Qspool_attr -s 2 htmlattrs.gperf */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646. */
+#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
+#endif
+
+#line 1 "htmlattrs.gperf"
+
+/* This file is automatically generated from
+#htmlattrs.in by makeattrs, do not edit */
+#include "htmlattrs.h"
+#line 6 "htmlattrs.gperf"
+struct attrs {
+ int name;
+ int id;
+};
+enum
+ {
+ TOTAL_KEYWORDS = 152,
+ MIN_WORD_LENGTH = 2,
+ MAX_WORD_LENGTH = 15,
+ MIN_HASH_VALUE = 3,
+ MAX_HASH_VALUE = 576
+ };
+
+/* maximum key range = 574, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+hash_attr (register const char *str, register unsigned int len)
+{
+ static const unsigned short asso_values[] =
+ {
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 5, 5, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 30, 10, 0,
+ 10, 5, 10, 15, 165, 40, 140, 80, 0, 25,
+ 70, 0, 5, 5, 0, 0, 10, 55, 70, 180,
+ 5, 90, 45, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577
+ };
+ register int hval = len;
+
+ switch (hval)
+ {
+ default:
+ hval += asso_values[(unsigned char)str[14]];
+ /*FALLTHROUGH*/
+ case 14:
+ hval += asso_values[(unsigned char)str[13]];
+ /*FALLTHROUGH*/
+ case 13:
+ hval += asso_values[(unsigned char)str[12]];
+ /*FALLTHROUGH*/
+ case 12:
+ hval += asso_values[(unsigned char)str[11]];
+ /*FALLTHROUGH*/
+ case 11:
+ hval += asso_values[(unsigned char)str[10]];
+ /*FALLTHROUGH*/
+ case 10:
+ hval += asso_values[(unsigned char)str[9]];
+ /*FALLTHROUGH*/
+ case 9:
+ hval += asso_values[(unsigned char)str[8]];
+ /*FALLTHROUGH*/
+ case 8:
+ hval += asso_values[(unsigned char)str[7]];
+ /*FALLTHROUGH*/
+ case 7:
+ hval += asso_values[(unsigned char)str[6]];
+ /*FALLTHROUGH*/
+ case 6:
+ hval += asso_values[(unsigned char)str[5]];
+ /*FALLTHROUGH*/
+ case 5:
+ hval += asso_values[(unsigned char)str[4]];
+ /*FALLTHROUGH*/
+ case 4:
+ hval += asso_values[(unsigned char)str[3]];
+ /*FALLTHROUGH*/
+ case 3:
+ hval += asso_values[(unsigned char)str[2]];
+ /*FALLTHROUGH*/
+ case 2:
+ hval += asso_values[(unsigned char)str[1]+1];
+ /*FALLTHROUGH*/
+ case 1:
+ hval += asso_values[(unsigned char)str[0]];
+ break;
+ }
+ return hval;
+}
+
+struct spool_attr_t
+ {
+ char spool_attr_str0[sizeof("src")];
+ char spool_attr_str1[sizeof("onscroll")];
+ char spool_attr_str2[sizeof("cols")];
+ char spool_attr_str3[sizeof("color")];
+ char spool_attr_str4[sizeof("onerror")];
+ char spool_attr_str5[sizeof("rel")];
+ char spool_attr_str6[sizeof("loop")];
+ char spool_attr_str7[sizeof("for")];
+ char spool_attr_str8[sizeof("coords")];
+ char spool_attr_str9[sizeof("top")];
+ char spool_attr_str10[sizeof("code")];
+ char spool_attr_str11[sizeof("scope")];
+ char spool_attr_str12[sizeof("onreset")];
+ char spool_attr_str13[sizeof("onselect")];
+ char spool_attr_str14[sizeof("face")];
+ char spool_attr_str15[sizeof("label")];
+ char spool_attr_str16[sizeof("left")];
+ char spool_attr_str17[sizeof("border")];
+ char spool_attr_str18[sizeof("text")];
+ char spool_attr_str19[sizeof("defer")];
+ char spool_attr_str20[sizeof("bordercolor")];
+ char spool_attr_str21[sizeof("abbr")];
+ char spool_attr_str22[sizeof("pagex")];
+ char spool_attr_str23[sizeof("onload")];
+ char spool_attr_str24[sizeof("id")];
+ char spool_attr_str25[sizeof("selected")];
+ char spool_attr_str26[sizeof("prompt")];
+ char spool_attr_str27[sizeof("target")];
+ char spool_attr_str28[sizeof("onabort")];
+ char spool_attr_str29[sizeof("class")];
+ char spool_attr_str30[sizeof("declare")];
+ char spool_attr_str31[sizeof("data")];
+ char spool_attr_str32[sizeof("clear")];
+ char spool_attr_str33[sizeof("accept")];
+ char spool_attr_str34[sizeof("profile")];
+ char spool_attr_str35[sizeof("alt")];
+ char spool_attr_str36[sizeof("type")];
+ char spool_attr_str37[sizeof("onblur")];
+ char spool_attr_str38[sizeof("onfocus")];
+ char spool_attr_str39[sizeof("codebase")];
+ char spool_attr_str40[sizeof("char")];
+ char spool_attr_str41[sizeof("frame")];
+ char spool_attr_str42[sizeof("rules")];
+ char spool_attr_str43[sizeof("compact")];
+ char spool_attr_str44[sizeof("rev")];
+ char spool_attr_str45[sizeof("shape")];
+ char spool_attr_str46[sizeof("charset")];
+ char spool_attr_str47[sizeof("charoff")];
+ char spool_attr_str48[sizeof("lang")];
+ char spool_attr_str49[sizeof("start")];
+ char spool_attr_str50[sizeof("onresize")];
+ char spool_attr_str51[sizeof("truespeed")];
+ char spool_attr_str52[sizeof("frameborder")];
+ char spool_attr_str53[sizeof("span")];
+ char spool_attr_str54[sizeof("classid")];
+ char spool_attr_str55[sizeof("longdesc")];
+ char spool_attr_str56[sizeof("name")];
+ char spool_attr_str57[sizeof("ismap")];
+ char spool_attr_str58[sizeof("colspan")];
+ char spool_attr_str59[sizeof("media")];
+ char spool_attr_str60[sizeof("enctype")];
+ char spool_attr_str61[sizeof("datetime")];
+ char spool_attr_str62[sizeof("vspace")];
+ char spool_attr_str63[sizeof("onclick")];
+ char spool_attr_str64[sizeof("pagey")];
+ char spool_attr_str65[sizeof("usemap")];
+ char spool_attr_str66[sizeof("codetype")];
+ char spool_attr_str67[sizeof("scrolling")];
+ char spool_attr_str68[sizeof("value")];
+ char spool_attr_str69[sizeof("checked")];
+ char spool_attr_str70[sizeof("onsubmit")];
+ char spool_attr_str71[sizeof("ondblclick")];
+ char spool_attr_str72[sizeof("dir")];
+ char spool_attr_str73[sizeof("onmouseup")];
+ char spool_attr_str74[sizeof("style")];
+ char spool_attr_str75[sizeof("scrolldelay")];
+ char spool_attr_str76[sizeof("cite")];
+ char spool_attr_str77[sizeof("onmouseout")];
+ char spool_attr_str78[sizeof("object")];
+ char spool_attr_str79[sizeof("multiple")];
+ char spool_attr_str80[sizeof("axis")];
+ char spool_attr_str81[sizeof("action")];
+ char spool_attr_str82[sizeof("tabindex")];
+ char spool_attr_str83[sizeof("title")];
+ char spool_attr_str84[sizeof("onmouseover")];
+ char spool_attr_str85[sizeof("autocomplete")];
+ char spool_attr_str86[sizeof("onunload")];
+ char spool_attr_str87[sizeof("challenge")];
+ char spool_attr_str88[sizeof("plain")];
+ char spool_attr_str89[sizeof("content")];
+ char spool_attr_str90[sizeof("noresize")];
+ char spool_attr_str91[sizeof("cellspacing")];
+ char spool_attr_str92[sizeof("bgcolor")];
+ char spool_attr_str93[sizeof("href")];
+ char spool_attr_str94[sizeof("align")];
+ char spool_attr_str95[sizeof("nosave")];
+ char spool_attr_str96[sizeof("z-index")];
+ char spool_attr_str97[sizeof("rows")];
+ char spool_attr_str98[sizeof("oversrc")];
+ char spool_attr_str99[sizeof("size")];
+ char spool_attr_str100[sizeof("onkeypress")];
+ char spool_attr_str101[sizeof("onmousemove")];
+ char spool_attr_str102[sizeof("version")];
+ char spool_attr_str103[sizeof("cellpadding")];
+ char spool_attr_str104[sizeof("language")];
+ char spool_attr_str105[sizeof("topmargin")];
+ char spool_attr_str106[sizeof("valign")];
+ char spool_attr_str107[sizeof("scrollamount")];
+ char spool_attr_str108[sizeof("disabled")];
+ char spool_attr_str109[sizeof("scheme")];
+ char spool_attr_str110[sizeof("readonly")];
+ char spool_attr_str111[sizeof("wrap")];
+ char spool_attr_str112[sizeof("leftmargin")];
+ char spool_attr_str113[sizeof("hspace")];
+ char spool_attr_str114[sizeof("method")];
+ char spool_attr_str115[sizeof("headers")];
+ char spool_attr_str116[sizeof("accesskey")];
+ char spool_attr_str117[sizeof("onkeyup")];
+ char spool_attr_str118[sizeof("summary")];
+ char spool_attr_str119[sizeof("html")];
+ char spool_attr_str120[sizeof("alink")];
+ char spool_attr_str121[sizeof("bgproperties")];
+ char spool_attr_str122[sizeof("valuetype")];
+ char spool_attr_str123[sizeof("background")];
+ char spool_attr_str124[sizeof("nohref")];
+ char spool_attr_str125[sizeof("standby")];
+ char spool_attr_str126[sizeof("pluginurl")];
+ char spool_attr_str127[sizeof("pluginpage")];
+ char spool_attr_str128[sizeof("pluginspage")];
+ char spool_attr_str129[sizeof("direction")];
+ char spool_attr_str130[sizeof("accept-charset")];
+ char spool_attr_str131[sizeof("vlink")];
+ char spool_attr_str132[sizeof("noshade")];
+ char spool_attr_str133[sizeof("onchange")];
+ char spool_attr_str134[sizeof("link")];
+ char spool_attr_str135[sizeof("contenteditable")];
+ char spool_attr_str136[sizeof("nowrap")];
+ char spool_attr_str137[sizeof("rowspan")];
+ char spool_attr_str138[sizeof("hreflang")];
+ char spool_attr_str139[sizeof("maxlength")];
+ char spool_attr_str140[sizeof("archive")];
+ char spool_attr_str141[sizeof("behavior")];
+ char spool_attr_str142[sizeof("onmousedown")];
+ char spool_attr_str143[sizeof("hidden")];
+ char spool_attr_str144[sizeof("height")];
+ char spool_attr_str145[sizeof("http-equiv")];
+ char spool_attr_str146[sizeof("onkeydown")];
+ char spool_attr_str147[sizeof("visibility")];
+ char spool_attr_str148[sizeof("unknown")];
+ char spool_attr_str149[sizeof("width")];
+ char spool_attr_str150[sizeof("marginheight")];
+ char spool_attr_str151[sizeof("marginwidth")];
+ };
+static const struct spool_attr_t spool_attr_contents =
+ {
+ "src",
+ "onscroll",
+ "cols",
+ "color",
+ "onerror",
+ "rel",
+ "loop",
+ "for",
+ "coords",
+ "top",
+ "code",
+ "scope",
+ "onreset",
+ "onselect",
+ "face",
+ "label",
+ "left",
+ "border",
+ "text",
+ "defer",
+ "bordercolor",
+ "abbr",
+ "pagex",
+ "onload",
+ "id",
+ "selected",
+ "prompt",
+ "target",
+ "onabort",
+ "class",
+ "declare",
+ "data",
+ "clear",
+ "accept",
+ "profile",
+ "alt",
+ "type",
+ "onblur",
+ "onfocus",
+ "codebase",
+ "char",
+ "frame",
+ "rules",
+ "compact",
+ "rev",
+ "shape",
+ "charset",
+ "charoff",
+ "lang",
+ "start",
+ "onresize",
+ "truespeed",
+ "frameborder",
+ "span",
+ "classid",
+ "longdesc",
+ "name",
+ "ismap",
+ "colspan",
+ "media",
+ "enctype",
+ "datetime",
+ "vspace",
+ "onclick",
+ "pagey",
+ "usemap",
+ "codetype",
+ "scrolling",
+ "value",
+ "checked",
+ "onsubmit",
+ "ondblclick",
+ "dir",
+ "onmouseup",
+ "style",
+ "scrolldelay",
+ "cite",
+ "onmouseout",
+ "object",
+ "multiple",
+ "axis",
+ "action",
+ "tabindex",
+ "title",
+ "onmouseover",
+ "autocomplete",
+ "onunload",
+ "challenge",
+ "plain",
+ "content",
+ "noresize",
+ "cellspacing",
+ "bgcolor",
+ "href",
+ "align",
+ "nosave",
+ "z-index",
+ "rows",
+ "oversrc",
+ "size",
+ "onkeypress",
+ "onmousemove",
+ "version",
+ "cellpadding",
+ "language",
+ "topmargin",
+ "valign",
+ "scrollamount",
+ "disabled",
+ "scheme",
+ "readonly",
+ "wrap",
+ "leftmargin",
+ "hspace",
+ "method",
+ "headers",
+ "accesskey",
+ "onkeyup",
+ "summary",
+ "html",
+ "alink",
+ "bgproperties",
+ "valuetype",
+ "background",
+ "nohref",
+ "standby",
+ "pluginurl",
+ "pluginpage",
+ "pluginspage",
+ "direction",
+ "accept-charset",
+ "vlink",
+ "noshade",
+ "onchange",
+ "link",
+ "contenteditable",
+ "nowrap",
+ "rowspan",
+ "hreflang",
+ "maxlength",
+ "archive",
+ "behavior",
+ "onmousedown",
+ "hidden",
+ "height",
+ "http-equiv",
+ "onkeydown",
+ "visibility",
+ "unknown",
+ "width",
+ "marginheight",
+ "marginwidth"
+ };
+#define spool_attr ((const char *) &spool_attr_contents)
+
+static const struct attrs wordlist_attr[] =
+ {
+#line 157 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str0, ATTR_SRC},
+#line 151 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str1, ATTR_ONSCROLL},
+#line 33 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str2, ATTR_COLS},
+#line 32 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str3, ATTR_COLOR},
+#line 72 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str4, ATTR_ONERROR},
+#line 82 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str5, ATTR_REL},
+#line 59 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str6, ATTR_LOOP},
+#line 127 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str7, ATTR_FOR},
+#line 37 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str8, ATTR_COORDS},
+#line 100 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str9, ATTR_TOP},
+#line 122 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str10, ATTR_CODE},
+#line 87 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str11, ATTR_SCOPE},
+#line 149 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str12, ATTR_ONRESET},
+#line 150 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str13, ATTR_ONSELECT},
+#line 44 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str14, ATTR_FACE},
+#line 131 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str15, ATTR_LABEL},
+#line 56 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str16, ATTR_LEFT},
+#line 21 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str17, ATTR_BORDER},
+#line 99 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str18, ATTR_TEXT},
+#line 39 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str19, ATTR_DEFER},
+#line 22 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str20, ATTR_BORDERCOLOR},
+#line 114 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str21, ATTR_ABBR},
+#line 75 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str22, ATTR_PAGEX},
+#line 143 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str23, ATTR_ONLOAD},
+#line 130 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str24, ATTR_ID},
+#line 91 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str25, ATTR_SELECTED},
+#line 155 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str26, ATTR_PROMPT},
+#line 98 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str27, ATTR_TARGET},
+#line 71 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str28, ATTR_ONABORT},
+#line 120 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str29, ATTR_CLASS},
+#line 38 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str30, ATTR_DECLARE},
+#line 125 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str31, ATTR_DATA},
+#line 30 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str32, ATTR_CLEAR},
+#line 12 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str33, ATTR_ACCEPT},
+#line 154 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str34, ATTR_PROFILE},
+#line 116 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str35, ATTR_ALT},
+#line 103 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str36, ATTR_TYPE},
+#line 135 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str37, ATTR_ONBLUR},
+#line 139 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str38, ATTR_ONFOCUS},
+#line 123 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str39, ATTR_CODEBASE},
+#line 25 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str40, ATTR_CHAR},
+#line 45 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str41, ATTR_FRAME},
+#line 86 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str42, ATTR_RULES},
+#line 35 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str43, ATTR_COMPACT},
+#line 83 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str44, ATTR_REV},
+#line 92 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str45, ATTR_SHAPE},
+#line 28 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str46, ATTR_CHARSET},
+#line 27 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str47, ATTR_CHAROFF},
+#line 54 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str48, ATTR_LANG},
+#line 95 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str49, ATTR_START},
+#line 73 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str50, ATTR_ONRESIZE},
+#line 102 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str51, ATTR_TRUESPEED},
+#line 46 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str52, ATTR_FRAMEBORDER},
+#line 94 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str53, ATTR_SPAN},
+#line 121 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str54, ATTR_CLASSID},
+#line 132 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str55, ATTR_LONGDESC},
+#line 133 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str56, ATTR_NAME},
+#line 53 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str57, ATTR_ISMAP},
+#line 34 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str58, ATTR_COLSPAN},
+#line 63 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str59, ATTR_MEDIA},
+#line 43 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str60, ATTR_ENCTYPE},
+#line 126 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str61, ATTR_DATETIME},
+#line 110 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str62, ATTR_VSPACE},
+#line 137 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str63, ATTR_ONCLICK},
+#line 76 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str64, ATTR_PAGEY},
+#line 161 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str65, ATTR_USEMAP},
+#line 31 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str66, ATTR_CODETYPE},
+#line 90 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str67, ATTR_SCROLLING},
+#line 162 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str68, ATTR_VALUE},
+#line 29 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str69, ATTR_CHECKED},
+#line 152 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str70, ATTR_ONSUBMIT},
+#line 138 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str71, ATTR_ONDBLCLICK},
+#line 40 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str72, ATTR_DIR},
+#line 148 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str73, ATTR_ONMOUSEUP},
+#line 96 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str74, ATTR_STYLE},
+#line 89 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str75, ATTR_SCROLLDELAY},
+#line 119 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str76, ATTR_CITE},
+#line 146 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str77, ATTR_ONMOUSEOUT},
+#line 134 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str78, ATTR_OBJECT},
+#line 65 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str79, ATTR_MULTIPLE},
+#line 17 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str80, ATTR_AXIS},
+#line 115 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str81, ATTR_ACTION},
+#line 97 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str82, ATTR_TABINDEX},
+#line 160 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str83, ATTR_TITLE},
+#line 147 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str84, ATTR_ONMOUSEOVER},
+#line 16 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str85, ATTR_AUTOCOMPLETE},
+#line 153 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str86, ATTR_ONUNLOAD},
+#line 26 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str87, ATTR_CHALLENGE},
+#line 77 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str88, ATTR_PLAIN},
+#line 124 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str89, ATTR_CONTENT},
+#line 67 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str90, ATTR_NORESIZE},
+#line 24 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str91, ATTR_CELLSPACING},
+#line 19 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str92, ATTR_BGCOLOR},
+#line 129 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str93, ATTR_HREF},
+#line 14 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str94, ATTR_ALIGN},
+#line 68 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str95, ATTR_NOSAVE},
+#line 113 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str96, ATTR_Z_INDEX},
+#line 84 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str97, ATTR_ROWS},
+#line 74 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str98, ATTR_OVERSRC},
+#line 93 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str99, ATTR_SIZE},
+#line 141 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str100, ATTR_ONKEYPRESS},
+#line 145 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str101, ATTR_ONMOUSEMOVE},
+#line 107 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str102, ATTR_VERSION},
+#line 23 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str103, ATTR_CELLPADDING},
+#line 55 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str104, ATTR_LANGUAGE},
+#line 101 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str105, ATTR_TOPMARGIN},
+#line 105 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str106, ATTR_VALIGN},
+#line 88 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str107, ATTR_SCROLLAMOUNT},
+#line 42 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str108, ATTR_DISABLED},
+#line 156 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str109, ATTR_SCHEME},
+#line 81 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str110, ATTR_READONLY},
+#line 112 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str111, ATTR_WRAP},
+#line 57 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str112, ATTR_LEFTMARGIN},
+#line 50 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str113, ATTR_HSPACE},
+#line 64 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str114, ATTR_METHOD},
+#line 128 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str115, ATTR_HEADERS},
+#line 13 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str116, ATTR_ACCESSKEY},
+#line 142 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str117, ATTR_ONKEYUP},
+#line 159 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str118, ATTR_SUMMARY},
+#line 51 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str119, ATTR_HTML},
+#line 15 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str120, ATTR_ALINK},
+#line 20 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str121, ATTR_BGPROPERTIES},
+#line 106 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str122, ATTR_VALUETYPE},
+#line 118 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str123, ATTR_BACKGROUND},
+#line 66 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str124, ATTR_NOHREF},
+#line 158 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str125, ATTR_STANDBY},
+#line 80 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str126, ATTR_PLUGINURL},
+#line 78 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str127, ATTR_PLUGINPAGE},
+#line 79 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str128, ATTR_PLUGINSPAGE},
+#line 41 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str129, ATTR_DIRECTION},
+#line 11 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str130, ATTR_ACCEPT_CHARSET},
+#line 109 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str131, ATTR_VLINK},
+#line 69 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str132, ATTR_NOSHADE},
+#line 136 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str133, ATTR_ONCHANGE},
+#line 58 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str134, ATTR_LINK},
+#line 36 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str135, ATTR_CONTENTEDITABLE},
+#line 70 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str136, ATTR_NOWRAP},
+#line 85 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str137, ATTR_ROWSPAN},
+#line 49 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str138, ATTR_HREFLANG},
+#line 62 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str139, ATTR_MAXLENGTH},
+#line 117 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str140, ATTR_ARCHIVE},
+#line 18 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str141, ATTR_BEHAVIOR},
+#line 144 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str142, ATTR_ONMOUSEDOWN},
+#line 48 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str143, ATTR_HIDDEN},
+#line 47 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str144, ATTR_HEIGHT},
+#line 52 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str145, ATTR_HTTP_EQUIV},
+#line 140 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str146, ATTR_ONKEYDOWN},
+#line 108 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str147, ATTR_VISIBILITY},
+#line 104 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str148, ATTR_UNKNOWN},
+#line 111 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str149, ATTR_WIDTH},
+#line 60 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str150, ATTR_MARGINHEIGHT},
+#line 61 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str151, ATTR_MARGINWIDTH}
+ };
+
+static const short lookup[] =
+ {
+ -1, -1, -1, 0, -1, -1, -1, -1, 1, 2,
+ 3, -1, 4, 5, 6, -1, -1, -1, 7, -1,
+ -1, 8, -1, 9, 10, 11, -1, 12, 13, 14,
+ 15, -1, -1, -1, 16, -1, 17, -1, -1, 18,
+ 19, 20, -1, -1, 21, 22, 23, 24, 25, -1,
+ -1, 26, -1, -1, -1, -1, 27, 28, -1, -1,
+ 29, -1, 30, -1, 31, 32, 33, 34, 35, 36,
+ -1, 37, 38, 39, 40, 41, -1, -1, -1, -1,
+ 42, -1, 43, 44, -1, 45, -1, -1, -1, -1,
+ -1, -1, 46, -1, -1, -1, -1, 47, -1, 48,
+ 49, -1, -1, 50, 51, -1, 52, -1, -1, 53,
+ -1, -1, 54, 55, 56, 57, -1, 58, -1, -1,
+ 59, -1, 60, 61, -1, -1, 62, 63, -1, -1,
+ 64, -1, -1, -1, -1, -1, 65, -1, 66, -1,
+ -1, -1, -1, -1, 67, 68, -1, 69, 70, -1,
+ 71, -1, -1, 72, 73, 74, 75, -1, -1, 76,
+ 77, 78, -1, 79, 80, -1, 81, -1, 82, -1,
+ 83, 84, 85, 86, 87, 88, -1, 89, 90, -1,
+ -1, 91, 92, -1, 93, 94, 95, 96, -1, 97,
+ -1, -1, 98, -1, 99, 100, 101, 102, -1, -1,
+ -1, 103, -1, -1, -1, -1, -1, -1, 104, 105,
+ -1, 106, 107, 108, -1, -1, 109, -1, 110, 111,
+ 112, 113, -1, -1, -1, -1, 114, 115, -1, 116,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 117, -1, -1, -1, -1, 118, -1, 119,
+ 120, -1, -1, -1, -1, -1, -1, 121, -1, 122,
+ 123, 124, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 125, -1, 126, 127, 128, -1, -1, -1,
+ -1, -1, -1, -1, 129, -1, -1, -1, -1, 130,
+ 131, -1, 132, 133, 134, 135, 136, 137, -1, -1,
+ -1, -1, -1, 138, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 139, -1, -1, 140, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 141, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 142, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 143, -1, -1, -1,
+ -1, 144, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 145, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 146, -1, -1, -1, -1, -1,
+ 147, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 148, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 149, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 150, -1, -1, -1, 151
+ };
+
+#ifdef __GNUC__
+__inline
+#ifdef __GNUC_STDC_INLINE__
+__attribute__ ((__gnu_inline__))
+#endif
+#endif
+const struct attrs *
+findAttr (register const char *str, register unsigned int len)
+{
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ register int key = hash_attr (str, len);
+
+ if (key <= MAX_HASH_VALUE && key >= 0)
+ {
+ register int index = lookup[key];
+
+ if (index >= 0)
+ {
+ register const char *s = wordlist_attr[index].name + spool_attr;
+
+ if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
+ return &wordlist_attr[index];
+ }
+ }
+ }
+ return 0;
+}
+#line 163 "htmlattrs.gperf"
+
+
+
+static const unsigned short attrList[] = {
+ 65535,
+ 145,
+ 33,
+ 116,
+ 94,
+ 120,
+ 85,
+ 80,
+ 141,
+ 92,
+ 121,
+ 17,
+ 20,
+ 103,
+ 91,
+ 40,
+ 87,
+ 47,
+ 46,
+ 69,
+ 32,
+ 66,
+ 3,
+ 2,
+ 58,
+ 43,
+ 135,
+ 8,
+ 30,
+ 19,
+ 72,
+ 129,
+ 108,
+ 60,
+ 14,
+ 41,
+ 52,
+ 144,
+ 143,
+ 138,
+ 113,
+ 119,
+ 145,
+ 57,
+ 48,
+ 104,
+ 16,
+ 112,
+ 134,
+ 6,
+ 150,
+ 151,
+ 139,
+ 59,
+ 114,
+ 79,
+ 124,
+ 90,
+ 95,
+ 132,
+ 136,
+ 28,
+ 4,
+ 50,
+ 98,
+ 22,
+ 64,
+ 88,
+ 127,
+ 128,
+ 126,
+ 110,
+ 5,
+ 44,
+ 97,
+ 137,
+ 42,
+ 11,
+ 107,
+ 75,
+ 67,
+ 25,
+ 45,
+ 99,
+ 53,
+ 49,
+ 74,
+ 82,
+ 27,
+ 18,
+ 9,
+ 105,
+ 51,
+ 36,
+ 148,
+ 106,
+ 122,
+ 102,
+ 147,
+ 131,
+ 62,
+ 149,
+ 111,
+ 145,
+ 21,
+ 81,
+ 35,
+ 140,
+ 123,
+ 76,
+ 29,
+ 54,
+ 10,
+ 39,
+ 89,
+ 31,
+ 61,
+ 7,
+ 115,
+ 93,
+ 24,
+ 15,
+ 55,
+ 56,
+ 78,
+ 37,
+ 133,
+ 63,
+ 71,
+ 38,
+ 146,
+ 100,
+ 117,
+ 23,
+ 142,
+ 101,
+ 77,
+ 84,
+ 73,
+ 12,
+ 13,
+ 1,
+ 70,
+ 86,
+ 34,
+ 26,
+ 109,
+ 0,
+ 125,
+ 118,
+ 83,
+ 65,
+ 68,
+ 65535
+};
+
+const char* KDE_NO_EXPORT getAttrName(unsigned short id)
+{
+ if (!id || id > TOTAL_KEYWORDS) return "";
+ return spool_attr + wordlist_attr[attrList[id]].name;
+}
diff --git a/khtml/misc/htmlattrs.h b/khtml/misc/htmlattrs.h
new file mode 100644
index 000000000..d9aaff067
--- /dev/null
+++ b/khtml/misc/htmlattrs.h
@@ -0,0 +1,168 @@
+/* This file is automatically generated from
+htmlattrs.in by makeattrs, do not edit */
+/* Copyright 1999 Lars Knoll */
+
+#ifndef HTML_ATTRS_H
+#define HTML_ATTRS_H
+
+#include "dom/dom_string.h"
+#include <kdemacros.h>
+using namespace DOM;
+
+#define ATTR_ACCEPT_CHARSET 1
+#define ATTR_ACCEPT 2
+#define ATTR_ACCESSKEY 3
+#define ATTR_ALIGN 4
+#define ATTR_ALINK 5
+#define ATTR_AUTOCOMPLETE 6
+#define ATTR_AXIS 7
+#define ATTR_BEHAVIOR 8
+#define ATTR_BGCOLOR 9
+#define ATTR_BGPROPERTIES 10
+#define ATTR_BORDER 11
+#define ATTR_BORDERCOLOR 12
+#define ATTR_CELLPADDING 13
+#define ATTR_CELLSPACING 14
+#define ATTR_CHAR 15
+#define ATTR_CHALLENGE 16
+#define ATTR_CHAROFF 17
+#define ATTR_CHARSET 18
+#define ATTR_CHECKED 19
+#define ATTR_CLEAR 20
+#define ATTR_CODETYPE 21
+#define ATTR_COLOR 22
+#define ATTR_COLS 23
+#define ATTR_COLSPAN 24
+#define ATTR_COMPACT 25
+#define ATTR_CONTENTEDITABLE 26
+#define ATTR_COORDS 27
+#define ATTR_DECLARE 28
+#define ATTR_DEFER 29
+#define ATTR_DIR 30
+#define ATTR_DIRECTION 31
+#define ATTR_DISABLED 32
+#define ATTR_ENCTYPE 33
+#define ATTR_FACE 34
+#define ATTR_FRAME 35
+#define ATTR_FRAMEBORDER 36
+#define ATTR_HEIGHT 37
+#define ATTR_HIDDEN 38
+#define ATTR_HREFLANG 39
+#define ATTR_HSPACE 40
+#define ATTR_HTML 41
+#define ATTR_HTTP_EQUIV 42
+#define ATTR_ISMAP 43
+#define ATTR_LANG 44
+#define ATTR_LANGUAGE 45
+#define ATTR_LEFT 46
+#define ATTR_LEFTMARGIN 47
+#define ATTR_LINK 48
+#define ATTR_LOOP 49
+#define ATTR_MARGINHEIGHT 50
+#define ATTR_MARGINWIDTH 51
+#define ATTR_MAXLENGTH 52
+#define ATTR_MEDIA 53
+#define ATTR_METHOD 54
+#define ATTR_MULTIPLE 55
+#define ATTR_NOHREF 56
+#define ATTR_NORESIZE 57
+#define ATTR_NOSAVE 58
+#define ATTR_NOSHADE 59
+#define ATTR_NOWRAP 60
+#define ATTR_ONABORT 61
+#define ATTR_ONERROR 62
+#define ATTR_ONRESIZE 63
+#define ATTR_OVERSRC 64
+#define ATTR_PAGEX 65
+#define ATTR_PAGEY 66
+#define ATTR_PLAIN 67
+#define ATTR_PLUGINPAGE 68
+#define ATTR_PLUGINSPAGE 69
+#define ATTR_PLUGINURL 70
+#define ATTR_READONLY 71
+#define ATTR_REL 72
+#define ATTR_REV 73
+#define ATTR_ROWS 74
+#define ATTR_ROWSPAN 75
+#define ATTR_RULES 76
+#define ATTR_SCOPE 77
+#define ATTR_SCROLLAMOUNT 78
+#define ATTR_SCROLLDELAY 79
+#define ATTR_SCROLLING 80
+#define ATTR_SELECTED 81
+#define ATTR_SHAPE 82
+#define ATTR_SIZE 83
+#define ATTR_SPAN 84
+#define ATTR_START 85
+#define ATTR_STYLE 86
+#define ATTR_TABINDEX 87
+#define ATTR_TARGET 88
+#define ATTR_TEXT 89
+#define ATTR_TOP 90
+#define ATTR_TOPMARGIN 91
+#define ATTR_TRUESPEED 92
+#define ATTR_TYPE 93
+#define ATTR_UNKNOWN 94
+#define ATTR_VALIGN 95
+#define ATTR_VALUETYPE 96
+#define ATTR_VERSION 97
+#define ATTR_VISIBILITY 98
+#define ATTR_VLINK 99
+#define ATTR_VSPACE 100
+#define ATTR_WIDTH 101
+#define ATTR_WRAP 102
+#define ATTR_Z_INDEX 103
+#define ATTR_ABBR 104
+#define ATTR_ACTION 105
+#define ATTR_ALT 106
+#define ATTR_ARCHIVE 107
+#define ATTR_BACKGROUND 108
+#define ATTR_CITE 109
+#define ATTR_CLASS 110
+#define ATTR_CLASSID 111
+#define ATTR_CODE 112
+#define ATTR_CODEBASE 113
+#define ATTR_CONTENT 114
+#define ATTR_DATA 115
+#define ATTR_DATETIME 116
+#define ATTR_FOR 117
+#define ATTR_HEADERS 118
+#define ATTR_HREF 119
+#define ATTR_ID 120
+#define ATTR_LABEL 121
+#define ATTR_LONGDESC 122
+#define ATTR_NAME 123
+#define ATTR_OBJECT 124
+#define ATTR_ONBLUR 125
+#define ATTR_ONCHANGE 126
+#define ATTR_ONCLICK 127
+#define ATTR_ONDBLCLICK 128
+#define ATTR_ONFOCUS 129
+#define ATTR_ONKEYDOWN 130
+#define ATTR_ONKEYPRESS 131
+#define ATTR_ONKEYUP 132
+#define ATTR_ONLOAD 133
+#define ATTR_ONMOUSEDOWN 134
+#define ATTR_ONMOUSEMOVE 135
+#define ATTR_ONMOUSEOUT 136
+#define ATTR_ONMOUSEOVER 137
+#define ATTR_ONMOUSEUP 138
+#define ATTR_ONRESET 139
+#define ATTR_ONSELECT 140
+#define ATTR_ONSCROLL 141
+#define ATTR_ONSUBMIT 142
+#define ATTR_ONUNLOAD 143
+#define ATTR_PROFILE 144
+#define ATTR_PROMPT 145
+#define ATTR_SCHEME 146
+#define ATTR_SRC 147
+#define ATTR_STANDBY 148
+#define ATTR_SUMMARY 149
+#define ATTR_TITLE 150
+#define ATTR_USEMAP 151
+#define ATTR_VALUE 152
+#define ATTR_LAST_ATTR 152
+#define ATTR_LAST_CI_ATTR 103
+const char* getAttrName(unsigned short id) KDE_NO_EXPORT;
+
+#endif
diff --git a/khtml/misc/htmlattrs.in b/khtml/misc/htmlattrs.in
new file mode 100644
index 000000000..263b2fd7b
--- /dev/null
+++ b/khtml/misc/htmlattrs.in
@@ -0,0 +1,157 @@
+# First, list attributes with a case-insensitive value
+accept-charset
+accept
+accesskey
+align
+alink
+autocomplete
+axis
+behavior
+bgcolor
+bgproperties
+border
+bordercolor
+cellpadding
+cellspacing
+char
+challenge
+charoff
+charset
+checked
+clear
+codetype
+color
+cols
+colspan
+compact
+contenteditable
+coords
+declare
+defer
+dir
+direction
+disabled
+enctype
+face
+frame
+frameborder
+height
+hidden
+hreflang
+hspace
+html
+http-equiv
+ismap
+lang
+language
+left
+leftmargin
+link
+loop
+marginheight
+marginwidth
+maxlength
+media
+method
+multiple
+nohref
+noresize
+nosave
+noshade
+nowrap
+onabort
+onerror
+onresize
+oversrc
+pagex
+pagey
+plain
+pluginpage
+pluginspage
+pluginurl
+readonly
+rel
+rev
+rows
+rowspan
+rules
+scope
+scrollamount
+scrolldelay
+scrolling
+selected
+shape
+size
+span
+start
+style
+tabindex
+target
+text
+top
+topmargin
+truespeed
+type
+unknown
+valign
+valuetype
+version
+visibility
+vlink
+vspace
+width
+wrap
+z-index
+END_CI_ATTRIBUTES
+
+# Then attributes listed as [CS] and [CT] in the HTML specification,
+# which value is to be treated case sensitively.
+abbr
+action
+alt
+archive
+background
+cite
+class
+classid
+code
+codebase
+content
+data
+datetime
+for
+headers
+href
+id
+label
+longdesc
+name
+object
+onblur
+onchange
+onclick
+ondblclick
+onfocus
+onkeydown
+onkeypress
+onkeyup
+onload
+onmousedown
+onmousemove
+onmouseout
+onmouseover
+onmouseup
+onreset
+onselect
+onscroll
+onsubmit
+onunload
+profile
+prompt
+scheme
+src
+standby
+summary
+title
+usemap
+value
diff --git a/khtml/misc/htmlhashes.cpp b/khtml/misc/htmlhashes.cpp
new file mode 100644
index 000000000..593c1ce96
--- /dev/null
+++ b/khtml/misc/htmlhashes.cpp
@@ -0,0 +1,45 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 1999 Lars Knoll (knoll@mpi-hd.mpg.de)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <kglobal.h>
+
+#include "htmlhashes.h"
+#include "htmltags.c"
+#include "htmlattrs.c"
+
+int khtml::getTagID(const char *tagStr, int len)
+{
+ const struct tags *tagPtr = findTag(tagStr, len);
+ if (!tagPtr)
+ return 0;
+
+ return tagPtr->id;
+}
+
+int khtml::getAttrID(const char *tagStr, int len)
+{
+ const struct attrs *tagPtr = findAttr(tagStr, len);
+ if (!tagPtr)
+ return 0;
+
+ return tagPtr->id;
+}
+
diff --git a/khtml/misc/htmlhashes.h b/khtml/misc/htmlhashes.h
new file mode 100644
index 000000000..bade18ffb
--- /dev/null
+++ b/khtml/misc/htmlhashes.h
@@ -0,0 +1,14 @@
+#ifndef HTMLHASHES_H
+#define HTMLHASHES_H
+
+#include "xml/dom_stringimpl.h"
+#include "htmlattrs.h"
+#include "htmltags.h"
+
+namespace khtml
+{
+ int getTagID(const char *tagStr, int len);
+ int getAttrID(const char *tagStr, int len);
+}
+
+#endif
diff --git a/khtml/misc/htmltags.c b/khtml/misc/htmltags.c
new file mode 100644
index 000000000..1342e62bf
--- /dev/null
+++ b/khtml/misc/htmltags.c
@@ -0,0 +1,687 @@
+/* ANSI-C code produced by gperf version 3.0.1 */
+/* Command-line: gperf -a -L ANSI-C -P -D -E -C -l -o -t -k '*' -NfindTag -Hhash_tag -Wwordlist_tag -Qspool_Tag htmltags.gperf */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646. */
+#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
+#endif
+
+#line 1 "htmltags.gperf"
+
+/* This file is automatically generated from htmltags.in by maketags, do not edit */
+/* Copyright 1999 Lars Knoll */
+#include "htmltags.h"
+#line 6 "htmltags.gperf"
+struct tags {
+ int name;
+ int id;
+};
+/* maximum key range = 345, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+hash_tag (register const char *str, register unsigned int len)
+{
+ static const unsigned short asso_values[] =
+ {
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 70, 60, 55, 40, 25, 15, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 15, 10, 35,
+ 10, 5, 10, 0, 55, 40, 70, 30, 5, 15,
+ 30, 50, 5, 50, 20, 0, 0, 90, 120, 5,
+ 15, 35, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346
+ };
+ register int hval = len;
+
+ switch (hval)
+ {
+ default:
+ hval += asso_values[(unsigned char)str[9]];
+ /*FALLTHROUGH*/
+ case 9:
+ hval += asso_values[(unsigned char)str[8]];
+ /*FALLTHROUGH*/
+ case 8:
+ hval += asso_values[(unsigned char)str[7]];
+ /*FALLTHROUGH*/
+ case 7:
+ hval += asso_values[(unsigned char)str[6]];
+ /*FALLTHROUGH*/
+ case 6:
+ hval += asso_values[(unsigned char)str[5]];
+ /*FALLTHROUGH*/
+ case 5:
+ hval += asso_values[(unsigned char)str[4]];
+ /*FALLTHROUGH*/
+ case 4:
+ hval += asso_values[(unsigned char)str[3]];
+ /*FALLTHROUGH*/
+ case 3:
+ hval += asso_values[(unsigned char)str[2]];
+ /*FALLTHROUGH*/
+ case 2:
+ hval += asso_values[(unsigned char)str[1]+1];
+ /*FALLTHROUGH*/
+ case 1:
+ hval += asso_values[(unsigned char)str[0]];
+ break;
+ }
+ return hval;
+}
+
+struct spool_Tag_t
+ {
+ char spool_Tag_str0[sizeof("s")];
+ char spool_Tag_str1[sizeof("tr")];
+ char spool_Tag_str2[sizeof("p")];
+ char spool_Tag_str3[sizeof("td")];
+ char spool_Tag_str4[sizeof("b")];
+ char spool_Tag_str5[sizeof("br")];
+ char spool_Tag_str6[sizeof("pre")];
+ char spool_Tag_str7[sizeof("a")];
+ char spool_Tag_str8[sizeof("dd")];
+ char spool_Tag_str9[sizeof("dl")];
+ char spool_Tag_str10[sizeof("del")];
+ char spool_Tag_str11[sizeof("base")];
+ char spool_Tag_str12[sizeof("map")];
+ char spool_Tag_str13[sizeof("samp")];
+ char spool_Tag_str14[sizeof("table")];
+ char spool_Tag_str15[sizeof("em")];
+ char spool_Tag_str16[sizeof("area")];
+ char spool_Tag_str17[sizeof("label")];
+ char spool_Tag_str18[sizeof("i")];
+ char spool_Tag_str19[sizeof("th")];
+ char spool_Tag_str20[sizeof("dfn")];
+ char spool_Tag_str21[sizeof("meta")];
+ char spool_Tag_str22[sizeof("col")];
+ char spool_Tag_str23[sizeof("font")];
+ char spool_Tag_str24[sizeof("frame")];
+ char spool_Tag_str25[sizeof("q")];
+ char spool_Tag_str26[sizeof("xmp")];
+ char spool_Tag_str27[sizeof("form")];
+ char spool_Tag_str28[sizeof("hr")];
+ char spool_Tag_str29[sizeof("frameset")];
+ char spool_Tag_str30[sizeof("code")];
+ char spool_Tag_str31[sizeof("small")];
+ char spool_Tag_str32[sizeof("select")];
+ char spool_Tag_str33[sizeof("address")];
+ char spool_Tag_str34[sizeof("wbr")];
+ char spool_Tag_str35[sizeof("body")];
+ char spool_Tag_str36[sizeof("embed")];
+ char spool_Tag_str37[sizeof("legend")];
+ char spool_Tag_str38[sizeof("ol")];
+ char spool_Tag_str39[sizeof("bdo")];
+ char spool_Tag_str40[sizeof("nobr")];
+ char spool_Tag_str41[sizeof("param")];
+ char spool_Tag_str42[sizeof("h6")];
+ char spool_Tag_str43[sizeof("img")];
+ char spool_Tag_str44[sizeof("thead")];
+ char spool_Tag_str45[sizeof("li")];
+ char spool_Tag_str46[sizeof("kbd")];
+ char spool_Tag_str47[sizeof("layer")];
+ char spool_Tag_str48[sizeof("script")];
+ char spool_Tag_str49[sizeof("h5")];
+ char spool_Tag_str50[sizeof("big")];
+ char spool_Tag_str51[sizeof("abbr")];
+ char spool_Tag_str52[sizeof("title")];
+ char spool_Tag_str53[sizeof("applet")];
+ char spool_Tag_str54[sizeof("noembed")];
+ char spool_Tag_str55[sizeof("textarea")];
+ char spool_Tag_str56[sizeof("u")];
+ char spool_Tag_str57[sizeof("tt")];
+ char spool_Tag_str58[sizeof("ins")];
+ char spool_Tag_str59[sizeof("head")];
+ char spool_Tag_str60[sizeof("image")];
+ char spool_Tag_str61[sizeof("h4")];
+ char spool_Tag_str62[sizeof("span")];
+ char spool_Tag_str63[sizeof("iframe")];
+ char spool_Tag_str64[sizeof("dt")];
+ char spool_Tag_str65[sizeof("dir")];
+ char spool_Tag_str66[sizeof("tfoot")];
+ char spool_Tag_str67[sizeof("center")];
+ char spool_Tag_str68[sizeof("ul")];
+ char spool_Tag_str69[sizeof("noframes")];
+ char spool_Tag_str70[sizeof("h3")];
+ char spool_Tag_str71[sizeof("fieldset")];
+ char spool_Tag_str72[sizeof("cite")];
+ char spool_Tag_str73[sizeof("keygen")];
+ char spool_Tag_str74[sizeof("h2")];
+ char spool_Tag_str75[sizeof("nolayer")];
+ char spool_Tag_str76[sizeof("basefont")];
+ char spool_Tag_str77[sizeof("h1")];
+ char spool_Tag_str78[sizeof("sup")];
+ char spool_Tag_str79[sizeof("sub")];
+ char spool_Tag_str80[sizeof("plaintext")];
+ char spool_Tag_str81[sizeof("tbody")];
+ char spool_Tag_str82[sizeof("ilayer")];
+ char spool_Tag_str83[sizeof("link")];
+ char spool_Tag_str84[sizeof("style")];
+ char spool_Tag_str85[sizeof("noscript")];
+ char spool_Tag_str86[sizeof("isindex")];
+ char spool_Tag_str87[sizeof("menu")];
+ char spool_Tag_str88[sizeof("listing")];
+ char spool_Tag_str89[sizeof("var")];
+ char spool_Tag_str90[sizeof("html")];
+ char spool_Tag_str91[sizeof("caption")];
+ char spool_Tag_str92[sizeof("acronym")];
+ char spool_Tag_str93[sizeof("input")];
+ char spool_Tag_str94[sizeof("strike")];
+ char spool_Tag_str95[sizeof("strong")];
+ char spool_Tag_str96[sizeof("object")];
+ char spool_Tag_str97[sizeof("marquee")];
+ char spool_Tag_str98[sizeof("div")];
+ char spool_Tag_str99[sizeof("button")];
+ char spool_Tag_str100[sizeof("colgroup")];
+ char spool_Tag_str101[sizeof("option")];
+ char spool_Tag_str102[sizeof("anchor")];
+ char spool_Tag_str103[sizeof("optgroup")];
+ char spool_Tag_str104[sizeof("blockquote")];
+ };
+static const struct spool_Tag_t spool_Tag_contents =
+ {
+ "s",
+ "tr",
+ "p",
+ "td",
+ "b",
+ "br",
+ "pre",
+ "a",
+ "dd",
+ "dl",
+ "del",
+ "base",
+ "map",
+ "samp",
+ "table",
+ "em",
+ "area",
+ "label",
+ "i",
+ "th",
+ "dfn",
+ "meta",
+ "col",
+ "font",
+ "frame",
+ "q",
+ "xmp",
+ "form",
+ "hr",
+ "frameset",
+ "code",
+ "small",
+ "select",
+ "address",
+ "wbr",
+ "body",
+ "embed",
+ "legend",
+ "ol",
+ "bdo",
+ "nobr",
+ "param",
+ "h6",
+ "img",
+ "thead",
+ "li",
+ "kbd",
+ "layer",
+ "script",
+ "h5",
+ "big",
+ "abbr",
+ "title",
+ "applet",
+ "noembed",
+ "textarea",
+ "u",
+ "tt",
+ "ins",
+ "head",
+ "image",
+ "h4",
+ "span",
+ "iframe",
+ "dt",
+ "dir",
+ "tfoot",
+ "center",
+ "ul",
+ "noframes",
+ "h3",
+ "fieldset",
+ "cite",
+ "keygen",
+ "h2",
+ "nolayer",
+ "basefont",
+ "h1",
+ "sup",
+ "sub",
+ "plaintext",
+ "tbody",
+ "ilayer",
+ "link",
+ "style",
+ "noscript",
+ "isindex",
+ "menu",
+ "listing",
+ "var",
+ "html",
+ "caption",
+ "acronym",
+ "input",
+ "strike",
+ "strong",
+ "object",
+ "marquee",
+ "div",
+ "button",
+ "colgroup",
+ "option",
+ "anchor",
+ "optgroup",
+ "blockquote"
+ };
+#define spool_Tag ((const char *) &spool_Tag_contents)
+#ifdef __GNUC__
+__inline
+#endif
+const struct tags *
+findTag (register const char *str, register unsigned int len)
+{
+ enum
+ {
+ TOTAL_KEYWORDS = 105,
+ MIN_WORD_LENGTH = 1,
+ MAX_WORD_LENGTH = 10,
+ MIN_HASH_VALUE = 1,
+ MAX_HASH_VALUE = 345
+ };
+
+ static const unsigned char lengthtable[] =
+ {
+ 1, 2, 1, 2, 1, 2, 3, 1, 2, 2, 3, 4, 3, 4,
+ 5, 2, 4, 5, 1, 2, 3, 4, 3, 4, 5, 1, 3, 4,
+ 2, 8, 4, 5, 6, 7, 3, 4, 5, 6, 2, 3, 4, 5,
+ 2, 3, 5, 2, 3, 5, 6, 2, 3, 4, 5, 6, 7, 8,
+ 1, 2, 3, 4, 5, 2, 4, 6, 2, 3, 5, 6, 2, 8,
+ 2, 8, 4, 6, 2, 7, 8, 2, 3, 3, 9, 5, 6, 4,
+ 5, 8, 7, 4, 7, 3, 4, 7, 7, 5, 6, 6, 6, 7,
+ 3, 6, 8, 6, 6, 8, 10
+ };
+ static const struct tags wordlist_tag[] =
+ {
+#line 87 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str0, ID_S},
+#line 106 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str1, ID_TR},
+#line 82 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str2, ID_P},
+#line 100 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str3, ID_TD},
+#line 17 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str4, ID_B},
+#line 24 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str5, ID_BR},
+#line 85 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str6, ID_PRE},
+#line 11 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str7, ID_A},
+#line 32 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str8, ID_DD},
+#line 37 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str9, ID_DL},
+#line 33 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str10, ID_DEL},
+#line 18 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str11, ID_BASE},
+#line 69 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str12, ID_MAP},
+#line 88 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str13, ID_SAMP},
+#line 98 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str14, ID_TABLE},
+#line 39 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str15, ID_EM},
+#line 16 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str16, ID_AREA},
+#line 64 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str17, ID_LABEL},
+#line 55 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str18, ID_I},
+#line 103 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str19, ID_TH},
+#line 34 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str20, ID_DFN},
+#line 72 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str21, ID_META},
+#line 30 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str22, ID_COL},
+#line 42 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str23, ID_FONT},
+#line 44 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str24, ID_FRAME},
+#line 86 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str25, ID_Q},
+#line 112 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str26, ID_XMP},
+#line 43 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str27, ID_FORM},
+#line 53 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str28, ID_HR},
+#line 45 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str29, ID_FRAMESET},
+#line 29 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str30, ID_CODE},
+#line 91 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str31, ID_SMALL},
+#line 90 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str32, ID_SELECT},
+#line 14 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str33, ID_ADDRESS},
+#line 111 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str34, ID_WBR},
+#line 23 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str35, ID_BODY},
+#line 40 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str36, ID_EMBED},
+#line 66 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str37, ID_LEGEND},
+#line 79 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str38, ID_OL},
+#line 20 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str39, ID_BDO},
+#line 73 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str40, ID_NOBR},
+#line 83 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str41, ID_PARAM},
+#line 51 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str42, ID_H6},
+#line 58 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str43, ID_IMG},
+#line 104 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str44, ID_THEAD},
+#line 67 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str45, ID_LI},
+#line 62 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str46, ID_KBD},
+#line 65 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str47, ID_LAYER},
+#line 89 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str48, ID_SCRIPT},
+#line 50 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str49, ID_H5},
+#line 21 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str50, ID_BIG},
+#line 12 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str51, ID_ABBR},
+#line 105 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str52, ID_TITLE},
+#line 15 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str53, ID_APPLET},
+#line 74 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str54, ID_NOEMBED},
+#line 101 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str55, ID_TEXTAREA},
+#line 108 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str56, ID_U},
+#line 107 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str57, ID_TT},
+#line 60 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str58, ID_INS},
+#line 52 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str59, ID_HEAD},
+#line 114 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str60, ID_IMG},
+#line 49 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str61, ID_H4},
+#line 92 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str62, ID_SPAN},
+#line 56 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str63, ID_IFRAME},
+#line 38 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str64, ID_DT},
+#line 35 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str65, ID_DIR},
+#line 102 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str66, ID_TFOOT},
+#line 27 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str67, ID_CENTER},
+#line 109 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str68, ID_UL},
+#line 75 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str69, ID_NOFRAMES},
+#line 48 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str70, ID_H3},
+#line 41 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str71, ID_FIELDSET},
+#line 28 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str72, ID_CITE},
+#line 63 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str73, ID_KEYGEN},
+#line 47 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str74, ID_H2},
+#line 77 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str75, ID_NOLAYER},
+#line 19 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str76, ID_BASEFONT},
+#line 46 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str77, ID_H1},
+#line 97 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str78, ID_SUP},
+#line 96 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str79, ID_SUB},
+#line 84 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str80, ID_PLAINTEXT},
+#line 99 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str81, ID_TBODY},
+#line 57 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str82, ID_ILAYER},
+#line 68 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str83, ID_LINK},
+#line 95 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str84, ID_STYLE},
+#line 76 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str85, ID_NOSCRIPT},
+#line 61 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str86, ID_ISINDEX},
+#line 71 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str87, ID_MENU},
+#line 115 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str88, ID_PRE},
+#line 110 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str89, ID_VAR},
+#line 54 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str90, ID_HTML},
+#line 26 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str91, ID_CAPTION},
+#line 13 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str92, ID_ACRONYM},
+#line 59 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str93, ID_INPUT},
+#line 93 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str94, ID_STRIKE},
+#line 94 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str95, ID_STRONG},
+#line 78 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str96, ID_OBJECT},
+#line 70 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str97, ID_MARQUEE},
+#line 36 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str98, ID_DIV},
+#line 25 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str99, ID_BUTTON},
+#line 31 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str100, ID_COLGROUP},
+#line 81 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str101, ID_OPTION},
+#line 113 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str102, ID_A},
+#line 80 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str103, ID_OPTGROUP},
+#line 22 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str104, ID_BLOCKQUOTE}
+ };
+
+ static const signed char lookup[] =
+ {
+ -1, 0, 1, -1, -1, -1, 2, 3, -1, -1,
+ -1, 4, 5, 6, -1, -1, 7, 8, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 9, 10, 11,
+ -1, -1, -1, 12, 13, 14, -1, 15, -1, 16,
+ 17, 18, 19, 20, 21, -1, -1, -1, 22, 23,
+ 24, 25, -1, 26, 27, -1, -1, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, -1, 42, 43, -1, 44, -1, 45, 46, -1,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, -1,
+ -1, 56, 57, 58, 59, 60, -1, 61, -1, 62,
+ -1, 63, 64, 65, -1, 66, 67, 68, 69, -1,
+ -1, -1, 70, 71, 72, -1, 73, 74, -1, -1,
+ -1, -1, 75, 76, -1, -1, -1, 77, 78, -1,
+ -1, -1, -1, 79, 80, 81, 82, -1, -1, 83,
+ 84, -1, -1, 85, -1, -1, -1, 86, -1, 87,
+ -1, -1, 88, 89, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 90,
+ -1, -1, -1, -1, -1, -1, -1, 91, -1, -1,
+ -1, -1, 92, -1, -1, -1, -1, -1, -1, -1,
+ 93, 94, -1, -1, -1, -1, 95, -1, -1, -1,
+ -1, 96, 97, 98, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 99, -1, 100, -1,
+ -1, -1, -1, -1, -1, -1, 101, -1, -1, -1,
+ -1, 102, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 103, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 104
+ };
+
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ register int key = hash_tag (str, len);
+
+ if (key <= MAX_HASH_VALUE && key >= 0)
+ {
+ register int index = lookup[key];
+
+ if (index >= 0)
+ {
+ if (len == lengthtable[index])
+ {
+ register const char *s = wordlist_tag[index].name + spool_Tag;
+
+ if (*str == *s && !memcmp (str + 1, s + 1, len - 1))
+ return &wordlist_tag[index];
+ }
+ }
+ }
+ }
+ return 0;
+}
+#line 116 "htmltags.gperf"
+
+
+
+static const char tagStable[] = {
+ "\000/a\000/abbr\000/acronym\000/address\000/applet\000/area\000/b"
+ "\000/base\000/basefont\000/bdo\000/big\000/blockquote\000/body"
+ "\000/br\000/button\000/caption\000/center\000/cite\000/code\000/col"
+ "\000/colgroup\000/dd\000/del\000/dfn\000/dir\000/div\000/dl\000/dt"
+ "\000/em\000/embed\000/fieldset\000/font\000/form\000/frame\000/frameset"
+ "\000/h1\000/h2\000/h3\000/h4\000/h5\000/h6\000/head\000/hr\000/html"
+ "\000/i\000/iframe\000/ilayer\000/img\000/input\000/ins\000/isindex"
+ "\000/kbd\000/keygen\000/label\000/layer\000/legend\000/li\000/link"
+ "\000/map\000/marquee\000/menu\000/meta\000/nobr\000/noembed\000/noframes"
+ "\000/noscript\000/nolayer\000/object\000/ol\000/optgroup\000/option"
+ "\000/p\000/param\000/plaintext\000/pre\000/q\000/s\000/samp\000/script"
+ "\000/select\000/small\000/span\000/strike\000/strong\000/style"
+ "\000/sub\000/sup\000/table\000/tbody\000/td\000/textarea\000/tfoot"
+ "\000/th\000/thead\000/title\000/tr\000/tt\000/u\000/ul\000/var"
+ "\000/wbr\000/xmp\000/text\000/comment\000"
+};
+
+static const unsigned short tagSList[] = {
+ 0,
+
+ 2, 5, 11, 20, 29, 37, 43, 46, 52, 62, 67, 72,
+ 84, 90, 94, 102, 111, 119, 125, 131, 136, 146, 150, 155,
+ 160, 165, 170, 174, 178, 182, 189, 199, 205, 211, 218, 228,
+ 232, 236, 240, 244, 248, 252, 258, 262, 268, 271, 279, 287,
+ 292, 299, 304, 313, 318, 326, 333, 340, 348, 352, 358, 363,
+ 372, 378, 384, 390, 399, 409, 419, 428, 436, 440, 450, 458,
+ 461, 468, 479, 484, 487, 490, 496, 504, 512, 519, 525, 533,
+ 541, 548, 553, 558, 565, 572, 576, 586, 593, 597, 604, 611,
+ 615, 619, 622, 626, 631, 636, 641, 647, 1, 4, 10, 19,
+ 28, 36, 42, 45, 51, 61, 66, 71, 83, 89, 93, 101,
+ 110, 118, 124, 130, 135, 145, 149, 154, 159, 164, 169, 173,
+ 177, 181, 188, 198, 204, 210, 217, 227, 231, 235, 239, 243,
+ 247, 251, 257, 261, 267, 270, 278, 286, 291, 298, 303, 312,
+ 317, 325, 332, 339, 347, 351, 357, 362, 371, 377, 383, 389,
+ 398, 408, 418, 427, 435, 439, 449, 457, 460, 467, 478, 483,
+ 486, 489, 495, 503, 511, 518, 524, 532, 540, 547, 552, 557,
+ 564, 571, 575, 585, 592, 596, 603, 610, 614, 618, 621, 625,
+ 630, 635, 640, 646, 0
+};
+
+const char* KDE_NO_EXPORT getTagName(unsigned short id)
+{
+ if(id > ID_CLOSE_TAG*2) id = ID_CLOSE_TAG+1;
+ return &tagStable[tagSList[id]];
+}
diff --git a/khtml/misc/htmltags.h b/khtml/misc/htmltags.h
new file mode 100644
index 000000000..a2fb0fe55
--- /dev/null
+++ b/khtml/misc/htmltags.h
@@ -0,0 +1,119 @@
+/* This file is automatically generated from htmltags.in by maketags, do not edit */
+/* Copyright 1999 Lars Knoll */
+
+#ifndef KHTML_TAGS_H
+#define KHTML_TAGS_H
+
+#include "dom/dom_string.h"
+#include <kglobal.h>
+
+KDE_NO_EXPORT const char* getTagName(unsigned short id);
+
+#define ID_A 1
+#define ID_ABBR 2
+#define ID_ACRONYM 3
+#define ID_ADDRESS 4
+#define ID_APPLET 5
+#define ID_AREA 6
+#define ID_B 7
+#define ID_BASE 8
+#define ID_BASEFONT 9
+#define ID_BDO 10
+#define ID_BIG 11
+#define ID_BLOCKQUOTE 12
+#define ID_BODY 13
+#define ID_BR 14
+#define ID_BUTTON 15
+#define ID_CAPTION 16
+#define ID_CENTER 17
+#define ID_CITE 18
+#define ID_CODE 19
+#define ID_COL 20
+#define ID_COLGROUP 21
+#define ID_DD 22
+#define ID_DEL 23
+#define ID_DFN 24
+#define ID_DIR 25
+#define ID_DIV 26
+#define ID_DL 27
+#define ID_DT 28
+#define ID_EM 29
+#define ID_EMBED 30
+#define ID_FIELDSET 31
+#define ID_FONT 32
+#define ID_FORM 33
+#define ID_FRAME 34
+#define ID_FRAMESET 35
+#define ID_H1 36
+#define ID_H2 37
+#define ID_H3 38
+#define ID_H4 39
+#define ID_H5 40
+#define ID_H6 41
+#define ID_HEAD 42
+#define ID_HR 43
+#define ID_HTML 44
+#define ID_I 45
+#define ID_IFRAME 46
+#define ID_ILAYER 47
+#define ID_IMG 48
+#define ID_INPUT 49
+#define ID_INS 50
+#define ID_ISINDEX 51
+#define ID_KBD 52
+#define ID_KEYGEN 53
+#define ID_LABEL 54
+#define ID_LAYER 55
+#define ID_LEGEND 56
+#define ID_LI 57
+#define ID_LINK 58
+#define ID_MAP 59
+#define ID_MARQUEE 60
+#define ID_MENU 61
+#define ID_META 62
+#define ID_NOBR 63
+#define ID_NOEMBED 64
+#define ID_NOFRAMES 65
+#define ID_NOSCRIPT 66
+#define ID_NOLAYER 67
+#define ID_OBJECT 68
+#define ID_OL 69
+#define ID_OPTGROUP 70
+#define ID_OPTION 71
+#define ID_P 72
+#define ID_PARAM 73
+#define ID_PLAINTEXT 74
+#define ID_PRE 75
+#define ID_Q 76
+#define ID_S 77
+#define ID_SAMP 78
+#define ID_SCRIPT 79
+#define ID_SELECT 80
+#define ID_SMALL 81
+#define ID_SPAN 82
+#define ID_STRIKE 83
+#define ID_STRONG 84
+#define ID_STYLE 85
+#define ID_SUB 86
+#define ID_SUP 87
+#define ID_TABLE 88
+#define ID_TBODY 89
+#define ID_TD 90
+#define ID_TEXTAREA 91
+#define ID_TFOOT 92
+#define ID_TH 93
+#define ID_THEAD 94
+#define ID_TITLE 95
+#define ID_TR 96
+#define ID_TT 97
+#define ID_U 98
+#define ID_UL 99
+#define ID_VAR 100
+#define ID_WBR 101
+#define ID_XMP 102
+#define ID_TEXT 103
+#define ID_COMMENT 104
+#define ID_CLOSE_TAG 104
+#define ID_LAST_TAG 104
+
+#endif
diff --git a/khtml/misc/htmltags.in b/khtml/misc/htmltags.in
new file mode 100644
index 000000000..9d686364a
--- /dev/null
+++ b/khtml/misc/htmltags.in
@@ -0,0 +1,102 @@
+a
+abbr
+acronym
+address
+applet
+area
+b
+base
+basefont
+bdo
+big
+blockquote
+body
+br
+button
+caption
+center
+cite
+code
+col
+colgroup
+dd
+del
+dfn
+dir
+div
+dl
+dt
+em
+embed
+fieldset
+font
+form
+frame
+frameset
+h1
+h2
+h3
+h4
+h5
+h6
+head
+hr
+html
+i
+iframe
+ilayer
+img
+input
+ins
+isindex
+kbd
+keygen
+label
+layer
+legend
+li
+link
+map
+marquee
+menu
+meta
+nobr
+noembed
+noframes
+noscript
+nolayer
+object
+ol
+optgroup
+option
+p
+param
+plaintext
+pre
+q
+s
+samp
+script
+select
+small
+span
+strike
+strong
+style
+sub
+sup
+table
+tbody
+td
+textarea
+tfoot
+th
+thead
+title
+tr
+tt
+u
+ul
+var
+wbr
+xmp
diff --git a/khtml/misc/khtmllayout.h b/khtml/misc/khtmllayout.h
new file mode 100644
index 000000000..e4fb531a1
--- /dev/null
+++ b/khtml/misc/khtmllayout.h
@@ -0,0 +1,112 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+ This widget holds some useful definitions needed for layouting Elements
+*/
+#ifndef HTML_LAYOUT_H
+#define HTML_LAYOUT_H
+
+
+/*
+ * this namespace contains definitions for various types needed for
+ * layouting.
+ */
+namespace khtml
+{
+
+ const int UNDEFINED = -1;
+
+ // alignment
+ enum VAlign { VNone=0, Bottom, VCenter, Top, Baseline };
+ enum HAlign { HDefault, Left, HCenter, Right, HNone = 0 };
+
+ /*
+ * %multiLength and %Length
+ */
+ enum LengthType { Variable = 0, Relative, Percent, Fixed, Static };
+ struct Length
+ {
+ Length() : _length(0) {}
+ Length(LengthType t) { _length = 0; l.type = t; }
+ Length(int v, LengthType t, bool q=false)
+ { _length= 0; l.value = v; l.type = t; l.quirk = q; }
+ bool operator==(const Length& o) const
+ { return _length == o._length; }
+ bool operator!=(const Length& o) const
+ { return _length != o._length; }
+ void setValue(LengthType t, int v) {
+ _length = 0; l.value = v; l.type = t; l.quirk = false;
+ }
+ /*
+ * works only for Fixed and Percent, returns -1 otherwise
+ */
+ int width(int maxWidth) const
+ {
+ switch(l.type)
+ {
+ case Fixed:
+ return l.value;
+ case Percent:
+ return maxWidth*l.value/100;
+ case Variable:
+ return maxWidth;
+ default:
+ return -1;
+ }
+ }
+ /*
+ * returns the minimum width value which could work...
+ */
+ int minWidth(int maxWidth) const
+ {
+ switch(l.type)
+ {
+ case Fixed:
+ return l.value;
+ case Percent:
+ return maxWidth*l.value/100;
+ case Variable:
+ default:
+ return 0;
+ }
+ }
+ bool isVariable() const { return ((LengthType) l.type == Variable); }
+ bool isRelative() const { return ((LengthType) l.type == Relative); }
+ bool isPercent() const { return ((LengthType ) l.type == Percent); }
+ bool isFixed() const { return ((LengthType) l.type == Fixed); }
+ bool isStatic() const { return ((LengthType) l.type == Static); }
+ bool isQuirk() const { return l.quirk; }
+
+ int value() const { return l.value; }
+ LengthType type() const { return (LengthType) l.type; }
+
+ union {
+ struct {
+ signed int value : 28;
+ unsigned type : 3;
+ bool quirk : 1;
+ } l;
+ Q_UINT32 _length;
+ };
+ };
+
+}
+
+#endif
diff --git a/khtml/misc/loader.cpp b/khtml/misc/loader.cpp
new file mode 100644
index 000000000..8f7ae246f
--- /dev/null
+++ b/khtml/misc/loader.cpp
@@ -0,0 +1,1679 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
+ Copyright (C) 2001-2003 Dirk Mueller (mueller@kde.org)
+ Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
+ Copyright (C) 2003 Apple Computer, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+ This class provides all functionality needed for loading images, style sheets and html
+ pages from the web. It has a memory cache for these objects.
+
+ // regarding the LRU:
+ // http://www.is.kyusan-u.ac.jp/~chengk/pub/papers/compsac00_A07-07.pdf
+*/
+
+#undef CACHE_DEBUG
+//#define CACHE_DEBUG
+
+#ifdef CACHE_DEBUG
+#define CDEBUG kdDebug(6060)
+#else
+#define CDEBUG kndDebug()
+#endif
+
+#undef LOADER_DEBUG
+//#define LOADER_DEBUG
+
+#include <assert.h>
+
+#include "misc/loader.h"
+#include "misc/seed.h"
+
+// default cache size
+#define DEFCACHESIZE 2096*1024
+#define MAX_JOB_COUNT 32
+
+#include <qasyncio.h>
+#include <qasyncimageio.h>
+#include <qpainter.h>
+#include <qbitmap.h>
+#include <qmovie.h>
+#include <qwidget.h>
+
+#include <kapplication.h>
+#include <kio/job.h>
+#include <kio/jobclasses.h>
+#include <kglobal.h>
+#include <kimageio.h>
+#include <kcharsets.h>
+#include <kiconloader.h>
+#include <scheduler.h>
+#include <kdebug.h>
+#include "khtml_factory.h"
+#include "khtml_part.h"
+
+#ifdef IMAGE_TITLES
+#include <qfile.h>
+#include <kfilemetainfo.h>
+#include <ktempfile.h>
+#endif
+
+#include "html/html_documentimpl.h"
+#include "css/css_stylesheetimpl.h"
+#include "xml/dom_docimpl.h"
+
+#include "blocked_icon.cpp"
+
+using namespace khtml;
+using namespace DOM;
+
+#define MAX_LRU_LISTS 20
+struct LRUList {
+ CachedObject* m_head;
+ CachedObject* m_tail;
+
+ LRUList() : m_head(0), m_tail(0) {}
+};
+
+static LRUList m_LRULists[MAX_LRU_LISTS];
+static LRUList* getLRUListFor(CachedObject* o);
+
+CachedObjectClient::~CachedObjectClient()
+{
+}
+
+CachedObject::~CachedObject()
+{
+ Cache::removeFromLRUList(this);
+}
+
+void CachedObject::finish()
+{
+ m_status = Cached;
+}
+
+bool CachedObject::isExpired() const
+{
+ if (!m_expireDate) return false;
+ time_t now = time(0);
+ return (difftime(now, m_expireDate) >= 0);
+}
+
+void CachedObject::setRequest(Request *_request)
+{
+ if ( _request && !m_request )
+ m_status = Pending;
+
+ if ( allowInLRUList() )
+ Cache::removeFromLRUList( this );
+
+ m_request = _request;
+
+ if ( allowInLRUList() )
+ Cache::insertInLRUList( this );
+}
+
+void CachedObject::ref(CachedObjectClient *c)
+{
+ // unfortunately we can be ref'ed multiple times from the
+ // same object, because it uses e.g. the same foreground
+ // and the same background picture. so deal with it.
+ m_clients.insert(c,c);
+ Cache::removeFromLRUList(this);
+ m_accessCount++;
+}
+
+void CachedObject::deref(CachedObjectClient *c)
+{
+ assert( c );
+ assert( m_clients.count() );
+ assert( !canDelete() );
+ assert( m_clients.find( c ) );
+
+ Cache::flush();
+
+ m_clients.remove(c);
+
+ if (allowInLRUList())
+ Cache::insertInLRUList(this);
+}
+
+void CachedObject::setSize(int size)
+{
+ bool sizeChanged;
+
+ if ( !m_next && !m_prev && getLRUListFor(this)->m_head != this )
+ sizeChanged = false;
+ else
+ sizeChanged = ( size - m_size ) != 0;
+
+ // The object must now be moved to a different queue,
+ // since its size has been changed.
+ if ( sizeChanged && allowInLRUList())
+ Cache::removeFromLRUList(this);
+
+ m_size = size;
+
+ if ( sizeChanged && allowInLRUList())
+ Cache::insertInLRUList(this);
+}
+
+QTextCodec* CachedObject::codecForBuffer( const QString& charset, const QByteArray& buffer ) const
+{
+ // we don't use heuristicContentMatch here since it is a) far too slow and
+ // b) having too much functionality for our case.
+
+ uchar* d = ( uchar* ) buffer.data();
+ int s = buffer.size();
+
+ // BOM
+ if ( s >= 3 &&
+ d[0] == 0xef && d[1] == 0xbb && d[2] == 0xbf)
+ return QTextCodec::codecForMib( 106 ); // UTF-8
+
+ if ( s >= 2 && ((d[0] == 0xff && d[1] == 0xfe) ||
+ (d[0] == 0xfe && d[1] == 0xff)))
+ return QTextCodec::codecForMib( 1000 ); // UCS-2
+
+ // Link or @charset
+ if(!charset.isEmpty())
+ {
+ QTextCodec* c = KGlobal::charsets()->codecForName(charset);
+ if(c->mibEnum() == 11) {
+ // iso8859-8 (visually ordered)
+ c = QTextCodec::codecForName("iso8859-8-i");
+ }
+ return c;
+ }
+
+ // Default
+ return QTextCodec::codecForMib( 4 ); // latin 1
+}
+
+// -------------------------------------------------------------------------------------------
+
+CachedCSSStyleSheet::CachedCSSStyleSheet(DocLoader* dl, const DOMString &url, KIO::CacheControl _cachePolicy,
+ const char *accept)
+ : CachedObject(url, CSSStyleSheet, _cachePolicy, 0)
+{
+ // Set the type we want (probably css or xml)
+ QString ah = QString::fromLatin1( accept );
+ if ( !ah.isEmpty() )
+ ah += ",";
+ ah += "*/*;q=0.1";
+ setAccept( ah );
+ m_hadError = false;
+ m_wasBlocked = false;
+ m_err = 0;
+ // load the file
+ Cache::loader()->load(dl, this, false);
+ m_loading = true;
+}
+
+CachedCSSStyleSheet::CachedCSSStyleSheet(const DOMString &url, const QString &stylesheet_data)
+ : CachedObject(url, CSSStyleSheet, KIO::CC_Verify, stylesheet_data.length())
+{
+ m_loading = false;
+ m_status = Persistent;
+ m_sheet = DOMString(stylesheet_data);
+}
+
+
+void CachedCSSStyleSheet::ref(CachedObjectClient *c)
+{
+ CachedObject::ref(c);
+
+ if (!m_loading) {
+ if (m_hadError)
+ c->error( m_err, m_errText );
+ else
+ c->setStyleSheet( m_url, m_sheet, m_charset );
+ }
+}
+
+void CachedCSSStyleSheet::data( QBuffer &buffer, bool eof )
+{
+ if(!eof) return;
+ buffer.close();
+ setSize(buffer.buffer().size());
+
+// QString charset = checkCharset( buffer.buffer() );
+ QTextCodec* c = 0;
+ if (!m_charset.isEmpty()) {
+ c = KGlobal::charsets()->codecForName(m_charset);
+ if(c->mibEnum() == 11) c = QTextCodec::codecForName("iso8859-8-i");
+ }
+ else {
+ c = codecForBuffer( m_charsetHint, buffer.buffer() );
+ m_charset = c->name();
+ }
+ QString data = c->toUnicode( buffer.buffer().data(), m_size );
+ // workaround Qt bugs
+ m_sheet = static_cast<QChar>(data[0]) == QChar::byteOrderMark ? DOMString(data.mid( 1 ) ) : DOMString(data);
+ m_loading = false;
+
+ checkNotify();
+}
+
+void CachedCSSStyleSheet::checkNotify()
+{
+ if(m_loading || m_hadError) return;
+
+ CDEBUG << "CachedCSSStyleSheet:: finishedLoading " << m_url.string() << endl;
+
+ // it() first increments, then returnes the current item.
+ // this avoids skipping an item when setStyleSheet deletes the "current" one.
+ for (QPtrDictIterator<CachedObjectClient> it( m_clients ); it.current();)
+ it()->setStyleSheet( m_url, m_sheet, m_charset );
+}
+
+
+void CachedCSSStyleSheet::error( int err, const char* text )
+{
+ m_hadError = true;
+ m_err = err;
+ m_errText = text;
+ m_loading = false;
+
+ // it() first increments, then returnes the current item.
+ // this avoids skipping an item when setStyleSheet deletes the "current" one.
+ for (QPtrDictIterator<CachedObjectClient> it( m_clients ); it.current();)
+ it()->error( m_err, m_errText );
+}
+
+#if 0
+QString CachedCSSStyleSheet::checkCharset(const QByteArray& buffer ) const
+{
+ int s = buffer.size();
+ if (s <= 12) return m_charset;
+
+ // @charset has to be first or directly after BOM.
+ // CSS 2.1 says @charset should win over BOM, but since more browsers support BOM
+ // than @charset, we default to that.
+ const char* d = (const char*) buffer.data();
+ if (strncmp(d, "@charset \"",10) == 0)
+ {
+ // the string until "; is the charset name
+ char *p = strchr(d+10, '"');
+ if (p == 0) return m_charset;
+ QString charset = QString::fromAscii(d+10, p-(d+10));
+ return charset;
+ }
+ return m_charset;
+}
+#endif
+
+// -------------------------------------------------------------------------------------------
+
+CachedScript::CachedScript(DocLoader* dl, const DOMString &url, KIO::CacheControl _cachePolicy, const char*)
+ : CachedObject(url, Script, _cachePolicy, 0)
+{
+ // It's javascript we want.
+ // But some websites think their scripts are <some wrong mimetype here>
+ // and refuse to serve them if we only accept application/x-javascript.
+ setAccept( QString::fromLatin1("*/*") );
+ // load the file
+ Cache::loader()->load(dl, this, false);
+ m_loading = true;
+}
+
+CachedScript::CachedScript(const DOMString &url, const QString &script_data)
+ : CachedObject(url, Script, KIO::CC_Verify, script_data.length())
+{
+ m_loading = false;
+ m_status = Persistent;
+ m_script = DOMString(script_data);
+}
+
+void CachedScript::ref(CachedObjectClient *c)
+{
+ CachedObject::ref(c);
+
+ if(!m_loading) c->notifyFinished(this);
+}
+
+void CachedScript::data( QBuffer &buffer, bool eof )
+{
+ if(!eof) return;
+ buffer.close();
+ setSize(buffer.buffer().size());
+
+ QTextCodec* c = codecForBuffer( m_charset, buffer.buffer() );
+ QString data = c->toUnicode( buffer.buffer().data(), m_size );
+ m_script = static_cast<QChar>(data[0]) == QChar::byteOrderMark ? DOMString(data.mid( 1 ) ) : DOMString(data);
+ m_loading = false;
+ checkNotify();
+}
+
+void CachedScript::checkNotify()
+{
+ if(m_loading) return;
+
+ for (QPtrDictIterator<CachedObjectClient> it( m_clients); it.current();)
+ it()->notifyFinished(this);
+}
+
+void CachedScript::error( int /*err*/, const char* /*text*/ )
+{
+ m_loading = false;
+ checkNotify();
+}
+
+// ------------------------------------------------------------------------------------------
+
+namespace khtml
+{
+
+class ImageSource : public QDataSource
+{
+public:
+ ImageSource(QByteArray buf)
+ : buffer( buf ), pos( 0 ), eof( false ), rew(false ), rewable( true )
+ {}
+
+ int readyToSend()
+ {
+ if(eof && pos == buffer.size())
+ return -1;
+
+ return buffer.size() - pos;
+ }
+
+ void sendTo(QDataSink* sink, int n)
+ {
+ sink->receive((const uchar*)&buffer.at(pos), n);
+
+ pos += n;
+
+ // buffer is no longer needed
+ if(eof && pos == buffer.size() && !rewable)
+ {
+ buffer.resize(0);
+ pos = 0;
+ }
+ }
+
+ /**
+ * Sets the EOF state.
+ */
+ void setEOF( bool state ) { eof = state; }
+
+ bool rewindable() const { return rewable; }
+ void enableRewind(bool on) { rew = on; }
+
+ /*
+ Calls reset() on the QIODevice.
+ */
+ void rewind()
+ {
+ pos = 0;
+ if (!rew) {
+ QDataSource::rewind();
+ } else
+ ready();
+ }
+
+ /*
+ Indicates that the buffered data is no longer
+ needed.
+ */
+ void cleanBuffer()
+ {
+ // if we need to be able to rewind, buffer is needed
+ if(rew)
+ return;
+
+ rewable = false;
+
+ // buffer is no longer needed
+ if(eof && pos == buffer.size())
+ {
+ buffer.resize(0);
+ pos = 0;
+ }
+ }
+
+ QByteArray buffer;
+ unsigned int pos;
+private:
+ bool eof : 1;
+ bool rew : 1;
+ bool rewable : 1;
+};
+
+} // end namespace
+
+static QString buildAcceptHeader()
+{
+ return "image/png, image/jpeg, video/x-mng, image/jp2, image/gif;q=0.5,*/*;q=0.1";
+}
+
+// -------------------------------------------------------------------------------------
+
+CachedImage::CachedImage(DocLoader* dl, const DOMString &url, KIO::CacheControl _cachePolicy, const char*)
+ : QObject(), CachedObject(url, Image, _cachePolicy, 0)
+{
+ static const QString &acceptHeader = KGlobal::staticQString( buildAcceptHeader() );
+
+ m = 0;
+ p = 0;
+ pixPart = 0;
+ bg = 0;
+ scaled = 0;
+ bgColor = qRgba( 0, 0, 0, 0xFF );
+ typeChecked = false;
+ isFullyTransparent = false;
+ monochrome = false;
+ formatType = 0;
+ m_status = Unknown;
+ imgSource = 0;
+ setAccept( acceptHeader );
+ m_showAnimations = dl->showAnimations();
+
+ if ( KHTMLFactory::defaultHTMLSettings()->isAdFiltered( url.string() ) ) {
+ m_wasBlocked = true;
+ CachedObject::finish();
+ }
+}
+
+CachedImage::~CachedImage()
+{
+ clear();
+}
+
+void CachedImage::ref( CachedObjectClient *c )
+{
+ CachedObject::ref(c);
+
+ if( m ) {
+ m->unpause();
+ if( m->finished() || m_clients.count() == 1 )
+ m->restart();
+ }
+
+ // for mouseovers, dynamic changes
+ if ( m_status >= Persistent && !valid_rect().isNull() ) {
+ c->setPixmap( pixmap(), valid_rect(), this);
+ c->notifyFinished( this );
+ }
+}
+
+void CachedImage::deref( CachedObjectClient *c )
+{
+ CachedObject::deref(c);
+ if(m && m_clients.isEmpty() && m->running())
+ m->pause();
+}
+
+#define BGMINWIDTH 32
+#define BGMINHEIGHT 32
+
+const QPixmap &CachedImage::tiled_pixmap(const QColor& newc, int xWidth, int xHeight)
+{
+ static QRgb bgTransparent = qRgba( 0, 0, 0, 0xFF );
+
+ QSize s(pixmap_size());
+ int w = xWidth;
+ int h = xHeight;
+ if (w == -1) xWidth = w = s.width();
+ if (h == -1) xHeight = h = s.height();
+
+ if ( ( (bgColor != bgTransparent) && (bgColor != newc.rgb()) ) ||
+ ( bgSize != QSize(xWidth, xHeight)) )
+ {
+ delete bg; bg = 0;
+ }
+
+ if (bg)
+ return *bg;
+
+ const QPixmap &r = pixmap();
+
+ if (r.isNull()) return r;
+
+ // no error indication for background images
+ if(m_hadError||m_wasBlocked) return *Cache::nullPixmap;
+
+ bool isvalid = newc.isValid();
+
+ const QPixmap* src; //source for pretiling, if any
+
+ //See whether we should scale
+ if (xWidth != s.width() || xHeight != s.height()) {
+ src = &scaled_pixmap(xWidth, xHeight);
+ } else {
+ src = &r;
+ }
+
+ bgSize = QSize(xWidth, xHeight);
+
+ //See whether we can - and should - pre-blend
+ if (isvalid && (r.hasAlphaChannel() || r.mask() )) {
+ bg = new QPixmap(xWidth, xHeight, r.depth());
+ bg->fill(newc);
+ bitBlt(bg, 0, 0, src);
+ bgColor = newc.rgb();
+ src = bg;
+ } else {
+ bgColor = bgTransparent;
+ }
+
+ //See whether to pre-tile.
+ if ( w*h < 8192 )
+ {
+ if ( r.width() < BGMINWIDTH )
+ w = ((BGMINWIDTH-1) / xWidth + 1) * xWidth;
+ if ( r.height() < BGMINHEIGHT )
+ h = ((BGMINHEIGHT-1) / xHeight + 1) * xHeight;
+ }
+ if ( w != xWidth || h != xHeight )
+ {
+// kdDebug() << "pre-tiling " << s.width() << "," << s.height() << " to " << w << "," << h << endl;
+ QPixmap* oldbg = bg;
+ bg = new QPixmap(w, h, r.depth());
+
+ //Tile horizontally on the first stripe
+ for (int x = 0; x < w; x += xWidth)
+ copyBlt(bg, x, 0, src, 0, 0, xWidth, xHeight);
+
+ //Copy first stripe down
+ for (int y = xHeight; y < h; y += xHeight)
+ copyBlt(bg, 0, y, bg, 0, 0, w, xHeight);
+
+ if ( src == oldbg )
+ delete oldbg;
+ }
+
+ if (bg)
+ return *bg;
+
+ return *src;
+}
+
+const QPixmap &CachedImage::scaled_pixmap( int xWidth, int xHeight )
+{
+ if (scaled) {
+ if (scaled->width() == xWidth && scaled->height() == xHeight)
+ return *scaled;
+ delete scaled;
+ }
+ const QPixmap &r = pixmap();
+ if (r.isNull()) return r;
+
+// kdDebug() << "scaling " << r.width() << "," << r.height() << " to " << xWidth << "," << xHeight << endl;
+
+ QImage image = r.convertToImage().smoothScale(xWidth, xHeight);
+
+ scaled = new QPixmap(xWidth, xHeight, r.depth());
+ scaled->convertFromImage(image);
+
+ return *scaled;
+}
+
+
+const QPixmap &CachedImage::pixmap( ) const
+{
+ if(m_hadError)
+ return *Cache::brokenPixmap;
+
+ if(m_wasBlocked)
+ return *Cache::blockedPixmap;
+
+ if(m)
+ {
+ if(m->framePixmap().size() != m->getValidRect().size())
+ {
+ // pixmap is not yet completely loaded, so we
+ // return a clipped version. asserting here
+ // that the valid rect is always from 0/0 to fullwidth/ someheight
+ if(!pixPart) pixPart = new QPixmap();
+
+ (*pixPart) = m->framePixmap();
+ if (m->getValidRect().size().isValid())
+ pixPart->resize(m->getValidRect().size());
+ else
+ pixPart->resize(0, 0);
+ return *pixPart;
+ }
+ else
+ return m->framePixmap();
+ }
+ else if(p)
+ return *p;
+
+ return *Cache::nullPixmap;
+}
+
+
+QSize CachedImage::pixmap_size() const
+{
+ if (m_wasBlocked) return Cache::blockedPixmap->size();
+ return (m_hadError ? Cache::brokenPixmap->size() : m ? m->framePixmap().size() : ( p ? p->size() : QSize()));
+}
+
+
+QRect CachedImage::valid_rect() const
+{
+ if (m_wasBlocked) return Cache::blockedPixmap->rect();
+ return (m_hadError ? Cache::brokenPixmap->rect() : m ? m->getValidRect() : ( p ? p->rect() : QRect()) );
+}
+
+
+void CachedImage::do_notify(const QPixmap& p, const QRect& r)
+{
+ for (QPtrDictIterator<CachedObjectClient> it( m_clients ); it.current();)
+ it()->setPixmap( p, r, this);
+}
+
+
+void CachedImage::movieUpdated( const QRect& r )
+{
+#ifdef LOADER_DEBUG
+ qDebug("movie updated %d/%d/%d/%d, pixmap size %d/%d", r.x(), r.y(), r.right(), r.bottom(),
+ m->framePixmap().size().width(), m->framePixmap().size().height());
+#endif
+
+ do_notify(m->framePixmap(), r);
+}
+
+void CachedImage::movieStatus(int status)
+{
+#ifdef LOADER_DEBUG
+ qDebug("movieStatus(%d)", status);
+#endif
+
+ // ### the html image objects are supposed to send the load event after every frame (according to
+ // netscape). We have a problem though where an image is present, and js code creates a new Image object,
+ // which uses the same CachedImage, the one in the document is not supposed to be notified
+
+ // just another Qt 2.2.0 bug. we cannot call
+ // QMovie::frameImage if we're after QMovie::EndOfMovie
+ if(status == QMovie::EndOfFrame)
+ {
+ const QImage& im = m->frameImage();
+ monochrome = ( ( im.depth() <= 8 ) && ( im.numColors() - int( im.hasAlphaBuffer() ) <= 2 ) );
+ for (int i = 0; monochrome && i < im.numColors(); ++i)
+ if (im.colorTable()[i] != qRgb(0xff, 0xff, 0xff) &&
+ im.colorTable()[i] != qRgb(0x00, 0x00, 0x00))
+ monochrome = false;
+ if( (im.width() < 5 || im.height() < 5) && im.hasAlphaBuffer()) // only evaluate for small images
+ {
+ QImage am = im.createAlphaMask();
+ if(am.depth() == 1)
+ {
+ bool solid = false;
+ for(int y = 0; y < am.height(); y++)
+ for(int x = 0; x < am.width(); x++)
+ if(am.pixelIndex(x, y)) {
+ solid = true;
+ break;
+ }
+ isFullyTransparent = (!solid);
+ }
+ }
+
+ // we have to delete our tiled bg variant here
+ // because the frame has changed (in order to keep it in sync)
+ delete bg;
+ bg = 0;
+ }
+
+ if((status == QMovie::EndOfMovie && (!m || m->frameNumber() <= 1)) ||
+ ((status == QMovie::EndOfLoop) && (m_showAnimations == KHTMLSettings::KAnimationLoopOnce)) ||
+ ((status == QMovie::EndOfFrame) && (m_showAnimations == KHTMLSettings::KAnimationDisabled))
+ )
+ {
+ if(imgSource)
+ {
+ setShowAnimations( KHTMLSettings::KAnimationDisabled );
+
+ // monochrome alphamasked images are usually about 10000 times
+ // faster to draw, so this is worth the hack
+ if (p && monochrome && p->depth() > 1)
+ {
+ QPixmap* pix = new QPixmap;
+ pix->convertFromImage( p->convertToImage().convertDepth( 1 ), MonoOnly|AvoidDither );
+ if ( p->mask() )
+ pix->setMask( *p->mask() );
+ delete p;
+ p = pix;
+ monochrome = false;
+ }
+ }
+ for (QPtrDictIterator<CachedObjectClient> it( m_clients ); it.current();)
+ it()->notifyFinished( this );
+ m_status = Cached; //all done
+ }
+
+#if 0
+ if((status == QMovie::EndOfFrame) || (status == QMovie::EndOfMovie))
+ {
+#ifdef LOADER_DEBUG
+ QRect r(valid_rect());
+ qDebug("movie Status frame update %d/%d/%d/%d, pixmap size %d/%d", r.x(), r.y(), r.right(), r.bottom(),
+ pixmap().size().width(), pixmap().size().height());
+#endif
+ do_notify(pixmap(), valid_rect());
+ }
+#endif
+}
+
+void CachedImage::movieResize(const QSize& /*s*/)
+{
+ do_notify(m->framePixmap(), QRect());
+}
+
+void CachedImage::setShowAnimations( KHTMLSettings::KAnimationAdvice showAnimations )
+{
+ m_showAnimations = showAnimations;
+ if ( (m_showAnimations == KHTMLSettings::KAnimationDisabled) && imgSource ) {
+ imgSource->cleanBuffer();
+ delete p;
+ p = new QPixmap(m->framePixmap());
+ m->disconnectUpdate( this, SLOT( movieUpdated( const QRect &) ));
+ m->disconnectStatus( this, SLOT( movieStatus( int ) ));
+ m->disconnectResize( this, SLOT( movieResize( const QSize& ) ) );
+ QTimer::singleShot(0, this, SLOT( deleteMovie()));
+ imgSource = 0;
+ }
+}
+
+void CachedImage::pauseAnimations()
+{
+ if ( m ) m->pause();
+}
+
+void CachedImage::resumeAnimations()
+{
+ if ( m ) m->unpause();
+}
+
+
+void CachedImage::deleteMovie()
+{
+ delete m; m = 0;
+}
+
+void CachedImage::clear()
+{
+ delete m; m = 0;
+ delete p; p = 0;
+ delete bg; bg = 0;
+ delete scaled; scaled = 0;
+ bgColor = qRgba( 0, 0, 0, 0xff );
+ bgSize = QSize(-1,-1);
+ delete pixPart; pixPart = 0;
+
+ formatType = 0;
+ typeChecked = false;
+ setSize(0);
+
+ // No need to delete imageSource - QMovie does it for us
+ imgSource = 0;
+}
+
+void CachedImage::data ( QBuffer &_buffer, bool eof )
+{
+#ifdef LOADER_DEBUG
+ kdDebug( 6060 ) << this << "in CachedImage::data(buffersize " << _buffer.buffer().size() <<", eof=" << eof << endl;
+#endif
+ if ( !typeChecked )
+ {
+ // don't attempt incremental loading if we have all the data already
+ if (!eof)
+ {
+ formatType = QImageDecoder::formatName( (const uchar*)_buffer.buffer().data(), _buffer.size());
+ if ( formatType && strcmp( formatType, "PNG" ) == 0 )
+ formatType = 0; // Some png files contain multiple images, we want to show only the first one
+ }
+
+ typeChecked = true;
+
+ if ( formatType ) // movie format exists
+ {
+ imgSource = new ImageSource( _buffer.buffer());
+ m = new QMovie( imgSource, 8192 );
+ m->connectUpdate( this, SLOT( movieUpdated( const QRect &) ));
+ m->connectStatus( this, SLOT( movieStatus(int)));
+ m->connectResize( this, SLOT( movieResize( const QSize& ) ) );
+ }
+ }
+
+ if ( imgSource )
+ {
+ imgSource->setEOF(eof);
+ imgSource->maybeReady();
+ }
+
+ if(eof)
+ {
+ // QMovie currently doesn't support all kinds of image formats
+ // so we need to use a QPixmap here when we finished loading the complete
+ // picture and display it then all at once.
+ if(typeChecked && !formatType)
+ {
+#ifdef CACHE_DEBUG
+ kdDebug(6060) << "CachedImage::data(): reloading as pixmap:" << endl;
+#endif
+ p = new QPixmap;
+ {
+ QBuffer buffer(_buffer.buffer());
+ buffer.open(IO_ReadOnly);
+ QImageIO io( &buffer, 0 );
+ io.setGamma(2.2); // hardcoded "reasonable value"
+ bool result = io.read();
+ if (result) p->convertFromImage(io.image(), 0);
+ }
+
+ // set size of image.
+#ifdef CACHE_DEBUG
+ kdDebug(6060) << "CachedImage::data(): image is null: " << p->isNull() << endl;
+#endif
+ if(p->isNull())
+ {
+ m_hadError = true;
+ do_notify(pixmap(), QRect(0, 0, 16, 16)); // load "broken image" icon
+ }
+ else
+ do_notify(*p, p->rect());
+
+ for (QPtrDictIterator<CachedObjectClient> it( m_clients ); it.current();)
+ it()->notifyFinished( this );
+ m_status = Cached; //all done
+ }
+ }
+}
+
+void CachedImage::finish()
+{
+ Status oldStatus = m_status;
+ CachedObject::finish();
+ if ( oldStatus != m_status ) {
+ const QPixmap &pm = pixmap();
+ do_notify( pm, pm.rect() );
+ }
+ QSize s = pixmap_size();
+ setSize( s.width() * s.height() * 2);
+}
+
+
+void CachedImage::error( int /*err*/, const char* /*text*/ )
+{
+ clear();
+ typeChecked = true;
+ m_hadError = true;
+ m_loading = false;
+ do_notify(pixmap(), QRect(0, 0, 16, 16));
+ for (QPtrDictIterator<CachedObjectClient> it( m_clients ); it.current();)
+ it()->notifyFinished(this);
+}
+
+// ------------------------------------------------------------------------------------------
+
+Request::Request(DocLoader* dl, CachedObject *_object, bool _incremental)
+{
+ object = _object;
+ object->setRequest(this);
+ incremental = _incremental;
+ m_docLoader = dl;
+}
+
+Request::~Request()
+{
+ object->setRequest(0);
+}
+
+// ------------------------------------------------------------------------------------------
+
+DocLoader::DocLoader(KHTMLPart* part, DocumentImpl* doc)
+{
+ m_cachePolicy = KIO::CC_Verify;
+ m_expireDate = 0;
+ m_creationDate = time(0);
+ m_bautoloadImages = true;
+ m_showAnimations = KHTMLSettings::KAnimationEnabled;
+ m_part = part;
+ m_doc = doc;
+
+ Cache::docloader->append( this );
+}
+
+DocLoader::~DocLoader()
+{
+ Cache::loader()->cancelRequests( this );
+ Cache::docloader->remove( this );
+}
+
+void DocLoader::setCacheCreationDate(time_t _creationDate)
+{
+ if (_creationDate)
+ m_creationDate = _creationDate;
+ else
+ m_creationDate = time(0); // Now
+}
+
+void DocLoader::setExpireDate(time_t _expireDate, bool relative)
+{
+ if (relative)
+ m_expireDate = _expireDate + m_creationDate; // Relative date
+ else
+ m_expireDate = _expireDate; // Absolute date
+#ifdef CACHE_DEBUG
+ kdDebug(6061) << "docLoader: " << m_expireDate - time(0) << " seconds left until reload required.\n";
+#endif
+}
+
+void DocLoader::insertCachedObject( CachedObject* o ) const
+{
+ if ( m_docObjects.find(o) )
+ return;
+ m_docObjects.insert( o, o );
+ if ( m_docObjects.count() > 3 * m_docObjects.size() )
+ m_docObjects.resize(khtml::nextSeed( m_docObjects.size() ) );
+}
+
+bool DocLoader::needReload(CachedObject *existing, const QString& fullURL)
+{
+ bool reload = false;
+ if (m_cachePolicy == KIO::CC_Verify)
+ {
+ if (!m_reloadedURLs.contains(fullURL))
+ {
+ if (existing && existing->isExpired())
+ {
+ Cache::removeCacheEntry(existing);
+ m_reloadedURLs.append(fullURL);
+ reload = true;
+ }
+ }
+ }
+ else if ((m_cachePolicy == KIO::CC_Reload) || (m_cachePolicy == KIO::CC_Refresh))
+ {
+ if (!m_reloadedURLs.contains(fullURL))
+ {
+ if (existing)
+ {
+ Cache::removeCacheEntry(existing);
+ }
+ m_reloadedURLs.append(fullURL);
+ reload = true;
+ }
+ }
+ return reload;
+}
+
+#define DOCLOADER_SECCHECK(doRedirectCheck) \
+ KURL fullURL (m_doc->completeURL( url.string() )); \
+ if ( !fullURL.isValid() || \
+ ( m_part && m_part->onlyLocalReferences() && fullURL.protocol() != "file" && fullURL.protocol() != "data") || \
+ doRedirectCheck && ( kapp && m_doc && !kapp->authorizeURLAction("redirect", m_doc->URL(), fullURL))) \
+ return 0L;
+
+CachedImage *DocLoader::requestImage( const DOM::DOMString &url)
+{
+ DOCLOADER_SECCHECK(true);
+
+ CachedImage* i = Cache::requestObject<CachedImage, CachedObject::Image>( this, fullURL, 0);
+
+ if (i && i->status() == CachedObject::Unknown && autoloadImages())
+ Cache::loader()->load(this, i, true);
+
+ return i;
+}
+
+CachedCSSStyleSheet *DocLoader::requestStyleSheet( const DOM::DOMString &url, const QString& charset,
+ const char *accept, bool userSheet )
+{
+ DOCLOADER_SECCHECK(!userSheet);
+
+ CachedCSSStyleSheet* s = Cache::requestObject<CachedCSSStyleSheet, CachedObject::CSSStyleSheet>( this, fullURL, accept );
+ if ( s && !charset.isEmpty() ) {
+ s->setCharsetHint( charset );
+ }
+ return s;
+}
+
+CachedScript *DocLoader::requestScript( const DOM::DOMString &url, const QString& charset)
+{
+ DOCLOADER_SECCHECK(true);
+ if ( ! KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(fullURL.host()) ||
+ KHTMLFactory::defaultHTMLSettings()->isAdFiltered(fullURL.url()))
+ return 0L;
+
+ CachedScript* s = Cache::requestObject<CachedScript, CachedObject::Script>( this, fullURL, 0 );
+ if ( s && !charset.isEmpty() )
+ s->setCharset( charset );
+ return s;
+}
+
+#undef DOCLOADER_SECCHECK
+
+void DocLoader::setAutoloadImages( bool enable )
+{
+ if ( enable == m_bautoloadImages )
+ return;
+
+ m_bautoloadImages = enable;
+
+ if ( !m_bautoloadImages ) return;
+
+ for ( QPtrDictIterator<CachedObject> it( m_docObjects ); it.current(); ++it )
+ if ( it.current()->type() == CachedObject::Image )
+ {
+ CachedImage *img = const_cast<CachedImage*>( static_cast<const CachedImage *>( it.current()) );
+
+ CachedObject::Status status = img->status();
+ if ( status != CachedObject::Unknown )
+ continue;
+
+ Cache::loader()->load(this, img, true);
+ }
+}
+
+void DocLoader::setShowAnimations( KHTMLSettings::KAnimationAdvice showAnimations )
+{
+ if ( showAnimations == m_showAnimations ) return;
+ m_showAnimations = showAnimations;
+
+ for ( QPtrDictIterator<CachedObject> it( m_docObjects ); it.current(); ++it )
+ if ( it.current()->type() == CachedObject::Image )
+ {
+ CachedImage *img = const_cast<CachedImage*>( static_cast<const CachedImage *>( it.current() ) );
+
+ img->setShowAnimations( m_showAnimations );
+ }
+}
+
+void DocLoader::pauseAnimations()
+{
+ for ( QPtrDictIterator<CachedObject> it( m_docObjects ); it.current(); ++it )
+ if ( it.current()->type() == CachedObject::Image )
+ {
+ CachedImage *img = const_cast<CachedImage*>( static_cast<const CachedImage *>( it.current() ) );
+
+ img->pauseAnimations();
+ }
+}
+
+void DocLoader::resumeAnimations()
+{
+ for ( QPtrDictIterator<CachedObject> it( m_docObjects ); it.current(); ++it )
+ if ( it.current()->type() == CachedObject::Image )
+ {
+ CachedImage *img = const_cast<CachedImage*>( static_cast<const CachedImage *>( it.current() ) );
+
+ img->resumeAnimations();
+ }
+}
+
+// ------------------------------------------------------------------------------------------
+
+Loader::Loader() : QObject()
+{
+ m_requestsPending.setAutoDelete( true );
+ m_requestsLoading.setAutoDelete( true );
+ connect(&m_timer, SIGNAL(timeout()), this, SLOT( servePendingRequests() ) );
+}
+
+void Loader::load(DocLoader* dl, CachedObject *object, bool incremental)
+{
+ Request *req = new Request(dl, object, incremental);
+ m_requestsPending.append(req);
+
+ emit requestStarted( req->m_docLoader, req->object );
+
+ m_timer.start(0, true);
+}
+
+void Loader::servePendingRequests()
+{
+ while ( (m_requestsPending.count() != 0) && (m_requestsLoading.count() < MAX_JOB_COUNT) )
+ {
+ // get the first pending request
+ Request *req = m_requestsPending.take(0);
+
+#ifdef LOADER_DEBUG
+ kdDebug( 6060 ) << "starting Loader url=" << req->object->url().string() << endl;
+#endif
+
+ KURL u(req->object->url().string());
+ KIO::TransferJob* job = KIO::get( u, false, false /*no GUI*/);
+
+ job->addMetaData("cache", KIO::getCacheControlString(req->object->cachePolicy()));
+ if (!req->object->accept().isEmpty())
+ job->addMetaData("accept", req->object->accept());
+ if ( req->m_docLoader )
+ {
+ job->addMetaData( "referrer", req->m_docLoader->doc()->URL().url() );
+
+ KHTMLPart *part = req->m_docLoader->part();
+ if (part )
+ {
+ job->addMetaData( "cross-domain", part->toplevelURL().url() );
+ if (part->widget())
+ job->setWindow (part->widget()->topLevelWidget());
+ }
+ }
+
+ connect( job, SIGNAL( result( KIO::Job * ) ), this, SLOT( slotFinished( KIO::Job * ) ) );
+ connect( job, SIGNAL( data( KIO::Job*, const QByteArray &)),
+ SLOT( slotData( KIO::Job*, const QByteArray &)));
+
+ if ( req->object->schedule() )
+ KIO::Scheduler::scheduleJob( job );
+
+ m_requestsLoading.insert(job, req);
+ }
+}
+
+void Loader::slotFinished( KIO::Job* job )
+{
+ Request *r = m_requestsLoading.take( job );
+ KIO::TransferJob* j = static_cast<KIO::TransferJob*>(job);
+
+ if ( !r )
+ return;
+
+ if (j->error() || j->isErrorPage())
+ {
+#ifdef LOADER_DEBUG
+ kdDebug(6060) << "Loader::slotFinished, with error. job->error()= " << j->error() << " job->isErrorPage()=" << j->isErrorPage() << endl;
+#endif
+ r->object->error( job->error(), job->errorText().ascii() );
+ emit requestFailed( r->m_docLoader, r->object );
+ }
+ else
+ {
+ QString cs = j->queryMetaData("charset");
+ if (!cs.isEmpty()) r->object->setCharset(cs);
+ r->object->data(r->m_buffer, true);
+ emit requestDone( r->m_docLoader, r->object );
+ time_t expireDate = j->queryMetaData("expire-date").toLong();
+#ifdef LOADER_DEBUG
+ kdDebug(6060) << "Loader::slotFinished, url = " << j->url().url() << endl;
+#endif
+ r->object->setExpireDate( expireDate );
+
+ if ( r->object->type() == CachedObject::Image ) {
+ QString fn = j->queryMetaData("content-disposition");
+ static_cast<CachedImage*>( r->object )->setSuggestedFilename(fn);
+#ifdef IMAGE_TITLES
+ static_cast<CachedImage*>( r->object )->setSuggestedTitle(fn);
+ KTempFile tf;
+ tf.setAutoDelete(true);
+ tf.file()->writeBlock((const char*)r->m_buffer.buffer().data(), r->m_buffer.size());
+ tf.sync();
+ KFileMetaInfo kfmi(tf.name());
+ if (!kfmi.isEmpty()) {
+ KFileMetaInfoItem i = kfmi.item("Name");
+ if (i.isValid()) {
+ static_cast<CachedImage*>(r->object)->setSuggestedTitle(i.string());
+ } else {
+ i = kfmi.item("Title");
+ if (i.isValid()) {
+ static_cast<CachedImage*>(r->object)->setSuggestedTitle(i.string());
+ }
+ }
+ }
+#endif
+ }
+ }
+
+ r->object->finish();
+
+#ifdef LOADER_DEBUG
+ kdDebug( 6060 ) << "Loader:: JOB FINISHED " << r->object << ": " << r->object->url().string() << endl;
+#endif
+
+ delete r;
+
+ if ( (m_requestsPending.count() != 0) && (m_requestsLoading.count() < MAX_JOB_COUNT / 2) )
+ m_timer.start(0, true);
+}
+
+void Loader::slotData( KIO::Job*job, const QByteArray &data )
+{
+ Request *r = m_requestsLoading[job];
+ if(!r) {
+ kdDebug( 6060 ) << "got data for unknown request!" << endl;
+ return;
+ }
+
+ if ( !r->m_buffer.isOpen() )
+ r->m_buffer.open( IO_WriteOnly );
+
+ r->m_buffer.writeBlock( data.data(), data.size() );
+
+ if(r->incremental)
+ r->object->data( r->m_buffer, false );
+}
+
+int Loader::numRequests( DocLoader* dl ) const
+{
+ int res = 0;
+
+ QPtrListIterator<Request> pIt( m_requestsPending );
+ for (; pIt.current(); ++pIt )
+ if ( pIt.current()->m_docLoader == dl )
+ res++;
+
+ QPtrDictIterator<Request> lIt( m_requestsLoading );
+ for (; lIt.current(); ++lIt )
+ if ( lIt.current()->m_docLoader == dl )
+ res++;
+
+ return res;
+}
+
+void Loader::cancelRequests( DocLoader* dl )
+{
+ QPtrListIterator<Request> pIt( m_requestsPending );
+ while ( pIt.current() ) {
+ if ( pIt.current()->m_docLoader == dl )
+ {
+ CDEBUG << "canceling pending request for " << pIt.current()->object->url().string() << endl;
+ Cache::removeCacheEntry( pIt.current()->object );
+ m_requestsPending.remove( pIt );
+ }
+ else
+ ++pIt;
+ }
+
+ //kdDebug( 6060 ) << "got " << m_requestsLoading.count() << "loading requests" << endl;
+
+ QPtrDictIterator<Request> lIt( m_requestsLoading );
+ while ( lIt.current() )
+ {
+ if ( lIt.current()->m_docLoader == dl )
+ {
+ //kdDebug( 6060 ) << "canceling loading request for " << lIt.current()->object->url().string() << endl;
+ KIO::Job *job = static_cast<KIO::Job *>( lIt.currentKey() );
+ Cache::removeCacheEntry( lIt.current()->object );
+ m_requestsLoading.remove( lIt.currentKey() );
+ job->kill();
+ //emit requestFailed( dl, pIt.current()->object );
+ }
+ else
+ ++lIt;
+ }
+}
+
+KIO::Job *Loader::jobForRequest( const DOM::DOMString &url ) const
+{
+ QPtrDictIterator<Request> it( m_requestsLoading );
+
+ for (; it.current(); ++it )
+ {
+ CachedObject *obj = it.current()->object;
+
+ if ( obj && obj->url() == url )
+ return static_cast<KIO::Job *>( it.currentKey() );
+ }
+
+ return 0;
+}
+
+// ----------------------------------------------------------------------------
+
+
+QDict<CachedObject> *Cache::cache = 0;
+QPtrList<DocLoader>* Cache::docloader = 0;
+QPtrList<CachedObject> *Cache::freeList = 0;
+Loader *Cache::m_loader = 0;
+
+int Cache::maxSize = DEFCACHESIZE;
+int Cache::totalSizeOfLRU;
+
+QPixmap *Cache::nullPixmap = 0;
+QPixmap *Cache::brokenPixmap = 0;
+QPixmap *Cache::blockedPixmap = 0;
+
+void Cache::init()
+{
+ if ( !cache )
+ cache = new QDict<CachedObject>(401, true);
+
+ if ( !docloader )
+ docloader = new QPtrList<DocLoader>;
+
+ if ( !nullPixmap )
+ nullPixmap = new QPixmap;
+
+ if ( !brokenPixmap )
+ brokenPixmap = new QPixmap(KHTMLFactory::instance()->iconLoader()->loadIcon("file_broken", KIcon::Desktop, 16, KIcon::DisabledState));
+
+ if ( !blockedPixmap ) {
+ blockedPixmap = new QPixmap();
+ blockedPixmap->loadFromData(blocked_icon_data, blocked_icon_len);
+ }
+
+ if ( !m_loader )
+ m_loader = new Loader();
+
+ if ( !freeList ) {
+ freeList = new QPtrList<CachedObject>;
+ freeList->setAutoDelete(true);
+ }
+}
+
+void Cache::clear()
+{
+ if ( !cache ) return;
+#ifdef CACHE_DEBUG
+ kdDebug( 6060 ) << "Cache: CLEAR!" << endl;
+ statistics();
+#endif
+ cache->setAutoDelete( true );
+
+#ifndef NDEBUG
+ bool crash = false;
+ for (QDictIterator<CachedObject> it(*cache); it.current(); ++it) {
+ if (!it.current()->canDelete()) {
+ kdDebug( 6060 ) << " Object in cache still linked to" << endl;
+ kdDebug( 6060 ) << " -> URL: " << it.current()->url() << endl;
+ kdDebug( 6060 ) << " -> #clients: " << it.current()->count() << endl;
+ crash = true;
+// assert(it.current()->canDelete());
+ }
+ }
+ for (freeList->first(); freeList->current(); freeList->next()) {
+ if (!freeList->current()->canDelete()) {
+ kdDebug( 6060 ) << " Object in freelist still linked to" << endl;
+ kdDebug( 6060 ) << " -> URL: " << freeList->current()->url() << endl;
+ kdDebug( 6060 ) << " -> #clients: " << freeList->current()->count() << endl;
+ crash = true;
+ /*
+ QPtrDictIterator<CachedObjectClient> it(freeList->current()->m_clients);
+ for(;it.current(); ++it) {
+ if (dynamic_cast<RenderObject*>(it.current())) {
+ kdDebug( 6060 ) << " --> RenderObject" << endl;
+ } else
+ kdDebug( 6060 ) << " --> Something else" << endl;
+ }*/
+ }
+// assert(freeList->current()->canDelete());
+ }
+ assert(!crash);
+#endif
+
+ delete cache; cache = 0;
+ delete nullPixmap; nullPixmap = 0;
+ delete brokenPixmap; brokenPixmap = 0;
+ delete blockedPixmap; blockedPixmap = 0;
+ delete m_loader; m_loader = 0;
+ delete docloader; docloader = 0;
+ delete freeList; freeList = 0;
+}
+
+template<typename CachedObjectType, enum CachedObject::Type CachedType>
+CachedObjectType* Cache::requestObject( DocLoader* dl, const KURL& kurl, const char* accept )
+{
+ KIO::CacheControl cachePolicy = dl ? dl->cachePolicy() : KIO::CC_Verify;
+
+ QString url = kurl.url();
+ CachedObject* o = cache->find(url);
+
+ if ( o && o->type() != CachedType ) {
+ removeCacheEntry( o );
+ o = 0;
+ }
+
+ if ( o && dl->needReload( o, url ) ) {
+ o = 0;
+ assert( cache->find( url ) == 0 );
+ }
+
+ if(!o)
+ {
+#ifdef CACHE_DEBUG
+ kdDebug( 6060 ) << "Cache: new: " << kurl.url() << endl;
+#endif
+ CachedObjectType* cot = new CachedObjectType(dl, url, cachePolicy, accept);
+ cache->insert( url, cot );
+ if ( cot->allowInLRUList() )
+ insertInLRUList( cot );
+ o = cot;
+ }
+#ifdef CACHE_DEBUG
+ else {
+ kdDebug( 6060 ) << "Cache: using pending/cached: " << kurl.url() << endl;
+ }
+#endif
+
+
+ dl->insertCachedObject( o );
+
+ return static_cast<CachedObjectType *>(o);
+}
+
+void Cache::preloadStyleSheet( const QString &url, const QString &stylesheet_data)
+{
+ CachedObject *o = cache->find(url);
+ if(o)
+ removeCacheEntry(o);
+
+ CachedCSSStyleSheet *stylesheet = new CachedCSSStyleSheet(url, stylesheet_data);
+ cache->insert( url, stylesheet );
+}
+
+void Cache::preloadScript( const QString &url, const QString &script_data)
+{
+ CachedObject *o = cache->find(url);
+ if(o)
+ removeCacheEntry(o);
+
+ CachedScript *script = new CachedScript(url, script_data);
+ cache->insert( url, script );
+}
+
+void Cache::flush(bool force)
+{
+ init();
+
+ if ( force || totalSizeOfLRU > maxSize + maxSize/4) {
+ for ( int i = MAX_LRU_LISTS-1; i >= 0 && totalSizeOfLRU > maxSize; --i )
+ while ( totalSizeOfLRU > maxSize && m_LRULists[i].m_tail )
+ removeCacheEntry( m_LRULists[i].m_tail );
+
+#ifdef CACHE_DEBUG
+ statistics();
+#endif
+ }
+
+ for ( freeList->first(); freeList->current(); ) {
+ CachedObject* p = freeList->current();
+ if ( p->canDelete() )
+ freeList->remove();
+ else
+ freeList->next();
+ }
+
+}
+
+void Cache::setSize( int bytes )
+{
+ maxSize = bytes;
+ flush(true /* force */);
+}
+
+void Cache::statistics()
+{
+ CachedObject *o;
+ // this function is for debugging purposes only
+ init();
+
+ int size = 0;
+ int msize = 0;
+ int movie = 0;
+ int images = 0;
+ int scripts = 0;
+ int stylesheets = 0;
+ QDictIterator<CachedObject> it(*cache);
+ for(it.toFirst(); it.current(); ++it)
+ {
+ o = it.current();
+ switch(o->type()) {
+ case CachedObject::Image:
+ {
+ CachedImage *im = static_cast<CachedImage *>(o);
+ images++;
+ if(im->m != 0)
+ {
+ movie++;
+ msize += im->size();
+ }
+ break;
+ }
+ case CachedObject::CSSStyleSheet:
+ stylesheets++;
+ break;
+ case CachedObject::Script:
+ scripts++;
+ break;
+ }
+ size += o->size();
+ }
+ size /= 1024;
+
+ kdDebug( 6060 ) << "------------------------- image cache statistics -------------------" << endl;
+ kdDebug( 6060 ) << "Number of items in cache: " << cache->count() << endl;
+ kdDebug( 6060 ) << "Number of cached images: " << images << endl;
+ kdDebug( 6060 ) << "Number of cached movies: " << movie << endl;
+ kdDebug( 6060 ) << "Number of cached scripts: " << scripts << endl;
+ kdDebug( 6060 ) << "Number of cached stylesheets: " << stylesheets << endl;
+ kdDebug( 6060 ) << "pixmaps: allocated space approx. " << size << " kB" << endl;
+ kdDebug( 6060 ) << "movies : allocated space approx. " << msize/1024 << " kB" << endl;
+ kdDebug( 6060 ) << "--------------------------------------------------------------------" << endl;
+}
+
+void Cache::removeCacheEntry( CachedObject *object )
+{
+ QString key = object->url().string();
+
+ cache->remove( key );
+ removeFromLRUList( object );
+
+ for (const DocLoader* dl=docloader->first(); dl; dl=docloader->next() )
+ dl->removeCachedObject( object );
+
+ if ( !object->free() ) {
+ Cache::freeList->append( object );
+ object->m_free = true;
+ }
+}
+
+static inline int FastLog2(unsigned int j)
+{
+ unsigned int log2;
+ log2 = 0;
+ if (j & (j-1))
+ log2 += 1;
+ if (j >> 16)
+ log2 += 16, j >>= 16;
+ if (j >> 8)
+ log2 += 8, j >>= 8;
+ if (j >> 4)
+ log2 += 4, j >>= 4;
+ if (j >> 2)
+ log2 += 2, j >>= 2;
+ if (j >> 1)
+ log2 += 1;
+
+ return log2;
+}
+
+static LRUList* getLRUListFor(CachedObject* o)
+{
+ int accessCount = o->accessCount();
+ int queueIndex;
+ if (accessCount == 0) {
+ queueIndex = 0;
+ } else {
+ int sizeLog = FastLog2(o->size());
+ queueIndex = sizeLog/o->accessCount() - 1;
+ if (queueIndex < 0)
+ queueIndex = 0;
+ if (queueIndex >= MAX_LRU_LISTS)
+ queueIndex = MAX_LRU_LISTS-1;
+ }
+ return &m_LRULists[queueIndex];
+}
+
+void Cache::removeFromLRUList(CachedObject *object)
+{
+ CachedObject *next = object->m_next;
+ CachedObject *prev = object->m_prev;
+
+ LRUList* list = getLRUListFor(object);
+ CachedObject *&head = getLRUListFor(object)->m_head;
+
+ if (next == 0 && prev == 0 && head != object) {
+ return;
+ }
+
+ object->m_next = 0;
+ object->m_prev = 0;
+
+ if (next)
+ next->m_prev = prev;
+ else if (list->m_tail == object)
+ list->m_tail = prev;
+
+ if (prev)
+ prev->m_next = next;
+ else if (head == object)
+ head = next;
+
+ totalSizeOfLRU -= object->size();
+}
+
+void Cache::insertInLRUList(CachedObject *object)
+{
+ removeFromLRUList(object);
+
+ assert( object );
+ assert( !object->free() );
+ assert( object->canDelete() );
+ assert( object->allowInLRUList() );
+
+ LRUList* list = getLRUListFor(object);
+
+ CachedObject *&head = list->m_head;
+
+ object->m_next = head;
+ if (head)
+ head->m_prev = object;
+ head = object;
+
+ if (object->m_next == 0)
+ list->m_tail = object;
+
+ totalSizeOfLRU += object->size();
+}
+
+// --------------------------------------
+
+void CachedObjectClient::setPixmap(const QPixmap &, const QRect&, CachedImage *) {}
+void CachedObjectClient::setStyleSheet(const DOM::DOMString &/*url*/, const DOM::DOMString &/*sheet*/, const DOM::DOMString &/*charset*/) {}
+void CachedObjectClient::notifyFinished(CachedObject * /*finishedObj*/) {}
+void CachedObjectClient::error(int /*err*/, const QString &/*text*/) {}
+
+#undef CDEBUG
+
+#include "loader.moc"
diff --git a/khtml/misc/loader.h b/khtml/misc/loader.h
new file mode 100644
index 000000000..346e85f12
--- /dev/null
+++ b/khtml/misc/loader.h
@@ -0,0 +1,522 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
+ Copyright (C) 2001-2003 Dirk Mueller <mueller@kde.org>
+ Copyright (C) 2003 Apple Computer, Inc
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+ This class provides all functionality needed for loading images, style sheets and html
+ pages from the web. It has a memory cache for these objects.
+*/
+#ifndef _khtml_loader_h
+#define _khtml_loader_h
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <time.h>
+
+#include "loader_client.h"
+#ifdef HAVE_LIBJPEG
+#include "loader_jpeg.h"
+#endif
+
+#include <stdlib.h>
+#include <qptrlist.h>
+#include <qobject.h>
+#include <qptrdict.h>
+#include <qdict.h>
+#include <qpixmap.h>
+#include <qbuffer.h>
+#include <qstringlist.h>
+#include <qtextcodec.h>
+#include <qtimer.h>
+
+#include <kurl.h>
+#include <kio/global.h>
+
+#include <khtml_settings.h>
+#include <dom/dom_string.h>
+
+class QMovie;
+class KHTMLPart;
+
+namespace KIO {
+ class Job;
+ class TransferJob;
+}
+
+namespace DOM
+{
+ class CSSStyleSheetImpl;
+ class DocumentImpl;
+}
+
+namespace khtml
+{
+ class CachedObject;
+ class Request;
+ class DocLoader;
+
+ /**
+ * @internal
+ *
+ * A cached object. Classes who want to use this object should derive
+ * from CachedObjectClient, to get the function calls in case the requested data has arrived.
+ *
+ * This class also does the actual communication with kio and loads the file.
+ */
+ class CachedObject
+ {
+ public:
+ enum Type {
+ Image,
+ CSSStyleSheet,
+ Script
+ };
+
+ enum Status {
+ Unknown, // let imagecache decide what to do with it
+ New, // inserting new image
+ Pending, // only partially loaded
+ Persistent, // never delete this pixmap
+ Cached // regular case
+ };
+
+ CachedObject(const DOM::DOMString &url, Type type, KIO::CacheControl _cachePolicy, int size)
+ : m_url(url), m_type(type), m_cachePolicy(_cachePolicy),
+ m_expireDate(0), m_size(size)
+ {
+ m_status = Pending;
+ m_accessCount = 0;
+ m_cachePolicy = _cachePolicy;
+ m_request = 0;
+ m_deleted = false;
+ m_free = false;
+ m_hadError = false;
+ m_wasBlocked = false;
+ m_prev = m_next = 0;
+ }
+ virtual ~CachedObject();
+
+ virtual void data( QBuffer &buffer, bool eof) = 0;
+ virtual void error( int err, const char *text ) = 0;
+
+ const DOM::DOMString &url() const { return m_url; }
+ Type type() const { return m_type; }
+
+ virtual void ref(CachedObjectClient *consumer);
+ virtual void deref(CachedObjectClient *consumer);
+
+ int count() const { return m_clients.count(); }
+ int accessCount() const { return m_accessCount; }
+
+ void setStatus(Status s) { m_status = s; }
+ Status status() const { return m_status; }
+
+ virtual void setCharset( const QString& /*charset*/ ) {}
+
+ QTextCodec* codecForBuffer( const QString& charset, const QByteArray& buffer ) const;
+
+ int size() const { return m_size; }
+
+ bool isLoaded() const { return !m_loading; }
+
+ bool free() const { return m_free; }
+
+ KIO::CacheControl cachePolicy() const { return m_cachePolicy; }
+
+ void setRequest(Request *_request);
+
+ bool canDelete() const { return (m_clients.count() == 0 && !m_request); }
+
+ void setExpireDate(time_t _expireDate) { m_expireDate = _expireDate; }
+
+ bool isExpired() const;
+
+ virtual bool schedule() const { return false; }
+ virtual void finish();
+
+ /**
+ * List of acceptable mimetypes separated by ",". A mimetype may contain a wildcard.
+ */
+ // e.g. "text/*"
+ QString accept() const { return m_accept; }
+ void setAccept(const QString &_accept) { m_accept = _accept; }
+
+ protected:
+ void setSize(int size);
+ QPtrDict<CachedObjectClient> m_clients;
+ DOM::DOMString m_url;
+ QString m_accept;
+ Request *m_request;
+ Type m_type;
+ Status m_status;
+ int m_accessCount;
+ KIO::CacheControl m_cachePolicy;
+ time_t m_expireDate;
+ int m_size;
+ bool m_deleted : 1;
+ bool m_loading : 1;
+ bool m_free : 1;
+ bool m_hadError : 1;
+ bool m_wasBlocked : 1;
+
+ private:
+ bool allowInLRUList() const { return canDelete() && !m_free && status() != Persistent; }
+ CachedObject* m_next;
+ CachedObject* m_prev;
+ friend class Cache;
+ friend class ::KHTMLPart;
+ };
+
+
+ /**
+ * a cached style sheet. also used for loading xml documents.
+ *
+ * ### rename to CachedTextDoc or something since it's more generic than just for css
+ */
+ class CachedCSSStyleSheet : public CachedObject
+ {
+ public:
+ CachedCSSStyleSheet(DocLoader* dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy,
+ const char *accept);
+ CachedCSSStyleSheet(const DOM::DOMString &url, const QString &stylesheet_data);
+
+ const DOM::DOMString &sheet() const { return m_sheet; }
+
+ virtual void ref(CachedObjectClient *consumer);
+
+ virtual void data( QBuffer &buffer, bool eof );
+ virtual void error( int err, const char *text );
+
+ virtual bool schedule() const { return true; }
+ void setCharsetHint( const QString& charset ) { m_charsetHint = charset; }
+ void setCharset( const QString& charset ) { m_charset = charset; }
+
+ protected:
+ void checkNotify();
+
+ DOM::DOMString m_sheet;
+ QString m_charset;
+ QString m_charsetHint;
+ int m_err;
+ QString m_errText;
+ };
+
+ /**
+ * a cached script
+ */
+ class CachedScript : public CachedObject
+ {
+ public:
+ CachedScript(DocLoader* dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, const char* accept );
+ CachedScript(const DOM::DOMString &url, const QString &script_data);
+
+ const DOM::DOMString &script() const { return m_script; }
+
+ virtual void ref(CachedObjectClient *consumer);
+
+ virtual void data( QBuffer &buffer, bool eof );
+ virtual void error( int err, const char *text );
+
+ virtual bool schedule() const { return false; }
+
+ void checkNotify();
+
+ bool isLoaded() const { return !m_loading; }
+ void setCharset( const QString& charset ) { m_charset = charset; }
+
+ protected:
+ QString m_charset;
+ DOM::DOMString m_script;
+ };
+
+ class ImageSource;
+
+ /**
+ * a cached image
+ */
+ class CachedImage : public QObject, public CachedObject
+ {
+ Q_OBJECT
+ public:
+ CachedImage(DocLoader* dl, const DOM::DOMString &url, KIO::CacheControl cachePolicy, const char* accept);
+ virtual ~CachedImage();
+
+ const QPixmap &pixmap() const;
+ const QPixmap &scaled_pixmap(int xWidth, int xHeight);
+ const QPixmap &tiled_pixmap(const QColor& bg, int xWidth = -1, int xHeight = -1);
+
+ QSize pixmap_size() const; // returns the size of the complete (i.e. when finished) loading
+ QRect valid_rect() const; // returns the rectangle of pixmap that has been loaded already
+
+ bool canRender() const { return !isErrorImage() && pixmap_size().width() > 0 && pixmap_size().height() > 0; }
+ void ref(CachedObjectClient *consumer);
+ virtual void deref(CachedObjectClient *consumer);
+
+ virtual void data( QBuffer &buffer, bool eof );
+ virtual void error( int err, const char *text );
+
+ bool isTransparent() const { return isFullyTransparent; }
+ bool isErrorImage() const { return m_hadError; }
+ bool isBlockedImage() const { return m_wasBlocked; }
+ const QString& suggestedFilename() const { return m_suggestedFilename; }
+ void setSuggestedFilename( const QString& s ) { m_suggestedFilename = s; }
+#ifdef IMAGE_TITLES
+ const QString& suggestedTitle() const { return m_suggestedTitle; }
+ void setSuggestedTitle( const QString& s ) { m_suggestedTitle = s; }
+#else
+ const QString& suggestedTitle() const { return m_suggestedFilename; }
+#endif
+
+ void setShowAnimations( KHTMLSettings::KAnimationAdvice );
+ void pauseAnimations();
+ void resumeAnimations();
+
+ virtual bool schedule() const { return true; }
+
+ virtual void finish();
+
+ protected:
+ void clear();
+
+ private slots:
+ /**
+ * gets called, whenever a QMovie changes frame
+ */
+ void movieUpdated( const QRect &rect );
+ void movieStatus(int);
+ void movieResize(const QSize&);
+ void deleteMovie();
+
+ private:
+ void do_notify(const QPixmap& p, const QRect& r);
+
+ QString m_suggestedFilename;
+#ifdef IMAGE_TITLES
+ QString m_suggestedTitle;
+#endif
+ QMovie* m;
+ QPixmap* p;
+ QPixmap* scaled;
+ QPixmap* bg;
+ QRgb bgColor;
+ QSize bgSize;
+ mutable QPixmap* pixPart;
+
+ ImageSource* imgSource;
+ const char* formatType; // Is the name of the movie format type
+
+ int width;
+ int height;
+
+ // Is set if movie format type ( incremental/animation) was checked
+ bool typeChecked : 1;
+ bool isFullyTransparent : 1;
+ bool monochrome : 1;
+ KHTMLSettings::KAnimationAdvice m_showAnimations : 2;
+
+ friend class Cache;
+ friend class ::KHTMLPart;
+ };
+
+ /**
+ * @internal
+ *
+ * Manages the loading of scripts/images/stylesheets for a particular document
+ */
+ class DocLoader
+ {
+ public:
+ DocLoader(KHTMLPart*, DOM::DocumentImpl*);
+ ~DocLoader();
+
+ CachedImage *requestImage( const DOM::DOMString &url);
+ CachedCSSStyleSheet *requestStyleSheet( const DOM::DOMString &url, const QString& charsetHint,
+ const char *accept = "text/css", bool userSheet = false );
+ CachedScript *requestScript( const DOM::DOMString &url, const QString& charset);
+
+ bool autoloadImages() const { return m_bautoloadImages; }
+ KIO::CacheControl cachePolicy() const { return m_cachePolicy; }
+ KHTMLSettings::KAnimationAdvice showAnimations() const { return m_showAnimations; }
+ time_t expireDate() const { return m_expireDate; }
+ KHTMLPart* part() const { return m_part; }
+ DOM::DocumentImpl* doc() const { return m_doc; }
+
+ void setCacheCreationDate( time_t );
+ void setExpireDate( time_t, bool relative );
+ void setAutoloadImages( bool );
+ void setCachePolicy( KIO::CacheControl cachePolicy ) { m_cachePolicy = cachePolicy; }
+ void setShowAnimations( KHTMLSettings::KAnimationAdvice );
+ void pauseAnimations();
+ void resumeAnimations();
+ void insertCachedObject( CachedObject* o ) const;
+ void removeCachedObject( CachedObject* o) const { m_docObjects.remove( o ); }
+
+ private:
+ bool needReload(CachedObject *existing, const QString &fullUrl);
+
+ friend class Cache;
+ friend class DOM::DocumentImpl;
+ friend class ::KHTMLPart;
+
+ QStringList m_reloadedURLs;
+ mutable QPtrDict<CachedObject> m_docObjects;
+ time_t m_expireDate;
+ time_t m_creationDate;
+ KIO::CacheControl m_cachePolicy;
+ bool m_bautoloadImages : 1;
+ KHTMLSettings::KAnimationAdvice m_showAnimations : 2;
+ KHTMLPart* m_part;
+ DOM::DocumentImpl* m_doc;
+ };
+
+ /**
+ * @internal
+ */
+ class Request
+ {
+ public:
+ Request(DocLoader* dl, CachedObject *_object, bool _incremental);
+ ~Request();
+ bool incremental;
+ QBuffer m_buffer;
+ CachedObject *object;
+ DocLoader* m_docLoader;
+ };
+
+ /**
+ * @internal
+ */
+ class Loader : public QObject
+ {
+ Q_OBJECT
+
+ public:
+ Loader();
+
+ void load(DocLoader* dl, CachedObject *object, bool incremental = true);
+
+ int numRequests( DocLoader* dl ) const;
+ void cancelRequests( DocLoader* dl );
+
+ // may return 0L
+ KIO::Job *jobForRequest( const DOM::DOMString &url ) const;
+
+ signals:
+ void requestStarted( khtml::DocLoader* dl, khtml::CachedObject* obj );
+ void requestDone( khtml::DocLoader* dl, khtml::CachedObject *obj );
+ void requestFailed( khtml::DocLoader* dl, khtml::CachedObject *obj );
+
+ protected slots:
+ void slotFinished( KIO::Job * );
+ void slotData( KIO::Job *, const QByteArray & );
+ void servePendingRequests();
+
+ protected:
+ QPtrList<Request> m_requestsPending;
+ QPtrDict<Request> m_requestsLoading;
+#ifdef HAVE_LIBJPEG
+ KJPEGFormatType m_jpegloader;
+#endif
+ QTimer m_timer;
+ };
+
+ /**
+ * @internal
+ *
+ * Provides a cache/loader for objects needed for displaying the html page.
+ * At the moment these are stylesheets, scripts and images
+ */
+ class Cache
+ {
+ friend class DocLoader;
+
+ template<typename CachedObjectType, enum CachedObject::Type CachedType>
+ static CachedObjectType* requestObject( DocLoader* dl, const KURL& kurl, const char* accept );
+
+ public:
+ /**
+ * init the cache in case it's not already. This needs to get called once
+ * before using it.
+ */
+ KDE_EXPORT static void init();
+
+ /**
+ * Ask the cache for some url. Will return a cachedObject, and
+ * load the requested data in case it's not cached
+ * if the DocLoader is zero, the url must be full-qualified.
+ * Otherwise, it is automatically base-url expanded
+ */
+// static CachedImage *requestImage(const KURL& url)
+// { return Cache::requestObject<CachedImage, CachedObject::Image>( 0, url, 0 ); }
+
+ /**
+ * Pre-loads a stylesheet into the cache.
+ */
+ static void preloadStyleSheet(const QString &url, const QString &stylesheet_data);
+
+ /**
+ * Pre-loads a script into the cache.
+ */
+ static void preloadScript(const QString &url, const QString &script_data);
+
+ static void setSize( int bytes );
+ static int size() { return maxSize; };
+ static void statistics();
+ KDE_EXPORT static void flush(bool force=false);
+
+ /**
+ * clears the cache
+ * Warning: call this only at the end of your program, to clean
+ * up memory (useful for finding memory holes)
+ */
+ KDE_EXPORT static void clear();
+
+ static Loader *loader() { return m_loader; }
+
+ static QPixmap *nullPixmap;
+ static QPixmap *brokenPixmap;
+ static QPixmap *blockedPixmap;
+ static int cacheSize;
+
+ static void removeCacheEntry( CachedObject *object );
+
+ private:
+
+ static void checkLRUAndUncacheableListIntegrity();
+
+ friend class CachedObject;
+
+ static QDict<CachedObject> *cache;
+ static QPtrList<DocLoader>* docloader;
+ static QPtrList<CachedObject> *freeList;
+ static void insertInLRUList(CachedObject*);
+ static void removeFromLRUList(CachedObject*);
+
+ static int totalSizeOfLRU;
+ static int maxSize;
+
+ static Loader *m_loader;
+ };
+
+} // namespace
+
+#endif
diff --git a/khtml/misc/loader_client.h b/khtml/misc/loader_client.h
new file mode 100644
index 000000000..023f147c6
--- /dev/null
+++ b/khtml/misc/loader_client.h
@@ -0,0 +1,35 @@
+#ifndef LOADER_CLIENT_H
+#define LOADER_CLIENT_H
+
+#include <qpixmap.h>
+#include "dom/dom_string.h"
+
+namespace khtml {
+ class CachedObject;
+ class CachedImage;
+
+ /**
+ * @internal
+ *
+ * a client who wants to load stylesheets, images or scripts from the web has to
+ * inherit from this class and overload one of the 3 functions
+ *
+ */
+ class CachedObjectClient
+ {
+ public:
+ virtual ~CachedObjectClient();
+ // clipped pixmap (if it is not yet completely loaded,
+ // size of the complete (finished loading) pixmap
+ // rectangle of the part that has been loaded very recently
+ // pointer to us
+ // return whether we need manual update
+ // don't ref() or deref() elements in setPixmap!!
+ virtual void setPixmap(const QPixmap &, const QRect&, CachedImage *);
+ virtual void setStyleSheet(const DOM::DOMString &/*url*/, const DOM::DOMString &/*sheet*/, const DOM::DOMString &/*charset*/);
+ virtual void notifyFinished(CachedObject * /*finishedObj*/);
+ virtual void error(int err, const QString &text);
+ };
+}
+
+#endif
diff --git a/khtml/misc/loader_jpeg.cpp b/khtml/misc/loader_jpeg.cpp
new file mode 100644
index 000000000..4c9c97465
--- /dev/null
+++ b/khtml/misc/loader_jpeg.cpp
@@ -0,0 +1,548 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 2000 Dirk Mueller (mueller@kde.org)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_LIBJPEG
+// on some systems, libjpeg installs its config.h file which causes a conflict
+// and makes the compiler barf with "XXX already defined".
+#ifdef HAVE_STDLIB_H
+#undef HAVE_STDLIB_H
+#endif
+#include "loader_jpeg.h"
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <qdatetime.h>
+#include <kglobal.h>
+
+extern "C" {
+#define XMD_H
+#include <jpeglib.h>
+#undef const
+}
+
+
+#undef BUFFER_DEBUG
+//#define BUFFER_DEBUG
+
+#undef JPEG_DEBUG
+//#define JPEG_DEBUG
+
+// -----------------------------------------------------------------------------
+
+struct khtml_error_mgr : public jpeg_error_mgr {
+ jmp_buf setjmp_buffer;
+};
+
+extern "C" {
+
+ static
+ void khtml_error_exit (j_common_ptr cinfo)
+ {
+ khtml_error_mgr* myerr = (khtml_error_mgr*) cinfo->err;
+ char buffer[JMSG_LENGTH_MAX];
+ (*cinfo->err->format_message)(cinfo, buffer);
+#ifdef JPEG_DEBUG
+ qWarning("%s", buffer);
+#endif
+ longjmp(myerr->setjmp_buffer, 1);
+ }
+}
+
+static const int max_buf = 32768;
+static const int max_consumingtime = 2000;
+
+struct khtml_jpeg_source_mgr : public jpeg_source_mgr {
+ JOCTET buffer[max_buf];
+
+ int valid_buffer_len;
+ size_t skip_input_bytes;
+ int ateof;
+ QRect change_rect;
+ QRect old_change_rect;
+ QTime decoder_timestamp;
+ bool final_pass;
+ bool decoding_done;
+ bool do_progressive;
+
+public:
+ khtml_jpeg_source_mgr() KDE_NO_EXPORT;
+};
+
+
+extern "C" {
+
+ static
+ void khtml_j_decompress_dummy(j_decompress_ptr)
+ {
+ }
+
+ static
+ boolean khtml_fill_input_buffer(j_decompress_ptr cinfo)
+ {
+#ifdef BUFFER_DEBUG
+ qDebug("khtml_fill_input_buffer called!");
+#endif
+
+ khtml_jpeg_source_mgr* src = (khtml_jpeg_source_mgr*)cinfo->src;
+
+ if ( src->ateof )
+ {
+ /* Insert a fake EOI marker - as per jpeglib recommendation */
+ src->buffer[0] = (JOCTET) 0xFF;
+ src->buffer[1] = (JOCTET) JPEG_EOI;
+ src->bytes_in_buffer = 2;
+ src->next_input_byte = (JOCTET *) src->buffer;
+#ifdef BUFFER_DEBUG
+ qDebug("...returning true!");
+#endif
+ return true;
+ }
+ else
+ return false; /* I/O suspension mode */
+ }
+
+ static
+ void khtml_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
+ {
+ if(num_bytes <= 0)
+ return; /* required noop */
+
+#ifdef BUFFER_DEBUG
+ qDebug("khtml_skip_input_data (%d) called!", num_bytes);
+#endif
+
+ khtml_jpeg_source_mgr* src = (khtml_jpeg_source_mgr*)cinfo->src;
+ src->skip_input_bytes += num_bytes;
+
+ unsigned int skipbytes = kMin(src->bytes_in_buffer, src->skip_input_bytes);
+
+#ifdef BUFFER_DEBUG
+ qDebug("skip_input_bytes is now %d", src->skip_input_bytes);
+ qDebug("skipbytes is now %d", skipbytes);
+ qDebug("valid_buffer_len is before %d", src->valid_buffer_len);
+ qDebug("bytes_in_buffer is %d", src->bytes_in_buffer);
+#endif
+
+ if(skipbytes < src->bytes_in_buffer)
+ memmove(src->buffer, src->next_input_byte+skipbytes, src->bytes_in_buffer - skipbytes);
+
+ src->bytes_in_buffer -= skipbytes;
+ src->valid_buffer_len = src->bytes_in_buffer;
+ src->skip_input_bytes -= skipbytes;
+
+ /* adjust data for jpeglib */
+ cinfo->src->next_input_byte = (JOCTET *) src->buffer;
+ cinfo->src->bytes_in_buffer = (size_t) src->valid_buffer_len;
+#ifdef BUFFER_DEBUG
+ qDebug("valid_buffer_len is afterwards %d", src->valid_buffer_len);
+ qDebug("skip_input_bytes is now %d", src->skip_input_bytes);
+#endif
+ }
+}
+
+
+khtml_jpeg_source_mgr::khtml_jpeg_source_mgr()
+{
+ jpeg_source_mgr::init_source = khtml_j_decompress_dummy;
+ jpeg_source_mgr::fill_input_buffer = khtml_fill_input_buffer;
+ jpeg_source_mgr::skip_input_data = khtml_skip_input_data;
+ jpeg_source_mgr::resync_to_restart = jpeg_resync_to_restart;
+ jpeg_source_mgr::term_source = khtml_j_decompress_dummy;
+ bytes_in_buffer = 0;
+ valid_buffer_len = 0;
+ skip_input_bytes = 0;
+ ateof = 0;
+ next_input_byte = buffer;
+ final_pass = false;
+ decoding_done = false;
+}
+
+
+
+// -----------------------------------------------------------------------------
+
+class KJPEGFormat : public QImageFormat
+{
+public:
+ KJPEGFormat();
+
+ virtual ~KJPEGFormat();
+
+ virtual int decode(QImage& img, QImageConsumer* consumer,
+ const uchar* buffer, int length);
+private:
+
+ enum {
+ Init,
+ readHeader,
+ startDecompress,
+ decompressStarted,
+ consumeInput,
+ prepareOutputScan,
+ doOutputScan,
+ readDone,
+ invalid
+ } state;
+
+ // structs for the jpeglib
+ struct jpeg_decompress_struct cinfo;
+ struct khtml_error_mgr jerr;
+ struct khtml_jpeg_source_mgr jsrc;
+};
+
+
+// -----------------------------------------------------------------------------
+
+KJPEGFormat::KJPEGFormat()
+{
+ memset(&cinfo, 0, sizeof(cinfo));
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_decompress(&cinfo);
+ cinfo.err = jpeg_std_error(&jerr);
+ jerr.error_exit = khtml_error_exit;
+ cinfo.src = &jsrc;
+ state = Init;
+}
+
+
+KJPEGFormat::~KJPEGFormat()
+{
+ (void) jpeg_destroy_decompress(&cinfo);
+}
+
+/*
+ * return > 0 means "consumed x bytes, need more"
+ * return == 0 means "end of frame reached"
+ * return < 0 means "fatal error in image decoding, don't call me ever again"
+ */
+
+int KJPEGFormat::decode(QImage& image, QImageConsumer* consumer, const uchar* buffer, int length)
+{
+#ifdef JPEG_DEBUG
+ qDebug("KJPEGFormat::decode(%08lx, %08lx, %08lx, %d)",
+ &image, consumer, buffer, length);
+#endif
+
+ if(jsrc.ateof) {
+#ifdef JPEG_DEBUG
+ qDebug("ateof, eating");
+#endif
+ return length;
+ }
+
+
+ if(setjmp(jerr.setjmp_buffer))
+ {
+#ifdef JPEG_DEBUG
+ qDebug("jump into state invalid");
+#endif
+ if(consumer)
+ consumer->end();
+
+ // this is fatal
+ return -1;
+ }
+
+ int consumed = kMin(length, max_buf - jsrc.valid_buffer_len);
+
+#ifdef BUFFER_DEBUG
+ qDebug("consuming %d bytes", consumed);
+#endif
+
+ // filling buffer with the new data
+ memcpy(jsrc.buffer + jsrc.valid_buffer_len, buffer, consumed);
+ jsrc.valid_buffer_len += consumed;
+
+ if(jsrc.skip_input_bytes)
+ {
+#ifdef BUFFER_DEBUG
+ qDebug("doing skipping");
+ qDebug("valid_buffer_len %d", jsrc.valid_buffer_len);
+ qDebug("skip_input_bytes %d", jsrc.skip_input_bytes);
+#endif
+ int skipbytes = kMin((size_t) jsrc.valid_buffer_len, jsrc.skip_input_bytes);
+
+ if(skipbytes < jsrc.valid_buffer_len)
+ memmove(jsrc.buffer, jsrc.buffer+skipbytes, jsrc.valid_buffer_len - skipbytes);
+
+ jsrc.valid_buffer_len -= skipbytes;
+ jsrc.skip_input_bytes -= skipbytes;
+
+ // still more bytes to skip
+ if(jsrc.skip_input_bytes) {
+ if(consumed <= 0) qDebug("ERROR!!!");
+ return consumed;
+ }
+
+ }
+
+ cinfo.src->next_input_byte = (JOCTET *) jsrc.buffer;
+ cinfo.src->bytes_in_buffer = (size_t) jsrc.valid_buffer_len;
+
+#ifdef BUFFER_DEBUG
+ qDebug("buffer contains %d bytes", jsrc.valid_buffer_len);
+#endif
+
+ if(state == Init)
+ {
+ if(jpeg_read_header(&cinfo, true) != JPEG_SUSPENDED) {
+ // do some simple memory requirements limitations
+ // as long as we use that stupid Qt stuff
+ int s = cinfo.image_width * cinfo.image_height;
+ if ( s > 16384 * 12388 )
+ cinfo.scale_denom = 8;
+ else if ( s > 8192 * 6144 )
+ cinfo.scale_denom = 4;
+ else if ( s > 4096 * 3072 )
+ cinfo.scale_denom = 2;
+
+ if ( consumer )
+ consumer->setSize(cinfo.image_width/cinfo.scale_denom,
+ cinfo.image_height/cinfo.scale_denom);
+
+ state = startDecompress;
+ }
+ }
+
+ if(state == startDecompress)
+ {
+ jsrc.do_progressive = jpeg_has_multiple_scans( &cinfo );
+
+#ifdef JPEG_DEBUG
+ qDebug( "**** DOPROGRESSIVE: %d", jsrc.do_progressive );
+#endif
+ if ( jsrc.do_progressive )
+ cinfo.buffered_image = true;
+ else
+ cinfo.buffered_image = false;
+
+ // setup image sizes
+ jpeg_calc_output_dimensions( &cinfo );
+
+ if ( cinfo.jpeg_color_space == JCS_YCbCr )
+ cinfo.out_color_space = JCS_RGB;
+
+ cinfo.do_fancy_upsampling = true;
+ cinfo.do_block_smoothing = false;
+ cinfo.quantize_colors = false;
+
+ // false: IO suspension
+ if(jpeg_start_decompress(&cinfo)) {
+ if ( cinfo.output_components == 3 || cinfo.output_components == 4) {
+ image.create( cinfo.output_width, cinfo.output_height, 32 );
+ } else if ( cinfo.output_components == 1 ) {
+ image.create( cinfo.output_width, cinfo.output_height, 8, 256 );
+ for (int i=0; i<256; i++)
+ image.setColor(i, qRgb(i,i,i));
+ }
+
+#ifdef JPEG_DEBUG
+ qDebug("will create a picture %d/%d in size", cinfo.output_width, cinfo.output_height);
+#endif
+
+#ifdef JPEG_DEBUG
+ qDebug("ok, going to decompressStarted");
+#endif
+
+ jsrc.decoder_timestamp.start();
+ state = jsrc.do_progressive ? decompressStarted : doOutputScan;
+ }
+ }
+
+again:
+
+ if(state == decompressStarted) {
+ state = (!jsrc.final_pass && jsrc.decoder_timestamp.elapsed() < max_consumingtime)
+ ? consumeInput : prepareOutputScan;
+ }
+
+ if(state == consumeInput)
+ {
+ int retval;
+
+ do {
+ retval = jpeg_consume_input(&cinfo);
+ } while (retval != JPEG_SUSPENDED && retval != JPEG_REACHED_EOI
+ && (retval != JPEG_REACHED_SOS || jsrc.decoder_timestamp.elapsed() < max_consumingtime));
+
+ if(jsrc.decoder_timestamp.elapsed() >= max_consumingtime ||
+ jsrc.final_pass ||
+ retval == JPEG_REACHED_EOI || retval == JPEG_REACHED_SOS)
+ state = prepareOutputScan;
+ }
+
+ if(state == prepareOutputScan)
+ {
+ if ( jpeg_start_output(&cinfo, cinfo.input_scan_number) )
+ state = doOutputScan;
+ }
+
+ if(state == doOutputScan)
+ {
+ if(image.isNull() || jsrc.decoding_done)
+ {
+#ifdef JPEG_DEBUG
+ qDebug("complete in doOutputscan, eating..");
+#endif
+ return consumed;
+ }
+ uchar** lines = image.jumpTable();
+ int oldoutput_scanline = cinfo.output_scanline;
+
+ while(cinfo.output_scanline < cinfo.output_height &&
+ jpeg_read_scanlines(&cinfo, lines+cinfo.output_scanline, cinfo.output_height))
+ ; // here happens all the magic of decoding
+
+ int completed_scanlines = cinfo.output_scanline - oldoutput_scanline;
+#ifdef JPEG_DEBUG
+ qDebug("completed now %d scanlines", completed_scanlines);
+#endif
+
+ if ( cinfo.output_components == 3 ) {
+ // Expand 24->32 bpp.
+ for (int j=oldoutput_scanline; j<oldoutput_scanline+completed_scanlines; j++) {
+ uchar *in = image.scanLine(j) + cinfo.output_width * 3;
+ QRgb *out = (QRgb*)image.scanLine(j);
+
+ for (uint i=cinfo.output_width; i--; ) {
+ in-=3;
+ out[i] = qRgb(in[0], in[1], in[2]);
+ }
+ }
+ }
+
+ if(consumer && completed_scanlines)
+ {
+ QRect r(0, oldoutput_scanline, cinfo.output_width, completed_scanlines);
+#ifdef JPEG_DEBUG
+ qDebug("changing %d/%d %d/%d", r.x(), r.y(), r.width(), r.height());
+#endif
+ jsrc.change_rect |= r;
+
+ if ( jsrc.decoder_timestamp.elapsed() >= max_consumingtime ) {
+ if( !jsrc.old_change_rect.isEmpty()) {
+ consumer->changed(jsrc.old_change_rect);
+ jsrc.old_change_rect = QRect();
+ }
+ consumer->changed(jsrc.change_rect);
+ jsrc.change_rect = QRect();
+ jsrc.decoder_timestamp.restart();
+ }
+ }
+
+ if(cinfo.output_scanline >= cinfo.output_height)
+ {
+ if ( jsrc.do_progressive ) {
+ jpeg_finish_output(&cinfo);
+ jsrc.final_pass = jpeg_input_complete(&cinfo);
+ jsrc.decoding_done = jsrc.final_pass && cinfo.input_scan_number == cinfo.output_scan_number;
+ if ( !jsrc.decoding_done ) {
+ jsrc.old_change_rect |= jsrc.change_rect;
+ jsrc.change_rect = QRect();
+ }
+ }
+ else
+ jsrc.decoding_done = true;
+
+#ifdef JPEG_DEBUG
+ qDebug("one pass is completed, final_pass = %d, dec_done: %d, complete: %d",
+ jsrc.final_pass, jsrc.decoding_done, jpeg_input_complete(&cinfo));
+#endif
+ if(!jsrc.decoding_done)
+ {
+#ifdef JPEG_DEBUG
+ qDebug("starting another one, input_scan_number is %d/%d", cinfo.input_scan_number,
+ cinfo.output_scan_number);
+#endif
+ jsrc.decoder_timestamp.restart();
+ state = decompressStarted;
+ // don't return until necessary!
+ goto again;
+ }
+ }
+
+ if(state == doOutputScan && jsrc.decoding_done) {
+#ifdef JPEG_DEBUG
+ qDebug("input is complete, cleaning up, returning..");
+#endif
+ if ( consumer && !jsrc.change_rect.isEmpty() )
+ consumer->changed( jsrc.change_rect );
+
+ if(consumer)
+ consumer->end();
+
+ jsrc.ateof = true;
+
+ (void) jpeg_finish_decompress(&cinfo);
+ (void) jpeg_destroy_decompress(&cinfo);
+
+ state = readDone;
+
+ return 0;
+ }
+ }
+
+#ifdef BUFFER_DEBUG
+ qDebug("valid_buffer_len is now %d", jsrc.valid_buffer_len);
+ qDebug("bytes_in_buffer is now %d", jsrc.bytes_in_buffer);
+ qDebug("consumed %d bytes", consumed);
+#endif
+ if(jsrc.bytes_in_buffer && jsrc.buffer != jsrc.next_input_byte)
+ memmove(jsrc.buffer, jsrc.next_input_byte, jsrc.bytes_in_buffer);
+ jsrc.valid_buffer_len = jsrc.bytes_in_buffer;
+ return consumed;
+}
+
+// -----------------------------------------------------------------------------
+// This is the factory that teaches Qt about progressive JPEG's
+
+QImageFormat* khtml::KJPEGFormatType::decoderFor(const unsigned char* buffer, int length)
+{
+ if(length < 3) return 0;
+
+ if(buffer[0] == 0377 &&
+ buffer[1] == 0330 &&
+ buffer[2] == 0377)
+ return new KJPEGFormat;
+
+ return 0;
+}
+
+const char* khtml::KJPEGFormatType::formatName() const
+{
+ return "JPEG";
+}
+
+#else
+#ifdef __GNUC__
+#warning You don't seem to have libJPEG. jpeg support in khtml won't work
+#endif
+#endif // HAVE_LIBJPEG
+
+// -----------------------------------------------------------------------------
+
diff --git a/khtml/misc/loader_jpeg.h b/khtml/misc/loader_jpeg.h
new file mode 100644
index 000000000..f96d1f135
--- /dev/null
+++ b/khtml/misc/loader_jpeg.h
@@ -0,0 +1,50 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 2000 Dirk Mueller (mueller@kde.org)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ This is a helper for progressive loading of JPEG's.
+*/
+
+#ifndef _khtml_loader_jpeg_h
+#define _khtml_loader_jpeg_h
+
+#include <qasyncimageio.h>
+
+namespace khtml
+{
+ /**
+ * @internal
+ *
+ * An incremental loader factory for JPEG's.
+ */
+ class KJPEGFormatType : public QImageFormatType
+ {
+ public:
+ QImageFormat* decoderFor(const uchar* buffer, int length);
+ const char* formatName() const;
+ };
+
+}
+
+
+// -----------------------------------------------------------------------------
+
+#endif // _khtml_loader_jpeg_h
diff --git a/khtml/misc/makeattrs b/khtml/misc/makeattrs
new file mode 100644
index 000000000..48a02c045
--- /dev/null
+++ b/khtml/misc/makeattrs
@@ -0,0 +1,113 @@
+#!/usr/bin/perl
+#
+# This file is part of the KDE libraries
+#
+# Copyright (C) 1999 Lars Knoll (knoll@mpi-hd.mpg.de)
+# Copyright (C) 2003 Dirk Mueller (mueller@kde.org)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public License
+# along with this library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+#----------------------------------------------------------------------------
+#
+# KDE HTML Widget -- Script to generate khtmlattrs.c and khtmlattrs.h
+#
+open IN, "htmlattrs.in"
+ or die "Can't open in\n";
+open header, ">htmlattrs.h"
+ or die "Can't open header\n";
+open out, ">htmlattrs.gperf"
+ or die "Can't open out\n";
+
+print out "%{\n/* This file is automatically generated from
+#htmlattrs.in by makeattrs, do not edit */\n#include \"htmlattrs.h\"\n%}\n";
+print out "struct attrs {\n int name;\n int id;\n};\n%%\n";
+
+print header "/* This file is automatically generated from
+htmlattrs.in by makeattrs, do not edit */\n/* Copyright 1999 Lars Knoll */\n\n#ifndef HTML_ATTRS_H\n#define HTML_ATTRS_H\n\n#include \"dom/dom_string.h\"\n#include <kdemacros.h>\nusing namespace DOM;\n\n";
+
+my %amap = ();
+my $last_ci_attr = 0;
+$num = 0;
+while (<IN>) {
+ next if /^#/;
+ next if /^\s*$/;
+ /END_CI_ATTR/ and $last_ci_attr = $num and next;
+
+ chomp;
+ $attr = $_;
+ $num = $num + 1;
+
+ $up = uc($attr);
+ $amap{$up} = $num;
+ push(@a, $up);
+ $up =~ s/-/_/;
+ print out $attr . ", ATTR_" . $up . "\n";
+
+ print header "#define ATTR_" . $up . " " . $num . "\n";
+
+ }
+close(IN);
+
+print header "#define ATTR_LAST_ATTR $num\n";
+print header "#define ATTR_LAST_CI_ATTR $last_ci_attr\n";
+
+print out "%%\n";
+close out;
+
+print header "const char* getAttrName(unsigned short id) KDE_NO_EXPORT;\n";
+
+print header "\n#endif\n";
+close header;
+
+my $result = system("/bin/sh", "-c", "gperf -c -a -L 'ANSI-C' -P -G -D -E -C -o -t -k '*' -NfindAttr -Hhash_attr -Wwordlist_attr -Qspool_attr -s 2 htmlattrs.gperf > htmlattrs.c");
+if ($result) {
+ unlink "htmlattrs.c";
+ exit $result;
+}
+system("/bin/sh", "-c", 'perl -pi -e "s/\"\"}/\"\", 0}/g" htmlattrs.c');
+
+# read the hash mappings (is there a better way?)
+my %hmap = ();
+open(IN, "<htmlattrs.c");
+while(<IN>) {
+ if (/spool_attr_str(\d+), ATTR_([\w_]+)/) {
+ $hmap{$amap{$2}} = $1;
+ }
+}
+close(IN);
+
+open(OUT, ">>htmlattrs.c");
+print OUT "\n\nstatic const unsigned short attrList[] = {\n";
+print OUT " 65535,\n";
+
+while(defined ($line = shift @a))
+{
+ my $l = $line;
+ $l =~ y/-/_/;
+
+ die if !length($hmap{$amap{$l}});
+
+ print OUT " " .$hmap{$amap{$l}}.",\n";
+}
+print OUT " 65535\n};\n\n";
+print OUT "const char* KDE_NO_EXPORT getAttrName(unsigned short id)\n{\n";
+print OUT " if (!id || id > TOTAL_KEYWORDS) return \"\";\n";
+print OUT " return spool_attr + wordlist_attr[attrList[id]].name;\n";
+print OUT "}\n";
+
+
+
+
diff --git a/khtml/misc/maketags b/khtml/misc/maketags
new file mode 100644
index 000000000..a460cf8e4
--- /dev/null
+++ b/khtml/misc/maketags
@@ -0,0 +1,124 @@
+#!/usr/bin/perl
+# This file is part of the KDE libraries
+#
+# Copyright (C) 1998 Waldo Bastian (bastian@kde.org)
+# 1999 Lars Knoll (knoll@kde.org)
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public License
+# along with this library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+#----------------------------------------------------------------------------
+#
+# KDE HTML Widget -- Script to generate htmltags.c and htmltags.h
+#
+open IN, "htmltags.in"
+ or die "Can't open in\n";
+open header, ">htmltags.h"
+ or die "Can't open header\n";
+open out, ">htmltags.gperf"
+ or die "Can't open out\n";
+
+print out "%{\n/* This file is automatically generated from htmltags.in by maketags, do not edit */\n/* Copyright 1999 Lars Knoll */\n#include \"htmltags.h\"\n%}\n";
+print out "struct tags {\n int name;\n int id;\n};\n%%\n";
+
+print header <<EOF;
+/* This file is automatically generated from htmltags.in by maketags, do not edit */
+/* Copyright 1999 Lars Knoll */
+
+#ifndef KHTML_TAGS_H
+#define KHTML_TAGS_H
+
+#include "dom/dom_string.h"
+#include <kglobal.h>
+
+KDE_NO_EXPORT const char* getTagName(unsigned short id);
+
+EOF
+
+my @tags = ();
+$num = 0;
+while (<IN>) {
+ chomp;
+ $attr = $_;
+ $num = $num + 1;
+ push(@tags, $attr);
+ push(@a, " \"$attr\",");
+ push(@b, " \"/$attr\",");
+ $up = uc($attr);
+ $up =~ s/-/_/;
+ print out $attr . ", ID_" . $up . "\n";
+ print header "#define ID_" . $up . " " . $num . "\n";
+}
+print out "anchor, ID_A\n";
+print out "image, ID_IMG\n";
+print out "listing, ID_PRE\n";
+$num = $num+1;
+print header "#define ID_TEXT $num\n";
+$num = $num+1;
+print header "#define ID_COMMENT $num\n";
+print header "#define ID_CLOSE_TAG $num\n";
+print header "#define ID_LAST_TAG $num\n";
+
+print out "%%\n";
+close out;
+print header "\n#endif\n";
+close header;
+
+my $result = system("/bin/sh", "-c", "gperf -a -L 'ANSI-C' -P -D -E -C -l -o -t -k '*' -NfindTag -Hhash_tag -Wwordlist_tag -Qspool_Tag htmltags.gperf > htmltags.c");
+if ($result) {
+ unlink "htmltags.c";
+ exit $result;
+}
+
+open(OUT, ">>htmltags.c");
+print OUT "\n\nstatic const char tagStable[] = {\n \"";
+push (@tags, "text");
+push (@tags, "comment");
+my %stable = ();
+my $l = 1;
+my $line = 5;
+foreach my $k(@tags) {
+ if ($line > 65) {
+ print OUT "\"\n \"";
+ $line = 5;
+ }
+ #print OUT " \"\\000/$k\"\n";
+ print OUT "\\000/$k";
+ $stable{$k} = $l;
+ $l += length($k) + 2;
+ $line += length($k) + 5;
+}
+print OUT "\\000\"\n};\n";
+
+print OUT "\nstatic const unsigned short tagSList[] = {\n";
+print OUT " 0,\n";
+my $c = 0;
+foreach my $line (@tags)
+{
+ printf OUT "\n " if (($c % 12) == 0);
+ printf OUT "%4d,", ($stable{$line}+1) ;
+ ++$c;
+}
+foreach my $line (@tags)
+{
+ printf OUT "\n " if (($c % 12) == 0);
+ printf OUT "%4d,", ($stable{$line}) ;
+ ++$c;
+}
+print OUT " 0\n};\n\n";
+print OUT "const char* KDE_NO_EXPORT getTagName(unsigned short id)\n{\n";
+print OUT " if(id > ID_CLOSE_TAG*2) id = ID_CLOSE_TAG+1;\n";
+print OUT " return &tagStable[tagSList[id]];\n}\n";
+
diff --git a/khtml/misc/multimap.h b/khtml/misc/multimap.h
new file mode 100644
index 000000000..08cb11879
--- /dev/null
+++ b/khtml/misc/multimap.h
@@ -0,0 +1,345 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2006 Allan Sandfeld Jensen (kde@carewolf.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _MultiMap_h_
+#define _MultiMap_h_
+
+#include <qptrdict.h>
+#include <qptrlist.h>
+#include <assert.h>
+#include <stdlib.h>
+
+template<class T> class MultiMapPtrList;
+
+// KMultiMap is an implementaition of a Map with multiple entries per key.
+// It is originally designed to work like a shell for QPtrDict<QPtrList>, but
+// QPtrList have been replaced with a much faster hash set.
+template<class T>
+class KMultiMap {
+public:
+ KMultiMap() : dict(257) { dict.setAutoDelete(true); }
+ ~KMultiMap() {};
+
+ typedef MultiMapPtrList<T> List;
+
+ void append(void* key, T* element) {
+ List *list = dict.find(key);
+ if (!list){
+ list = new List(8);
+ dict.insert(key, list);
+ }
+ list->append(element);
+ }
+ void remove(void* key, T* element) {
+ List *list = dict.find(key);
+ if (list) {
+ list->remove(element);
+ if (list->isEmpty()) dict.remove(key);
+ }
+ }
+ void remove(void* key) {
+ dict.remove(key);
+ }
+ List* find(void* key) {
+ return dict.find(key);
+ }
+private:
+ QPtrDict<List> dict;
+
+};
+
+static inline unsigned int stupidHash(void* ptr)
+{
+ unsigned long val = (unsigned long)ptr;
+ // remove alignment and multiply by a prime unlikely to be a factor of size
+ val = (val >> 4) * 1237;
+ return val;
+}
+
+#define START_PTRLIST_SIZE 4
+#define MAX_PTRLIST_SIZE 27
+
+class PtrListEntry {
+public:
+ PtrListEntry(unsigned int log_size) : count(0), log_size(log_size), search(log_size), next(0) {
+// entry = new T* [size];
+ assert(log_size < MAX_PTRLIST_SIZE);
+ entry = (void**)calloc ((1<<log_size), sizeof(void*));
+ }
+ ~PtrListEntry() {
+// delete[] entry;
+ free(entry);
+ }
+ bool insert(void* e) {
+ unsigned int t_size = size();
+ if (count == t_size) return false;
+ unsigned int hash = stupidHash(e);
+ void** firstFree = 0;
+ // Only let elements be placed 'search' spots from their hash
+ for(unsigned int j=0; j<search; j++) {
+ unsigned int i = (hash + j) & (t_size-1); // modulo size
+ // We need check to all hashes in 'search' to garuantee uniqueness
+ if (entry[i] == 0) {
+ if (!firstFree)
+ firstFree = entry + i;
+ } else
+ if (entry[i] == e)
+ return true;
+ }
+ if (firstFree) {
+ *firstFree = e;
+ count++;
+ return true;
+ }
+ // We had more than 'search' collisions
+ if (count < (t_size/3)*2) {
+ // only 2/3 full => increase search
+ unsigned int s = search *2;
+ if (s >= t_size) s = t_size;
+ search = s;
+ return insert(e);
+ }
+ return false;
+ }
+ // Insert another smaller set into this one
+ // Is only garuantied to succede when this PtrList is new
+ void insert(PtrListEntry* listEntry) {
+ assert(size() >= listEntry->count * 2);
+ unsigned int old_size = 1U << listEntry->log_size;
+ for(unsigned int i = 0; i < old_size; i++) {
+ bool s = true;
+ void *e = listEntry->entry[i];
+ if (e) s = insert(e);
+ assert(s);
+ }
+ }
+ bool remove(void* e) {
+ if (count == 0) return false;
+ unsigned int size = (1U<<log_size);
+ unsigned int hash = stupidHash(e);
+ // Elements are at most placed 'search' spots from their hash
+ for(unsigned int j=0; j<search; j++) {
+ unsigned int i = (hash + j) & (size-1); // modulo size
+ if (entry[i] == e) {
+ entry[i] = 0;
+ count--;
+ return true;
+ }
+ }
+ return false;
+ }
+ bool contains(void* e) {
+ if (count == 0) return false;
+ unsigned int t_size = size();
+ unsigned int hash = stupidHash(e);
+ // Elements are at most placed 'search' spots from their hash
+ for(unsigned int j=0; j<search; j++) {
+ unsigned int i = (hash + j) & (t_size-1); // modulo size
+ if (entry[i] == e) return true;
+ }
+ return false;
+ }
+ void* at(unsigned int i) const {
+ assert (i < (1U<<log_size));
+ return entry[i];
+ }
+ bool isEmpty() const {
+ return count == 0;
+ }
+ bool isFull() const {
+ return count == size();
+ }
+ unsigned int size() const {
+ return (1U << log_size);
+ }
+
+ unsigned int count;
+ const unsigned short log_size;
+ unsigned short search;
+ PtrListEntry *next;
+ void** entry;
+};
+
+// An unsorted and unique PtrList that is implement as a linked list of hash-sets
+// Optimized for fast insert and fast lookup
+template<class T>
+class MultiMapPtrList {
+public:
+ MultiMapPtrList(unsigned int init_size= 16) : m_first(0), m_current(0), m_pos(0) {
+ assert(init_size > 0);
+ unsigned int s = init_size - 1;
+ unsigned int log_size = 0;
+ while (s > 0) {
+ log_size++;
+ s = s >> 1;
+ }
+ m_first = new PtrListEntry(log_size);
+ }
+ MultiMapPtrList(const MultiMapPtrList& ptrList) : m_first(0), m_current(0), m_pos(0) {
+ unsigned int t_count = ptrList.count();
+ unsigned int log_size = 0;
+ while (t_count > 0) {
+ log_size++;
+ t_count = t_count >> 1;
+ }
+ // At least as large as the largest ptrListEntry in the original
+ if (t_count < ptrList.m_first->log_size) log_size = ptrList.m_first->log_size;
+ m_first = new PtrListEntry(log_size);
+
+ PtrListEntry *t_current = ptrList.m_first;
+ while (t_current) {
+ unsigned int t_size = t_current->size();
+ for(unsigned int i=0; i < t_size; i++) {
+ void* e = t_current->at(i);
+ if (e != 0) {
+ bool t = m_first->insert(e);
+ if (!t) {
+ // Make a new, but keep the size
+ PtrListEntry *t_new = new PtrListEntry(log_size);
+ t_new->insert(e);
+ t_new->next = m_first;
+ m_first = t_new;
+ }
+ }
+ }
+ t_current = t_current->next;
+ }
+ }
+ ~MultiMapPtrList() {
+ PtrListEntry *t_next, *t_current = m_first;
+ while (t_current) {
+ t_next = t_current->next;
+ delete t_current;
+ t_current = t_next;
+ }
+ }
+ void append(T* e) {
+ PtrListEntry *t_last = 0, *t_current = m_first;
+ int count = 0;
+ while (t_current) {
+ if (t_current->insert(e)) return;
+ t_last = t_current;
+ t_current = t_current->next;
+ count++;
+ }
+ // Create new hash-set
+ unsigned int newsize = m_first->log_size+1;
+ if (newsize > MAX_PTRLIST_SIZE) newsize = MAX_PTRLIST_SIZE;
+ t_current = new PtrListEntry(newsize);
+ bool t = t_current->insert(e);
+ assert(t);
+ // Prepend it to the list, for insert effeciency
+ t_current->next = m_first;
+ m_first = t_current;
+ // ### rehash some of the smaller sets
+ /*
+ if (count > 4) {
+ // rehash the last in the new
+ t_current->insert(t_last);
+ }*/
+ }
+ void remove(T* e) {
+ PtrListEntry *t_next, *t_last = 0, *t_current = m_first;
+ // Remove has to check every PtrEntry.
+ while (t_current) {
+ t_next = t_current->next;
+ if (t_current->remove(e) && t_current->isEmpty()) {
+ if (t_last) {
+ t_last->next = t_current->next;
+ }
+ else {
+ assert (m_first == t_current);
+ m_first = t_current->next;
+ }
+ delete t_current;
+ } else {
+ t_last = t_current;
+ }
+ t_current = t_next;
+ }
+ }
+ bool contains(T* e) {
+ PtrListEntry *t_current = m_first;
+ while (t_current) {
+ if (t_current->contains(e)) return true;
+ t_current = t_current->next;
+ }
+ return false;
+ }
+ bool isEmpty() {
+ if (!m_first) return true;
+ PtrListEntry *t_current = m_first;
+ while (t_current) {
+ if (!t_current->isEmpty()) return false;
+ t_current = t_current->next;
+ }
+ return true;
+ }
+ unsigned int count() const {
+ unsigned int t_count = 0;
+ PtrListEntry *t_current = m_first;
+ while (t_current) {
+ t_count += t_current->count;
+ t_current = t_current->next;
+ }
+ return t_count;
+ }
+// Iterator functions:
+ T* first() {
+ m_current = m_first;
+ m_pos = 0;
+ // skip holes
+ if (m_current && !m_current->at(m_pos))
+ return next();
+ else
+ return current();
+ }
+ T* current() {
+ if (!m_current)
+ return (T*)0;
+ else
+ return (T*)m_current->at(m_pos);
+ }
+ T* next() {
+ if (!m_current) return (T*)0;
+ m_pos++;
+ if (m_pos >= m_current->size()) {
+ m_current = m_current->next;
+ m_pos = 0;
+ }
+ // skip holes
+ if (m_current && !m_current->at(m_pos))
+ return next();
+ else
+ return current();
+ }
+private:
+ PtrListEntry *m_first;
+// iteration:
+ PtrListEntry *m_current;
+ unsigned int m_pos;
+};
+
+#undef START_PTRLIST_SIZE
+#undef MAX_PTRLIST_SIZE
+
+#endif
diff --git a/khtml/misc/seed.h b/khtml/misc/seed.h
new file mode 100644
index 000000000..e491cbaae
--- /dev/null
+++ b/khtml/misc/seed.h
@@ -0,0 +1,46 @@
+/*
+ * A simple hash seed chooser.
+ *
+ * Copyright (C) 2003 Germain Garand <germain@ebooksfrance.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef html_seed_h
+#define html_seed_h
+
+#define khtml_MaxSeed 47963
+
+namespace khtml {
+
+static const int primes_t[] =
+{
+ 31, 61, 107, 233, 353, 541,
+ 821, 1237, 1861, 2797, 4201, 6311,
+ 9467, 14207, 21313, 31973, 47963, 0
+};
+
+static inline int nextSeed(int curSize) {
+ for (int i = 0 ; primes_t[i] ; i++)
+ if (primes_t[i] > curSize)
+ return primes_t[i];
+ return curSize;
+}
+
+} // namespace
+
+#endif
diff --git a/khtml/misc/shared.h b/khtml/misc/shared.h
new file mode 100644
index 000000000..f0a1eff96
--- /dev/null
+++ b/khtml/misc/shared.h
@@ -0,0 +1,228 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ * Copyright (C) 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2002 Lars Knoll
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef SHARED_H
+#define SHARED_H
+
+namespace khtml {
+
+template<class type> class Shared
+{
+public:
+ Shared() { _ref=0; /*counter++;*/ }
+ ~Shared() { /*counter--;*/ }
+
+ void ref() { _ref++; }
+ void deref() {
+ if(_ref) _ref--;
+ if(!_ref)
+ delete static_cast<type *>(this);
+ }
+ bool hasOneRef() { //kdDebug(300) << "ref=" << _ref << endl;
+ return _ref==1; }
+
+ int refCount() const { return _ref; }
+// static int counter;
+protected:
+ unsigned int _ref;
+};
+
+template<class type> class TreeShared
+{
+public:
+ TreeShared() { _ref = 0; m_parent = 0; /*counter++;*/ }
+ TreeShared( type *parent ) { _ref=0; m_parent = parent; /*counter++;*/ }
+ ~TreeShared() { /*counter--;*/ }
+
+ virtual void removedLastRef() { delete static_cast<type*>(this); }
+
+ void ref() { _ref++; }
+ void deref() {
+ if(_ref) _ref--;
+ if(!_ref && !m_parent) {
+ removedLastRef();
+ }
+ }
+ bool hasOneRef() { //kdDebug(300) << "ref=" << _ref << endl;
+ return _ref==1; }
+
+ int refCount() const { return _ref; }
+// static int counter;
+
+ void setParent(type *parent) { m_parent = parent; }
+ type *parent() const { return m_parent; }
+private:
+ unsigned int _ref;
+protected:
+ type *m_parent;
+};
+
+template <class T> class SharedPtr;
+
+template <class T> bool operator==(const SharedPtr<T> &a, const SharedPtr<T> &b);
+template <class T> bool operator==(const SharedPtr<T> &a, const T *b);
+template <class T> bool operator==(const T *a, const SharedPtr<T> &b);
+
+template <class T> class SharedPtr
+{
+public:
+ SharedPtr() : m_ptr(0) {}
+ explicit SharedPtr(T *ptr) : m_ptr(ptr) { if (m_ptr) m_ptr->ref(); }
+ SharedPtr(const SharedPtr &o) : m_ptr(o.m_ptr) { if (m_ptr) m_ptr->ref(); }
+ ~SharedPtr() { if (m_ptr) m_ptr->deref(); }
+
+ bool isNull() const { return m_ptr == 0; }
+ bool notNull() const { return m_ptr != 0; }
+
+ void reset() { if (m_ptr) m_ptr->deref(); m_ptr = 0; }
+ void reset(T *o) { if (o) o->ref(); if (m_ptr) m_ptr->deref(); m_ptr = o; }
+
+ T * get() const { return m_ptr; }
+ T &operator*() const { return *m_ptr; }
+ T *operator->() const { return m_ptr; }
+
+ bool operator!() const { return m_ptr == 0; }
+
+ template <class C> friend bool operator==(const SharedPtr<C> &a, const SharedPtr<C> &b);
+ template <class C> friend bool operator==(const SharedPtr<C> &a, const C *b);
+ template <class C> friend bool operator==(const C *a, const SharedPtr<C> &b);
+
+ SharedPtr &operator=(const SharedPtr &);
+
+private:
+ T* m_ptr;
+};
+
+template <class T> SharedPtr<T> &SharedPtr<T>::operator=(const SharedPtr<T> &o)
+{
+ if (o.m_ptr)
+ o.m_ptr->ref();
+ if (m_ptr)
+ m_ptr->deref();
+ m_ptr = o.m_ptr;
+ return *this;
+}
+
+template <class T> inline bool operator==(const SharedPtr<T> &a, const SharedPtr<T> &b) { return a.m_ptr == b.m_ptr; }
+template <class T> inline bool operator==(const SharedPtr<T> &a, const T *b) { return a.m_ptr == b; }
+template <class T> inline bool operator==(const T *a, const SharedPtr<T> &b) { return a == b.m_ptr; }
+
+template <class T> inline bool operator!=(const SharedPtr<T> &a, const SharedPtr<T> &b) { return !(a==b); }
+template <class T> inline bool operator!=(const SharedPtr<T> &a, const T *b) { return !(a == b); }
+template <class T> inline bool operator!=(const T *a, const SharedPtr<T> &b) { return !(a == b); }
+
+template <class T, class U> inline SharedPtr<T> static_pointer_cast(const SharedPtr<U> &p) { return SharedPtr<T>(static_cast<T *>(p.get())); }
+template <class T, class U> inline SharedPtr<T> const_pointer_cast(const SharedPtr<U> &p) { return SharedPtr<T>(const_cast<T *>(p.get())); }
+
+//A special pointer for nodes keeping track of the document,
+//which helps distinguish back links from them to it, in order to break
+//cycles
+template <class T> class DocPtr {
+public:
+ DocPtr() : m_ptr(0) {}
+ DocPtr(T *ptr) : m_ptr(ptr) { if (ptr) ptr->selfOnlyRef(); }
+ DocPtr(const DocPtr &o) : m_ptr(o.m_ptr) { if (T *ptr = m_ptr) ptr->selfOnlyRef(); }
+ ~DocPtr() { if (T *ptr = m_ptr) ptr->selfOnlyDeref(); }
+
+ template <class U> DocPtr(const DocPtr<U> &o) : m_ptr(o.get()) { if (T *ptr = m_ptr) ptr->selfOnlyRef(); }
+
+ void resetSkippingRef(T *o) { m_ptr = o; }
+
+ T *get() const { return m_ptr; }
+
+ T &operator*() const { return *m_ptr; }
+ T *operator->() const { return m_ptr; }
+
+ bool operator!() const { return !m_ptr; }
+
+ // this type conversion operator allows implicit conversion to
+ // bool but not to other integer types
+
+ typedef T * (DocPtr::*UnspecifiedBoolType)() const;
+ operator UnspecifiedBoolType() const
+ {
+ return m_ptr ? &DocPtr::get : 0;
+ }
+
+ DocPtr &operator=(const DocPtr &);
+ DocPtr &operator=(T *);
+
+ private:
+ T *m_ptr;
+};
+
+template <class T> DocPtr<T> &DocPtr<T>::operator=(const DocPtr<T> &o)
+{
+ T *optr = o.m_ptr;
+ if (optr)
+ optr->selfOnlyRef();
+ if (T *ptr = m_ptr)
+ ptr->selfOnlyDeref();
+ m_ptr = optr;
+ return *this;
+}
+
+template <class T> inline DocPtr<T> &DocPtr<T>::operator=(T *optr)
+{
+ if (optr)
+ optr->selfOnlyRef();
+ if (T *ptr = m_ptr)
+ ptr->selfOnlyDeref();
+ m_ptr = optr;
+ return *this;
+}
+
+template <class T> inline bool operator==(const DocPtr<T> &a, const DocPtr<T> &b)
+{
+ return a.get() == b.get();
+}
+
+template <class T> inline bool operator==(const DocPtr<T> &a, const T *b)
+{
+ return a.get() == b;
+}
+
+template <class T> inline bool operator==(const T *a, const DocPtr<T> &b)
+{
+ return a == b.get();
+}
+
+template <class T> inline bool operator!=(const DocPtr<T> &a, const DocPtr<T> &b)
+{
+ return a.get() != b.get();
+}
+
+template <class T> inline bool operator!=(const DocPtr<T> &a, const T *b)
+{
+ return a.get() != b;
+}
+
+template <class T> inline bool operator!=(const T *a, const DocPtr<T> &b)
+{
+ return a != b.get();
+}
+
+
+} // namespace
+
+#endif
diff --git a/khtml/misc/stringit.cpp b/khtml/misc/stringit.cpp
new file mode 100644
index 000000000..5dbe857be
--- /dev/null
+++ b/khtml/misc/stringit.cpp
@@ -0,0 +1,138 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 2004 Apple Computer
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "stringit.h"
+
+namespace khtml {
+
+uint TokenizerString::length() const
+{
+ uint length = m_currentString.m_length;
+ if (!m_pushedChar1.isNull()) {
+ ++length;
+ if (!m_pushedChar2.isNull())
+ ++length;
+ }
+ if (m_composite) {
+ QValueListConstIterator<TokenizerSubstring> i = m_substrings.begin();
+ QValueListConstIterator<TokenizerSubstring> e = m_substrings.end();
+ for (; i != e; ++i)
+ length += (*i).m_length;
+ }
+ return length;
+}
+
+void TokenizerString::clear()
+{
+ m_pushedChar1 = 0;
+ m_pushedChar2 = 0;
+ m_currentChar = 0;
+ m_currentString.clear();
+ m_substrings.clear();
+ m_lines = 0;
+ m_composite = false;
+}
+
+void TokenizerString::append(const TokenizerSubstring &s)
+{
+ if (s.m_length) {
+ if (!m_currentString.m_length) {
+ m_currentString = s;
+ } else {
+ m_substrings.append(s);
+ m_composite = true;
+ }
+ }
+}
+
+void TokenizerString::prepend(const TokenizerSubstring &s)
+{
+ assert(!escaped());
+ if (s.m_length) {
+ if (!m_currentString.m_length)
+ m_currentString = s;
+ else {
+ // Shift our m_currentString into our list.
+ m_substrings.prepend(m_currentString);
+ m_currentString = s;
+ m_composite = true;
+ }
+ }
+}
+
+void TokenizerString::append(const TokenizerString &s)
+{
+ assert(!s.escaped());
+ append(s.m_currentString);
+ if (s.m_composite) {
+ QValueListConstIterator<TokenizerSubstring> i = s.m_substrings.begin();
+ QValueListConstIterator<TokenizerSubstring> e = s.m_substrings.end();
+ for (; i != e; ++i)
+ append(*i);
+ }
+ m_currentChar = m_pushedChar1.isNull() ? m_currentString.m_current : &m_pushedChar1;
+}
+
+void TokenizerString::prepend(const TokenizerString &s)
+{
+ assert(!escaped());
+ assert(!s.escaped());
+ if (s.m_composite) {
+ QValueListConstIterator<TokenizerSubstring> i = s.m_substrings.fromLast();
+ QValueListConstIterator<TokenizerSubstring> e = s.m_substrings.end();
+ for (; i != e; --i)
+ prepend(*i);
+ }
+ prepend(s.m_currentString);
+ m_currentChar = m_pushedChar1.isNull() ? m_currentString.m_current : &m_pushedChar1;
+}
+
+void TokenizerString::advanceSubstring()
+{
+ if (m_composite) {
+ m_currentString = m_substrings.first();
+ m_substrings.remove(m_substrings.begin());
+ if (m_substrings.isEmpty())
+ m_composite = false;
+ } else {
+ m_currentString.clear();
+ }
+}
+
+QString TokenizerString::toString() const
+{
+ QString result;
+ if (!m_pushedChar1.isNull()) {
+ result.append(m_pushedChar1);
+ if (!m_pushedChar2.isNull())
+ result.append(m_pushedChar2);
+ }
+ m_currentString.appendTo(result);
+ if (m_composite) {
+ QValueListConstIterator<TokenizerSubstring> i = m_substrings.begin();
+ QValueListConstIterator<TokenizerSubstring> e = m_substrings.end();
+ for (; i != e; ++i)
+ (*i).appendTo(result);
+ }
+ return result;
+}
+
+}
diff --git a/khtml/misc/stringit.h b/khtml/misc/stringit.h
new file mode 100644
index 000000000..9b6c3885d
--- /dev/null
+++ b/khtml/misc/stringit.h
@@ -0,0 +1,203 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 1999 Lars Knoll (knoll@mpi-hd.mpg.de)
+ Copyright (C) 2004 Apple Computer, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+//----------------------------------------------------------------------------
+//
+// KDE HTML Widget -- String class
+
+#ifndef KHTMLSTRING_H
+#define KHTMLSTRING_H
+
+#include "dom/dom_string.h"
+
+#include <qstring.h>
+#include <qvaluelist.h>
+
+#include <assert.h>
+
+using namespace DOM;
+
+namespace khtml
+{
+
+class DOMStringIt
+{
+public:
+ DOMStringIt()
+ { s = 0, l = 0; lines = 0; }
+ DOMStringIt(QChar *str, uint len)
+ { s = str, l = len; lines = 0; }
+ DOMStringIt(const QString &str)
+ { s = str.unicode(); l = str.length(); lines = 0; }
+
+ DOMStringIt *operator++()
+ {
+ if(!pushedChar.isNull())
+ pushedChar=0;
+ else if(l > 0 ) {
+ if (*s == '\n')
+ lines++;
+ s++, l--;
+ }
+ return this;
+ }
+public:
+ void push(const QChar& c) { /* assert(pushedChar.isNull());*/ pushedChar = c; }
+
+ const QChar& operator*() const { return pushedChar.isNull() ? *s : pushedChar; }
+ const QChar* operator->() const { return pushedChar.isNull() ? s : &pushedChar; }
+
+ bool escaped() const { return !pushedChar.isNull(); }
+ uint length() const { return l+(!pushedChar.isNull()); }
+
+ const QChar *current() const { return pushedChar.isNull() ? s : &pushedChar; }
+ int lineCount() const { return lines; }
+
+protected:
+ QChar pushedChar;
+ const QChar *s;
+ int l;
+ int lines;
+};
+
+class TokenizerString;
+
+class TokenizerSubstring
+{
+ friend class TokenizerString;
+public:
+ TokenizerSubstring() : m_length(0), m_current(0) {}
+ TokenizerSubstring(const QString &str) : m_string(str), m_length(str.length()), m_current(m_length == 0 ? 0 : str.unicode()) {}
+ TokenizerSubstring(const QChar *str, int length) : m_length(length), m_current(length == 0 ? 0 : str) {}
+
+ void clear() { m_length = 0; m_current = 0; }
+
+ void appendTo(QString &str) const {
+ if (m_string.unicode() == m_current) {
+ if (str.isEmpty())
+ str = m_string;
+ else
+ str.append(m_string);
+ } else {
+ str.insert(str.length(), m_current, m_length);
+ }
+ }
+private:
+ QString m_string;
+ int m_length;
+ const QChar *m_current;
+};
+
+class TokenizerString
+{
+
+public:
+ TokenizerString() : m_currentChar(0), m_lines(0), m_composite(false) {}
+ TokenizerString(const QChar *str, int length) : m_currentString(str, length), m_currentChar(m_currentString.m_current), m_lines(0), m_composite(false) {}
+ TokenizerString(const QString &str) : m_currentString(str), m_currentChar(m_currentString.m_current), m_lines(0), m_composite(false) {}
+ TokenizerString(const TokenizerString &o) : m_pushedChar1(o.m_pushedChar1), m_pushedChar2(o.m_pushedChar2),
+ m_currentString(o.m_currentString), m_substrings(o.m_substrings),
+ m_lines(o.m_lines), m_composite(o.m_composite) {
+ m_currentChar = m_pushedChar1.isNull() ? m_currentString.m_current : &m_pushedChar1;
+ }
+
+ void clear();
+
+ void append(const TokenizerString &);
+ void prepend(const TokenizerString &);
+
+ void push(QChar c) {
+ if (m_pushedChar1.isNull()) {
+ m_pushedChar1 = c;
+ m_currentChar = m_pushedChar1.isNull() ? m_currentString.m_current : &m_pushedChar1;
+ } else {
+ assert(m_pushedChar2.isNull());
+ m_pushedChar2 = c;
+ }
+ }
+
+ bool isEmpty() const { return !current(); }
+ uint length() const;
+
+ void advance() {
+ if (!m_pushedChar1.isNull()) {
+ m_pushedChar1 = m_pushedChar2;
+ m_pushedChar2 = 0;
+ } else if (m_currentString.m_current) {
+ m_lines += *m_currentString.m_current++ == '\n';
+ if (--m_currentString.m_length == 0)
+ advanceSubstring();
+ }
+ m_currentChar = m_pushedChar1.isNull() ? m_currentString.m_current: &m_pushedChar1;
+ }
+ uint count() const { return m_substrings.count(); }
+
+ bool escaped() const { return !m_pushedChar1.isNull(); }
+
+ int lineCount() const { return m_lines; }
+ void resetLineCount() { m_lines = 0; }
+
+ QString toString() const;
+
+ void operator++() { advance(); }
+ const QChar &operator*() const { return *current(); }
+ const QChar *operator->() const { return current(); }
+
+private:
+ void append(const TokenizerSubstring &);
+ void prepend(const TokenizerSubstring &);
+
+ void advanceSubstring();
+ const QChar *current() const { return m_currentChar; }
+
+ QChar m_pushedChar1;
+ QChar m_pushedChar2;
+ TokenizerSubstring m_currentString;
+ const QChar *m_currentChar;
+ QValueList<TokenizerSubstring> m_substrings;
+ int m_lines;
+ bool m_composite;
+
+};
+
+
+class TokenizerQueue : public QValueList<TokenizerString>
+{
+
+public:
+ TokenizerQueue() {}
+ ~TokenizerQueue() {}
+ void push( const TokenizerString &t ) { prepend(t); }
+ TokenizerString pop() {
+ if (isEmpty())
+ return TokenizerString();
+ TokenizerString t(first());
+ remove( begin() );
+ return t;
+ }
+ TokenizerString& top() { return first(); }
+ TokenizerString& bottom() { return last(); }
+};
+
+}
+
+#endif
+