⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dicache.c

📁 浏览器的源代码,可移植到嵌入式设备.
💻 C
字号:
/* * File: dicache.c * * Copyright 2000 Jorge Arellano Cid <jcid@dillo.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */#include <glib.h>           /* GHashTable functions */#include <gtk/gtk.h>#include <sys/time.h>       /* for libc5 compatibility */#include <string.h>         /* for memset */#include <stdio.h>#include "image.h"#include "web.h"#include "dicache.h"#include "cache.h"#include "interface.h"#include "prefs.h"typedef struct _DICacheHashEntry DICacheHashEntry;struct _DICacheHashEntry {   gint valid;   DilloUrl *url;       /* "Key" of this hash entry */   DICacheEntry* next;  /* pointer to the first dicache entry in this list */};static GHashTable *dicache_hash;static gint dicache_size_total; /* invariant: dicache_size_total is                                 * the sum of the image sizes of all                                 * cache lines in dicache. *//* * Determine if two hash entries are equal (used by GHashTable) */static gint Dicache_hash_entry_equal(gconstpointer v1, gconstpointer v2){   return (!a_Url_cmp((DilloUrl *)v1, (DilloUrl *)v2));}/* * Determine the hash value given the key (used by GHashTable) */static guint Dicache_url_hash(gconstpointer key){   return g_str_hash(URL_STR(((DilloUrl *)key)));}/* * Initialize dicache data */void a_Dicache_init(void){   dicache_hash = g_hash_table_new(Dicache_url_hash, Dicache_hash_entry_equal);   dicache_size_total = 0;}/* * Create, and initialize a new, empty, dicache entry */static DICacheEntry *Dicache_entry_new(void){   DICacheEntry *entry = g_new(DICacheEntry, 1);   entry->width = 0;   entry->height = 0;   entry->type = DILLO_IMG_TYPE_NOTSET;   entry->cmap = NULL;   entry->ImageBuffer = NULL;   entry->RefCount = 1;   entry->TotalSize = 0;   entry->Y = 0;   entry->BitVec = NULL;   entry->State = DIC_Empty;   entry->version = 0;   entry->next = NULL;   return entry;}/* * Add a new entry to the hash */DICacheEntry *a_Dicache_add_entry(const DilloUrl *Url){   DICacheEntry *entry;   DICacheHashEntry *hash_entry;   entry = Dicache_entry_new();   if ( (hash_entry = g_hash_table_lookup(dicache_hash, Url))) {      /* this URL is already in the hash, add entry at the END of the list */      DICacheEntry *ptr = hash_entry->next;      hash_entry->valid = 1;      for (  ; ptr->next; ptr = ptr->next);      ptr->next = entry;      entry->version = ptr->version+1;      entry->url = hash_entry->url;   } else { /* no hash entry yet, so create one */      DICacheHashEntry *hash_entry = g_new(DICacheHashEntry, 1);      hash_entry->url = a_Url_dup(Url);      entry->url = hash_entry->url;      hash_entry->next = entry;      hash_entry->valid = 1;      g_hash_table_insert(dicache_hash, hash_entry->url, hash_entry);   }   return entry;}/* * Search an entry in the dicache (given the Url). * Return value: a pointer to the entry of the _newest_ (i.e. highest) *               version if found; NULL otherwise. */DICacheEntry *a_Dicache_get_entry(const DilloUrl *Url){   DICacheHashEntry *hash_entry = g_hash_table_lookup(dicache_hash, Url);   DICacheEntry *entry;   if (!hash_entry || !hash_entry->valid)      return NULL;   for (entry = hash_entry->next; (entry && entry->next); entry = entry->next);   return entry;}/* * Search a particular version of an URL in the Dicache. * Return value: a pointer to the entry if found; NULL otherwise. */static DICacheEntry *Dicache_get_entry_version(const DilloUrl *Url,                                               gint version){   DICacheHashEntry *hash_entry = g_hash_table_lookup(dicache_hash, Url);   DICacheEntry *entry = hash_entry ? hash_entry->next : NULL;   while (entry && entry->version != version)      entry = entry->next;   return entry;}/* * Actually free a dicache entry, given the URL and the version number. */static void Dicache_remove(const DilloUrl *Url, gint version){   DICacheHashEntry *hash_entry = g_hash_table_lookup(dicache_hash, Url);   DICacheEntry *entry = hash_entry ? hash_entry->next : NULL, *prev = entry;   while (entry && (entry->version != version) ) {      prev = entry;      entry = entry->next;   }   if ( entry ) {      /* Eliminate this dicache entry */      g_free(entry->cmap);      if (entry->ImageBuffer) {         g_free(entry->ImageBuffer);         dicache_size_total -= entry->TotalSize;      }      a_Bitvec_free(entry->BitVec);      if (hash_entry->next == entry) {         if (!entry->next) {            /* last entry with this URL. Remove the hash entry as well */            g_hash_table_remove(dicache_hash, hash_entry->url);            a_Url_free(hash_entry->url);            g_free(hash_entry);         } else            hash_entry->next = entry->next;      } else         prev->next = entry->next;      g_free(entry);   }}/* * Unrefs the counter of a dicache entry, and _if_ no DwImage is acessing * this buffer _and_ there is a higher version of this image, then we call * Dicache_free to do the dirty job. */void a_Dicache_unref(const DilloUrl *Url, gint version){   DICacheEntry *entry;   if ( (entry = Dicache_get_entry_version(Url, version)) )      if (--entry->RefCount == 0 && (entry->next || !prefs.use_dicache) )         Dicache_remove(Url, version);}/* * Refs the counter of a dicache entry. */DICacheEntry* a_Dicache_ref(const DilloUrl *Url, gint version){   DICacheEntry *entry;   if ( (entry = Dicache_get_entry_version(Url, version)) )      ++entry->RefCount;   return entry;}/* * Invalidate this entry. This is used for the reloading mechanism. * Can't erase current versions, but a_Dicache_get_entry must return NULL. */void a_Dicache_invalidate_entry(const DilloUrl *Url){   DICacheHashEntry *hash_entry = g_hash_table_lookup(dicache_hash, Url);   if (hash_entry) hash_entry->valid = 0;}/* ------------------------------------------------------------------------- *//* * This function is a cache client; (but feeds its clients from dicache) */void a_Dicache_callback(int Op, CacheClient_t *Client){   /* todo: Handle Op = CA_Abort (to show what was got)  --Jcid */   gint i;   DilloWeb *Web = Client->Web;   DilloImage *Image = Web->Image;   DICacheEntry *DicEntry = a_Dicache_get_entry(Web->url);   g_return_if_fail ( DicEntry != NULL );   if ( Op == CA_Send ) {      if ( Image->height == 0 && DicEntry->State >= DIC_SetParms ) {         /* Set parms */         a_Image_set_parms(            Image, DicEntry->ImageBuffer, DicEntry->url,            DicEntry->version, DicEntry->width, DicEntry->height,            DicEntry->type);      }      if ( DicEntry->State == DIC_Write ) {         for ( i = 0; i < DicEntry->height; ++i )            if ( a_Bitvec_get_bit(DicEntry->BitVec, i) &&                 !a_Bitvec_get_bit(Image->BitVec, i) )               a_Image_write(                  Image, DicEntry->ImageBuffer + i*DicEntry->width*3, i,FALSE);      }   } else if ( Op == CA_Close || Op == CA_Abort ) {      a_Image_close(Web->Image);      a_Interface_close_client(Web->bw, Client->Key);   }}/* ------------------------------------------------------------------------- *//* * Set image's width, height & type * (By now, we'll use the image information despite the html tags --Jcid) */void a_Dicache_set_parms(DilloUrl *url, gint version, DilloImage *Image,                         gint width, gint height, DilloImgType type){   DICacheEntry *DicEntry;   size_t Size = width * height * 3;   g_return_if_fail ( Image != NULL && width && height );   /* Find the DicEntry for this Image */   DicEntry = Dicache_get_entry_version(url, version);   g_return_if_fail ( DicEntry != NULL );   /* Initialize the DicEntry */   DicEntry->ImageBuffer = g_new(guchar, Size);   DicEntry->TotalSize = Size;   DicEntry->width = width;   DicEntry->height = height;   DicEntry->type = type;   DicEntry->BitVec = a_Bitvec_new(height);   DicEntry->State = DIC_SetParms;   dicache_size_total += Size;   /* For giggles, make the background of the undrawn parts interesting */   memset(DicEntry->ImageBuffer, 0xdd, DicEntry->TotalSize);   /* Allocate and initialize this image */   a_Image_set_parms(Image, DicEntry->ImageBuffer, url, version,                     width, height, type);}/* * Implement the set_cmap method for the Image */void a_Dicache_set_cmap(DilloUrl *url, gint version, DilloImage *Image,                        const guchar *cmap, gint num_colors,                        gint num_colors_max, gint bg_index){   DICacheEntry *DicEntry = Dicache_get_entry_version(url, version);   g_return_if_fail ( DicEntry != NULL );   g_free(DicEntry->cmap);   DicEntry->cmap = g_new0(guchar, 3 * num_colors_max);   memcpy(DicEntry->cmap, cmap, 3 * num_colors);   if (bg_index >= 0 && bg_index < num_colors) {      DicEntry->cmap[bg_index * 3]     = (Image->bg_color >> 16) & 0xff;      DicEntry->cmap[bg_index * 3 + 1] = (Image->bg_color >> 8) & 0xff;      DicEntry->cmap[bg_index * 3 + 2] = (Image->bg_color) & 0xff;   }   a_Image_set_cmap(Image, DicEntry->cmap);   DicEntry->State = DIC_SetCmap;}/* * Implement the write method * (Write a scan line into the Dicache entry) * buf: row buffer * Y  : row number * x  : horizontal offset? (always zero) */void a_Dicache_write(DilloImage *Image, DilloUrl *url, gint version,                     const guchar *buf, gint x, gint Y){   DICacheEntry *DicEntry;   g_return_if_fail ( Image != NULL );   DicEntry = Dicache_get_entry_version(url, version);   g_return_if_fail ( DicEntry != NULL );   g_return_if_fail ( DicEntry->width > 0 && DicEntry->height > 0 );   a_Image_write(Image, buf, Y, TRUE);   DicEntry->Y = Y;   a_Bitvec_set_bit(DicEntry->BitVec, Y);   DicEntry->State = DIC_Write;}/* * Implement the close method of the decoding process */void a_Dicache_close(DilloUrl *url, gint version, CacheClient_t *Client){   DilloWeb *Web = Client->Web;   DICacheEntry *DicEntry = Dicache_get_entry_version(url, version);   g_return_if_fail ( DicEntry != NULL );   DicEntry->State = DIC_Close;   if (DicEntry->cmap) {      g_free(DicEntry->cmap);      DicEntry->cmap = NULL;   }   a_Image_close(Web->Image);   a_Interface_close_client(Web->bw, Client->Key);}/* ------------------------------------------------------------------------- */static gboolean Dicache_remove_hash_entry(gpointer key, gpointer value, gpointer user_data){   DICacheHashEntry *hash_entry = (DICacheHashEntry *)value;   DICacheEntry *entry = hash_entry->next;   /* Eliminate this (last) dicache entry */   g_free(entry->cmap);   if (entry->ImageBuffer) {      g_free(entry->ImageBuffer);      dicache_size_total -= entry->TotalSize;   }   a_Bitvec_free(entry->BitVec);   a_Url_free(hash_entry->url);   g_free(hash_entry);   return TRUE;}/* * Deallocate memory used by dicache module * (Call this one at exit time) */void a_Dicache_freeall(void){   /* Remove every dicache entry */   g_hash_table_foreach_remove(dicache_hash,                               (GHRFunc)Dicache_remove_hash_entry, NULL);   /* Remove the dicache hash */   g_hash_table_destroy(dicache_hash);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -