diff options
Diffstat (limited to 'khtml/misc')
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 Binary files differnew file mode 100644 index 000000000..0f545c393 --- /dev/null +++ b/khtml/misc/blocked_icon.png 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 + |