Index: apps/plugins/CATEGORIES
===================================================================
--- apps/plugins/CATEGORIES	(revisão 27496)
+++ apps/plugins/CATEGORIES	(cópia de trabalho)
@@ -32,6 +32,7 @@
 firmware_flash,apps
 flipit,games
 frotz,viewers
+gifview,viewers
 goban,games
 greyscale,demos
 helloworld,demos
Index: apps/plugins/SOURCES
===================================================================
--- apps/plugins/SOURCES	(revisão 27496)
+++ apps/plugins/SOURCES	(cópia de trabalho)
@@ -180,6 +180,7 @@
 clix.c
 ppmviewer.c
 codebuster.c
+gifview.c
 #endif
 
 #if (LCD_WIDTH > 112) && (LCD_HEIGHT > 64)
Index: apps/plugins/gifview.c
===================================================================
--- apps/plugins/gifview.c	(revisão 0)
+++ apps/plugins/gifview.c	(revisão 0)
@@ -0,0 +1,728 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id: viewbox.c,v 0.46 2005/12/09
+ *
+ * Copyright (C) 2005 Eli Sherer
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "plugin.h"
+
+#ifdef HAVE_LCD_BITMAP
+#ifdef HAVE_LCD_COLOR
+
+PLUGIN_HEADER
+
+/* variable button definitions */
+#if CONFIG_KEYPAD == RECORDER_PAD
+#define GIF_ZOOM_IN BUTTON_PLAY
+#define GIF_ZOOM_OUT BUTTON_ON
+#define GIF_UP BUTTON_UP
+#define GIF_DOWN BUTTON_DOWN
+#define GIF_LEFT BUTTON_LEFT
+#define GIF_RIGHT BUTTON_RIGHT
+#define GIF_NEXT BUTTON_F3
+#define GIF_PREVIOUS BUTTON_F2
+#define GIF_MENU BUTTON_OFF
+
+#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
+#define GIF_ZOOM_IN BUTTON_SELECT
+#define GIF_ZOOM_OUT BUTTON_ON
+#define GIF_UP BUTTON_UP
+#define GIF_DOWN BUTTON_DOWN
+#define GIF_LEFT BUTTON_LEFT
+#define GIF_RIGHT BUTTON_RIGHT
+#define GIF_NEXT BUTTON_F3
+#define GIF_PREVIOUS BUTTON_F2
+#define GIF_MENU BUTTON_OFF
+
+#elif CONFIG_KEYPAD == ONDIO_PAD
+#define GIF_ZOOM_PRE BUTTON_MENU
+#define GIF_ZOOM_IN (BUTTON_MENU | BUTTON_REL)
+#define GIF_ZOOM_OUT (BUTTON_MENU | BUTTON_DOWN)
+#define GIF_UP BUTTON_UP
+#define GIF_DOWN BUTTON_DOWN
+#define GIF_LEFT BUTTON_LEFT
+#define GIF_RIGHT BUTTON_RIGHT
+#define GIF_NEXT (BUTTON_MENU | BUTTON_RIGHT)
+#define GIF_PREVIOUS (BUTTON_MENU | BUTTON_LEFT)
+#define GIF_MENU BUTTON_OFF
+
+#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
+      (CONFIG_KEYPAD == IRIVER_H300_PAD)
+#define GIF_ZOOM_IN BUTTON_SELECT
+#define GIF_ZOOM_OUT BUTTON_MODE
+#define GIF_UP BUTTON_UP
+#define GIF_DOWN BUTTON_DOWN
+#define GIF_LEFT BUTTON_LEFT
+#define GIF_RIGHT BUTTON_RIGHT
+#if (CONFIG_KEYPAD == IRIVER_H100_PAD)
+#define GIF_NEXT BUTTON_ON
+#define GIF_PREVIOUS BUTTON_REC
+#else
+#define GIF_NEXT BUTTON_REC
+#define GIF_PREVIOUS BUTTON_ON
+#endif
+#define GIF_MENU BUTTON_OFF
+#define GIF_RC_MENU BUTTON_RC_STOP
+
+#elif (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD)
+#define GIF_ZOOM_IN BUTTON_SCROLL_FWD
+#define GIF_ZOOM_OUT BUTTON_SCROLL_BACK
+#define GIF_UP BUTTON_MENU
+#define GIF_DOWN BUTTON_PLAY
+#define GIF_LEFT BUTTON_LEFT
+#define GIF_RIGHT BUTTON_RIGHT
+#define GIF_MENU (BUTTON_SELECT | BUTTON_MENU)
+#define GIF_NEXT (BUTTON_SELECT | BUTTON_RIGHT)
+#define GIF_PREVIOUS (BUTTON_SELECT | BUTTON_LEFT)
+
+#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
+#define GIF_ZOOM_PRE BUTTON_SELECT
+#define GIF_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
+#define GIF_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
+#define GIF_UP BUTTON_UP
+#define GIF_DOWN BUTTON_DOWN
+#define GIF_LEFT BUTTON_LEFT
+#define GIF_RIGHT BUTTON_RIGHT
+#define GIF_MENU BUTTON_POWER
+#define GIF_NEXT BUTTON_PLAY
+#define GIF_PREVIOUS BUTTON_REC
+
+#elif CONFIG_KEYPAD == GIGABEAT_PAD
+#define GIF_ZOOM_PRE BUTTON_MENU
+#define GIF_ZOOM_IN (BUTTON_MENU | BUTTON_REL)
+#define GIF_ZOOM_OUT (BUTTON_MENU | BUTTON_REPEAT)
+#define GIF_UP BUTTON_UP
+#define GIF_DOWN BUTTON_DOWN
+#define GIF_LEFT BUTTON_LEFT
+#define GIF_RIGHT BUTTON_RIGHT
+#define GIF_MENU BUTTON_A
+#define GIF_NEXT (BUTTON_POWER | BUTTON_RIGHT)
+#define GIF_PREVIOUS (BUTTON_POWER | BUTTON_LEFT)
+
+#elif CONFIG_KEYPAD == SANSA_E200_PAD
+#define GIF_ZOOM_PRE BUTTON_SELECT
+#define GIF_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
+#define GIF_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
+#define GIF_UP BUTTON_UP
+#define GIF_DOWN BUTTON_DOWN
+#define GIF_LEFT BUTTON_LEFT
+#define GIF_RIGHT BUTTON_RIGHT
+#define GIF_MENU BUTTON_REC
+#define GIF_NEXT BUTTON_SCROLL_DOWN
+#define GIF_PREVIOUS BUTTON_SCROLL_UP
+
+#elif CONFIG_KEYPAD == IRIVER_H10_PAD
+#define GIF_ZOOM_PRE BUTTON_PLAY
+#define GIF_ZOOM_IN (BUTTON_PLAY | BUTTON_REL)
+#define GIF_ZOOM_OUT (BUTTON_PLAY | BUTTON_REPEAT)
+#define GIF_UP BUTTON_SCROLL_UP
+#define GIF_DOWN BUTTON_SCROLL_DOWN
+#define GIF_LEFT BUTTON_LEFT
+#define GIF_RIGHT BUTTON_RIGHT
+#define GIF_MENU BUTTON_POWER
+#define GIF_NEXT BUTTON_FF
+#define GIF_PREVIOUS BUTTON_REW
+
+#endif
+
+#define TRANSPARENT_RED   0
+#define TRANSPARENT_GREEN 0
+#define TRANSPARENT_BLUE  0
+
+#define MAX_SAVE_FRAMES 3
+
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif 
+
+#ifdef __GNUC__
+#define STRUCT_PACKED __attribute__((packed))
+#else
+#define STRUCT_PACKED
+#pragma pack (push, 2)
+#endif
+
+/* max decoder pixel stack size */
+#define MAXSTACKSIZE 4096
+
+struct GIF_RGB { /* reveresed */
+  unsigned char Red; 
+  unsigned char Green; 
+  unsigned char Blue; 
+}STRUCT_PACKED;
+
+struct GIF_RECT { /* reveresed */
+  short x,y,w,h;
+}STRUCT_PACKED;
+
+static int fd; //File Descriptor
+	static unsigned char chTemp;
+	static unsigned short srTemp;
+	//static unsigned long lnTemp;
+	
+	/* header stuff*/
+	static char magic[6];
+    static unsigned short gif_width, gif_height;
+	static unsigned char packed;
+		static bool gctFlag; // global color table used
+		static unsigned short gctSize; // global color table size
+	static struct GIF_RGB gct[256]; // global color table (optional)
+	static unsigned char bgIndex; // background color index
+	static unsigned char pixelAspect; // pixel aspect ratio
+	
+	static struct GIF_RGB bgColor,lastBgColor; // background color
+
+	static struct GIF_RGB lct[256]; // local color table
+
+	static int loopCount = 1; // iterations; 0 = repeat forever
+	static int frameCount = 0;
+	//static int currentFrame = 0;
+	
+	static bool lctFlag; // local color table flag
+	static bool interlace; // interlace flag
+	static int lctSize; // local color table size
+	static int ix, iy, iw, ih; // current image rectangle
+	static struct GIF_RECT lastRect;
+	static unsigned char block[256]; // current data block
+	static int blockSize = 0; // block size
+	static int dispose = 0; // last graphic control extension info
+	static int lastDispose = 0; // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev
+	static bool transparency = false; // use transparent color
+	static int delay = 0; // delay in milliseconds
+	static int transIndex; // transparent color index
+
+	// LZW decoder working arrays
+	static short prefix[MAXSTACKSIZE];
+	static unsigned char suffix[MAXSTACKSIZE];
+	static unsigned char pixelStack[MAXSTACKSIZE];
+	static unsigned char *pixels;//[MAX_SAVE_FRAMES];
+	static unsigned char *lastpixels;
+	
+	/***************** Dynamic Memory Allocation Code *****************/
+	
+	static void *malloc_buffer;
+	static unsigned int malloc_size,malloc_free;
+
+	void init_malloc(void)
+	{
+		/* get the remainder of the plugin buffer */
+		malloc_buffer = rb->plugin_get_buffer(&malloc_size);
+		
+		/* save for freeing purposes */
+		malloc_free = malloc_size;
+	}
+	void my_free(void *ptr,size_t size)
+	{
+		if (malloc_free >= size+4)
+		{
+			malloc_buffer -= size + 4;
+			malloc_free += size + 4;
+		}
+		else //clean buffer if an error cought
+		{	malloc_buffer-=(malloc_size-malloc_free);
+			malloc_free=malloc_size; //buffer is empty
+		}
+		ptr=NULL;
+	}
+	void *my_malloc(size_t size)
+	{
+		void *alloc;
+	
+		if (size + 4 > malloc_free)
+			return NULL;
+		alloc = malloc_buffer;
+		malloc_buffer += size + 4;
+		malloc_free -= size + 4;
+		return alloc;
+	}
+	/***************** End of Dynamic Memory Allocation Code *****************/
+
+	/**
+	 * Creates new frame image from current data (and previous
+	 * frames as specified by their disposition codes).
+	 */
+	/*int getbeforelast(int currentFrame)
+	{
+		return (currentFrame>1?currentFrame-2:currentFrame-2+MAX_SAVE_FRAMES);
+	}*/
+	void DrawPixels(int x0,int y0)
+	{	
+		int pass=1,n,inc=8,iline=0;
+		int line,dlim,sx,index,r,g,b,x,y;
+		struct GIF_RGB c;
+		
+		// fill in starting image contents based on last image's dispose code
+		// 0- no need to do anything
+		// 1- don't dispose
+		// 2- put background color
+		// 3- restore area overwritten last time
+		DEBUGF("lastdisp-%d\n",dispose,lastDispose);
+		if (lastDispose > 0) 
+		{	if (lastDispose == 3) 
+			{	// use image before last
+				n=frameCount-2;
+				if (n > 0) 
+				{	//for(i=0;i<ih*iw;i++) pixels[currentFrame][i]=pixels[getbeforelast(currentFrame)][i];
+					DEBUGF("USED\n");
+				}
+			}
+			//if (lastPixels)
+			//{
+				if (lastDispose == 2)
+				{   // fill last image rect area with background color
+					if (transparency)
+					{	c.Red = TRANSPARENT_RED;
+						c.Green = TRANSPARENT_GREEN;
+						c.Blue = TRANSPARENT_BLUE;
+					}
+					else // use given background color
+					{	c.Red = lastBgColor.Red;
+						c.Green = lastBgColor.Green;
+						c.Blue = lastBgColor.Blue;
+					}
+					rb->lcd_set_foreground(LCD_RGBPACK(c.Red,c.Green,c.Blue));
+					rb->lcd_fillrect(x0+lastRect.x,y0+lastRect.y,lastRect.w,lastRect.h);
+				}
+			//}
+		}
+
+		// copy each source line to the appropriate place in the destination
+		for (y = 0; y < ih; y++) {
+			line = y;
+			if (interlace) {
+				if (iline >= ih) {
+					pass++;
+					switch (pass) {
+						case 2 :
+							iline = 4;
+							break;
+						case 3 :
+							iline = 2;
+							inc = 4;
+							break;
+						case 4 :
+							iline = 1;
+							inc = 2;
+					}
+				}
+				line = iline;
+				iline += inc;
+			}
+			line += iy;
+				
+			if (line < gif_height) {
+				x = ix; // start of line in dest
+				dlim = x + iw; // end of dest line
+				if ((x + gif_width) < dlim) {
+					dlim = x + gif_width; // past dest edge
+				}
+				sx = y * iw; // start of line in source
+				while (x < dlim) {
+					// map color and insert in destination
+					index = pixels[sx];
+					if ((index==transIndex)&&(frameCount>1)) index = lastpixels[y*gif_width+x];
+					lastpixels[y*gif_width+x]=index;
+					if (gctFlag)
+					{	r=gct[index].Red;
+						g=gct[index].Green;
+						b=gct[index].Blue;
+					}
+					else
+					{	r=lct[index].Red;
+						g=lct[index].Green;
+						b=lct[index].Blue;
+					}
+					rb->lcd_set_foreground(LCD_RGBPACK(r,g,b));
+					rb->lcd_drawpixel(x0+x,y0+y);
+					x++;
+					sx++; //pixel pointer
+				}
+			}
+		}
+		rb->lcd_update();
+	}
+
+	/**
+	 * Reads next variable length block from input.
+	 *
+	 * @return number of bytes stored in "buffer"
+	 */
+	static int readBlock(void)
+	{	int ret;
+		ret = rb->read(fd, &blockSize, sizeof(unsigned char)); //BlockSize
+		if ((blockSize > 0)&&(blockSize<=256)&&(ret>0))
+			ret=rb->read(fd, block, sizeof(unsigned char)*blockSize);
+		else return -1;
+		if (ret) return blockSize;
+		else return -1;
+	}
+
+	static void skipBlock(void)
+	{
+		while (readBlock()>0) DEBUGF("z");
+	}
+	
+	/**
+	 * Decodes LZW image data into pixel array.
+	 * Adapted from John Cristy's ImageMagick.
+	 */
+	static void decodeImageData(void) {
+		int NullCode = -1;
+		int npix = iw * ih;
+		int available=0,clear=0,code_mask=0,code_size=0,end_of_information=0,in_code=0,
+			old_code=0,bits=0,code=0,count=0,i=0,datum=0,first=0,top=0,bi=0,pi=0;
+		unsigned char data_size;
+		
+		pixels = (char*)my_malloc(npix*sizeof(char));
+		
+		/*  Initialize GIF data stream decoder. */
+
+		rb->read(fd, &data_size, sizeof(unsigned char));
+		clear = 1 << data_size;
+		end_of_information = clear + 1;
+		available = clear + 2;
+		old_code = NullCode;
+		code_size = data_size + 1;
+		code_mask = (1 << code_size) - 1;
+		for (code = 0; code < clear; code++) {
+			prefix[code] = 0;
+			suffix[code] = (unsigned char) code;
+		}
+
+		/*  Decode GIF pixel stream. */
+		for (i = 0; i < npix;)
+		{
+			if (top == 0)
+			{
+				if (bits < code_size)
+				{	/*  Load bytes until there are enough bits for a code. */
+					if (count == 0)
+					{	count = readBlock(); /* Read a new data block. */
+						if (count <= 0) break;
+						bi = 0;
+					}
+					datum += (((int) block[bi]) & 0xff) << bits;
+					bits += 8;
+					bi++;
+					count--;
+					continue;
+				}
+				/*  Get the next code. */
+				code = datum & code_mask;
+				datum >>= code_size;
+				bits -= code_size;
+				/*  Interpret the code */
+				if ((code > available) || (code == end_of_information)) break;
+				if (code == clear) /*  Reset decoder. */
+				{	code_size = data_size + 1;
+					code_mask = (1 << code_size) - 1;
+					available = clear + 2;
+					old_code = NullCode;
+					continue;
+				}
+				if (old_code == NullCode)
+				{	pixelStack[top++] = suffix[code];
+					old_code = code;
+					first = code;
+					continue;
+				}
+				in_code = code;
+				if (code == available)
+				{	pixelStack[top++] = (unsigned char) first;
+					code = old_code;
+				}
+				while (code > clear)
+				{	pixelStack[top++] = suffix[code];
+					code = prefix[code];
+				}
+				first = ((int) suffix[code]) & 0xff;
+				/*  Add a new string to the string table, */
+				if (available >= MAXSTACKSIZE) break;
+				pixelStack[top++] = (unsigned char) first;
+				prefix[available] = (short) old_code;
+				suffix[available] = (unsigned char) first;
+				available++;
+				if (((available & code_mask) == 0)&&(available < MAXSTACKSIZE))
+				{	code_size++;
+					code_mask += available;
+				}
+				old_code = in_code;
+			}
+			/*  Pop a pixel off the pixel stack. */
+			top--;
+			pixels[pi++] = pixelStack[top];
+			i++;
+		}
+		/* clear missing pixels */
+		for (i = pi; i < npix; i++) {
+			pixels[i] = 0;
+		}
+	}
+
+	/**
+	 * Reads Graphics Control Extension values
+	 */
+	static void readGraphicControlExt(void)
+	{	unsigned char packed;
+		rb->read(fd, &chTemp, sizeof(unsigned char)); //size of block
+		rb->read(fd, &packed, sizeof(unsigned char)); // packed fields
+		dispose = (packed & 0x1c) >> 2; // disposal method
+		if (dispose == 0) {
+			//dispose = 1; // elect to keep old image if discretionary
+		}
+		transparency = (packed & 1) != 0;
+		rb->read(fd, &srTemp, sizeof(unsigned short));
+		delay = letoh16(srTemp) * 10; // delay in milliseconds
+		rb->read(fd, &transIndex, sizeof(unsigned char));// transparent color index
+		rb->read(fd, &chTemp, sizeof(unsigned char)); //terminator of block
+	}
+
+	/**
+	 * Reads next frame image
+	 */
+	static void readImage(int x0,int y0)
+	{	unsigned char packed;
+		struct GIF_RGB save;
+		
+		// (sub)image position & size
+		rb->read(fd, &srTemp, sizeof(unsigned short));
+		ix = letoh16(srTemp);
+		rb->read(fd, &srTemp, sizeof(unsigned short));
+		iy = letoh16(srTemp);
+		rb->read(fd, &srTemp, sizeof(unsigned short));
+		iw = letoh16(srTemp);
+		rb->read(fd, &srTemp, sizeof(unsigned short));
+		ih = letoh16(srTemp);
+		rb->read(fd, &packed, sizeof(unsigned char)); // packed fields
+		lctFlag = (packed & 0x80) != 0; // 1 - local color table flag
+		interlace = (packed & 0x40) != 0; // 2 - interlace flag
+		// 3 - sort flag
+		// 4-5 - reserved
+		lctSize = 2 << (packed & 7); // 6-8 - local color table size
+
+		if (lctFlag) {
+			rb->read(fd, &lct, sizeof(unsigned char)*lctSize*3); // read table
+		} else {
+			if (bgIndex == transIndex)
+			{	bgColor.Red=TRANSPARENT_RED;
+				bgColor.Green=TRANSPARENT_GREEN;
+				bgColor.Blue=TRANSPARENT_BLUE;
+			}
+		}
+		if (transparency) {
+			if (lctFlag)
+			{	save.Red = lct[transIndex].Red;
+				save.Green = lct[transIndex].Green;
+				save.Blue = lct[transIndex].Blue;
+				lct[transIndex].Red=TRANSPARENT_RED;
+				lct[transIndex].Green=TRANSPARENT_GREEN;
+				lct[transIndex].Blue=TRANSPARENT_BLUE;
+			}
+			else
+			{	save.Red = gct[transIndex].Red;
+				save.Green = gct[transIndex].Green;
+				save.Blue = gct[transIndex].Blue;
+				gct[transIndex].Red=TRANSPARENT_RED;
+				gct[transIndex].Green=TRANSPARENT_GREEN;
+				gct[transIndex].Blue=TRANSPARENT_BLUE;
+			}
+		}
+		decodeImageData(); // decode pixel data
+		skipBlock();
+		
+		frameCount++;
+		DrawPixels(x0,y0); // transfer pixel data to image
+		
+		// this is to ensure that other colors that was
+		// indexed to be transparent like pink won't appear in the
+		// image but in black
+		if (transparency) {
+			if (lctFlag)
+			{	lct[transIndex].Red=save.Red;
+				lct[transIndex].Green=save.Green;
+				lct[transIndex].Blue=save.Blue;
+			}
+			else
+			{	gct[transIndex].Red=save.Red;
+				gct[transIndex].Green=save.Green;
+				gct[transIndex].Blue=save.Blue;
+			}
+		}
+		
+		lastDispose = dispose;
+		lastRect.x=ix;
+		lastRect.y=iy;
+		lastRect.w=iw;
+		lastRect.h=ih;
+ 		
+		//my_free(pixels,iw*ih*sizeof(char));
+		
+		lastBgColor.Red = bgColor.Red;
+		lastBgColor.Green = bgColor.Green;
+		lastBgColor.Blue = bgColor.Blue;
+		
+		dispose = 0;
+		transparency = false;
+		rb->sleep(5);
+		//currentFrame++;
+		//if (currentFrame>=MAX_SAVE_FRAMES)
+		//{	currentFrame=0;
+		//	init_malloc();
+		//}
+		delay = 0;
+	}
+
+	/**
+	 * Reads Netscape extenstion to obtain iteration count
+	 */
+	static void readNetscapeExt(void)
+	{	int b1,b2;
+		readBlock();
+		if (block[0] == 1) {
+			// loop count sub-block
+			b1 = ((int) block[1]) & 0xff;
+			b2 = ((int) block[2]) & 0xff;
+			loopCount = (b2 << 8) | b1;
+		}
+	}
+
+int loadgif(int x0,int y0,const char* filename)
+{
+  
+	bool done=false;
+	unsigned char code;
+
+	fd = rb->open(filename, O_RDONLY); 
+    if (fd<0) {
+    	rb->splash(HZ,"couldn't read file");
+    	return 0;
+    }
+	
+	init_malloc();
+	
+	/**
+	 * Reads GIF file header information.
+	 */
+	rb->read(fd, magic, sizeof(unsigned char)*6);
+	/* check for valid gif file */
+	if ((magic[0]=='G')&&(magic[1]=='I')&&(magic[2]=='F'))
+	{	/**
+		* Reads Logical Screen Descriptor
+		*/
+			// logical screen size
+			rb->read(fd, &srTemp, sizeof(unsigned short));
+			gif_width = letoh16(srTemp);
+			rb->read(fd, &srTemp, sizeof(unsigned short));
+			gif_height = letoh16(srTemp);
+
+			// packed fields (flags)
+			rb->read(fd, &packed, sizeof(unsigned char));
+				gctFlag = (packed & 0x80) != 0; // 1   : global color table flag
+				// 2-4 : color resolution
+				// 5   : gct sort flag
+				gctSize = 2 << (packed & 7); // 6-8 : gct size
+
+			// background color index
+			rb->read(fd, &bgIndex, sizeof(unsigned char));
+			// pixel aspect ratio
+			rb->read(fd, &pixelAspect, sizeof(unsigned char));
+			if (gctFlag)
+			{	rb->read(fd, &gct, sizeof(unsigned char)*gctSize*3);
+				bgColor = gct[bgIndex];
+			}
+			lastpixels=(char*)my_malloc(gif_width*gif_height*sizeof(char));
+		/**
+		* Read Contents 
+		*/
+		while (!done)
+		{
+			rb->read(fd, &code, sizeof(unsigned char));
+			switch (code) {
+				case 0x2C : // image separator
+						readImage(x0,y0);
+					break;
+				case 0x21 : // extension
+					rb->read(fd, &code, sizeof(unsigned char));
+					switch (code) {
+						case 0xf9 : // graphics control extension
+							readGraphicControlExt();
+							DEBUGF("%d",dispose);
+							break;
+						case 0xff : // application extension
+							readBlock();
+							if ((block[0]=='N')&&(block[10]=='0')) //"NETSCAPE2.0"
+								readNetscapeExt();
+							else
+								skipBlock(); // don't care
+							break;
+						default : // uninteresting extension
+							skipBlock();
+							break;
+					}
+					break;
+				case 0x3b : // terminator
+					done = true;
+					break;
+				case 0x00 : // bad byte, but keep going and see what happens
+				    //rb->splash(HZ*2, true, "Err: Bad byte");
+					//return 0;
+					DEBUGF("00");
+					break;
+				default :
+					DEBUGF("%x",code);
+					break;
+			}
+		}
+		
+	}
+	rb->close(fd); 
+    rb->lcd_update();
+    return 1;
+
+}
+
+enum plugin_status plugin_start(const void* parameter)
+{
+
+
+    rb->lcd_set_foreground(LCD_BLACK);
+    rb->lcd_fillrect(0,0,LCD_WIDTH,LCD_HEIGHT);
+    rb->splash(HZ, "Loading"); 
+
+    if (parameter) /* viewer startup */
+	{  
+		#ifndef SIMULATOR
+		#ifdef CPU_BOOST_LOGGING
+			rb->cpu_boost(true);
+		#endif 
+		#endif
+	   loadgif(0,0, ( char*)parameter);
+		#ifndef SIMULATOR
+		#ifdef CPU_BOOST_LOGGING
+			rb->cpu_boost(false);
+		#endif 
+		#endif
+
+	   rb->button_get(true);
+	}
+    return PLUGIN_OK;
+}
+
+#endif
+#endif
