From: ron@mlfarm.com (Ronald Florence)
Subject: Re: GIF viewer for Xenix
Organization: Maple Lawn Farm, Stonington, CT
Date: Wed, 19 Aug 1992 12:54:33 GMT

David Mason writes:

  [...] is there a .GIF viewer even for standard VGA for SCO Xenix 386
  2.3.2?

This works, or at least did when we had a Xenix box here.  You will
need the CGI package, and the CGIDISP and CGIPATH environmental
variables.  With a little work, someone could add panning with mouse
control for large gifs.  I'm not sure whether the SCO CGI includes a
driver for super-VGA displays.


				Ronald Florence
				ron@mlfarm.com



#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	Makefile
#	gif.c
# This archive created: Wed Aug 19 08:48:11 1992
# By:	Ronald Florence (Maple Lawn Farm, Stonington, CT )
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'Makefile'" '(181 characters)'
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
X# tek/gif makefile
X# copyright 1990 Ronald Florence
X# 
X# add -DBROKEN_MONO_VGA to CFLAGS if needed
X
XCC = gcc -m80387
XCFLAGS= -O -DBROKEN_MONO_VGA
XLDFLAGS= /usr/lib/386/Slibccgi.a
X
X
SHAR_EOF
if test 181 -ne "`wc -c < 'Makefile'`"
then
	echo shar: "error transmitting 'Makefile'" '(should have been 181 characters)'
fi
fi
echo shar: "extracting 'gif.c'" '(11281 characters)'
if test -f 'gif.c'
then
	echo shar: "will not over-write existing file 'gif.c'"
else
sed 's/^X//' << \SHAR_EOF > 'gif.c'
X/*
Xgif.c - gif viewer for SCO CGI
Xcopyright 1990 Ronald Florence (ron@mlfarm, 6.18.90)
X 
X(parts based on an SGI Iris viewer of unknown origins)
X
XTo use this viewer, you need both the CGIPATH and CGIDISP
Xenvironmental variables declared.
X
XPermission is hereby granted for unlimited non-commercial
Xuse of this program, on condition that the copyright notices
Xare left intact and any modifications to the source code are
Xnoted as such.  No warranty of any kind is implied or
Xgranted for this material.  
X
X*/
X
X
X#include <stdio.h>
X#include <signal.h>
X
Xtypedef unsigned char Uchar;
Xshort	cgidev, Ystep, Xmax;
X
Xtypedef struct {
X  int	dx, dy;			/* size */
X  int	colors,			/* # colors */
X	bits,			/* bits/pixel */
X	cr;			/* color resolution */
X  char	gcm,			/* global color map flag */
X	bgnd;			/* background color */
X} screen_dscrp;
X
Xtypedef struct {
X  int	x, y, dx, dy,		/* position, size */
X	colors, bits;		/* num colors, bits/pixel */
X  char	gcm,			/* use global color map */
X	order;			/* seq. or interlaced */
X} image_dscrp;
X
XUchar		g_colors[256][3],	/* Global color map */
X		pixel_row[4096];
Xint		bits_left, 
X		byte_count,
X		mask[14] = {0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff,
X			0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff},
X		code_size, countsize, countdown,
X		dy_table[4] = {8, 8, 4, 2}, 
X		offset_table[4] = {0, 4, 2, 1},
X		last_char, bit_mask, least_bits;
Xshort		code_table[4096][2], 
X		cmap;
XFILE		*stream_source;		/* file for input */
Xscreen_dscrp	si;			/* global screen descriptor */
X
X
X
Xint	mscanf(infile, parse)
X     FILE *infile; 
X     char *parse;
X{
X  char	*scan;
X  int	dx, dy;
X
X  for (scan = parse; *scan; scan++)
X    if (getc(infile) != (int)*scan) 
X      return(0);
X  return(!0);
X}
X
X
Xint	scan_SD(infile, sd)
X     FILE *infile;
X     screen_dscrp *sd;
X{
X  Uchar	data;
X
X  data = (Uchar)getc(infile);
X  sd->dx = data + ((Uchar)getc(infile) << 8);
X  data = (Uchar)getc(infile);
X  sd->dy = data + ((Uchar)getc(infile) << 8);
X  data = getc(infile);
X  if (data & 8) 
X    return(0);
X  sd->gcm = data & 0x80;
X  sd->cr = (data & 0x70) >> 4;
X  sd->bits = (data & 7) + 1;
X  sd->colors = 1 << sd->bits;
X  sd->bgnd = getc(infile);
X  if (getc(infile) != 0) 
X    return(0);
X  return(!0);
X}
X
X
Xvoid	skip_EB(infile)
X     FILE *infile;
X{
X  int	count;
X  char	garbage[256];
X
X  getc(infile);		/* get function */
X  while (count = getc(infile)) 
X    fread(garbage, 1, count, infile);
X}
X
X
Xint	scan_ID(infile, id)
X     FILE *infile;
X     image_dscrp *id;
X{
X  Uchar	data;
X
X  do 
X    {
X      data = (Uchar)getc(infile);
X      if (data == ';') 
X	return(1);
X      if (feof(infile)) 
X	return(0);
X      if (data ==0x21) 
X	skip_EB(infile);
X    } while (data != 0x2c);
X  data = (Uchar)getc(infile);
X  id->x = data + ((Uchar)getc(infile) << 8);
X  data = (Uchar)getc(infile);
X  id->y = data + ((Uchar)getc(infile) << 8);
X  data = (Uchar)getc(infile);
X  id->dx = data + ((Uchar)getc(infile) << 8);
X  data = (Uchar)getc(infile);
X  id->dy = data + ((Uchar)getc(infile) << 8);
X  data = (Uchar)getc(infile);
X  id->gcm = data & 0x80;
X  id->order = data & 0x40;
X  id->bits = (data & 7) + 1;
X  id->colors = 1 << id->bits;
X  return(2);
X}
X
X
Xvoid	scan_CM(infile, colors, cm)
X     FILE *infile;
X     int colors;
X     Uchar *cm;
X{
X  Uchar	*scan;
X  int	i;
X
X  for (scan = cm, i = 3 * colors; i > 0; i--)
X    *scan++ = (Uchar)getc(infile);
X}
X
X
Xvoid	reset_codes()
X{
X  code_size = least_bits + 1;
X  if (code_size <= 2) 
X    code_size = 3;
X  countsize = 1 << code_size;
X  countdown = countsize - (1 << least_bits) - 2;
X  bit_mask = (long)mask[code_size];
X}
X
X
Xvoid	clear_stream(infile, bits)
X     FILE *infile;
X     int bits;
X{
X  getc(infile);		/* skip minimum bit size */
X  byte_count = 0;
X  last_char = 0;
X  bits_left = 0;
X  least_bits = bits;
X  stream_source = infile;
X  reset_codes();
X}
X
X
Xshort	get_code()
X{
X  static char	flag = 0;
X  short		code;
X  int		new;
X
X  if (byte_count == 0) 
X    byte_count = getc(stream_source);
X  if (bits_left < code_size) 
X    {
X      new = (int)getc(stream_source);
X      byte_count--;
X      if (bits_left + 8 < code_size) 
X	{
X	  if (byte_count == 0) 
X	    byte_count = getc(stream_source);
X	  byte_count--;
X	  new |= ((int)getc(stream_source) << 8);
X	  code = 16; 
X	}
X      else 
X	code = 8;
X      if (bits_left) 
X	new <<= bits_left;
X      last_char |= new;
X      bits_left += code;
X    }
X  code = (short)(last_char & bit_mask);
X  last_char >>= code_size;
X  bits_left -= code_size;
X  if (flag) 
X    {
X      flag = 0;
X      reset_codes();
X    }
X  else if (--countdown == 0) 
X    {
X      countdown = countsize;
X      countsize <<= 1;
X      if (++code_size == 13) 
X	{ 
X	  flag = 1; 
X	  code_size--; 
X	}
X      else 
X	bit_mask = (int)mask[code_size];
X    }
X  return(code);
X}
X
X
Xvoid	install_cmap(colors, cm)
X     int colors;
X     Uchar *cm;
X{
X  Uchar	*scan;
X  unsigned int color;
X  int	i;
X  short rgb[3], rgb_out[3];
X
X  for (scan = cm, i = cmap; colors > 0; scan += 3, i++, colors--)
X    {
X#ifndef BROKEN_MONO_VGA
X      rgb[0] = *scan << 2;
X      rgb[1] = *(scan + 1) << 2;
X      rgb[2] = *(scan + 2) << 2;
X#else
X      color = 77 * *scan + 150 * *(scan + 1) + 29 * *(scan +2);
X      rgb[0] = rgb[1] = rgb[2] = color >> 6;
X#endif
X      vs_color(cgidev, i, rgb, rgb_out);
X    }
X}
X
X
Xvoid	setup_codes(colors)
X     int colors;
X{
X  int	i;
X
X  for (i = 0; i < colors; i++) 
X    code_table[i][0] = code_table[i][1] = i;
X}
X
X
Xvoid	read_interlaced(id)
X     image_dscrp *id;
X{
X  int	table_ptr, row_count, dy, y, pass, end_code, clear_code;
X  short	prefix, suffix, save, stack[4096], *stack_ptr;
X  Uchar *pixel = pixel_row;
X  short origin[2], v_width[2], v_height[2];
X
X  v_width[0] = id->x;
X  v_width[1] = (id->x + id->dx - 1 > Xmax) ? Xmax : id->x + id->dx - 1;
X  v_height[0] = v_height[1] = 0;
X  origin[0] = 0;
X
X  row_count = id->dx;
X  clear_code = id->colors;
X  end_code = clear_code + 1;
X  while ((prefix = get_code()) == clear_code)
X    ;
X  reset_codes();
X  table_ptr = clear_code + 2;
X  for (pass = 0; pass < 4; pass++) 
X    {
X      y = id->y + id->dy - 1 - offset_table[pass];
X      dy = dy_table[pass];
X      while (y >= 0 && (save = suffix = get_code()) != end_code) 
X	{
X	  if (suffix == clear_code) 
X	    {
X	      reset_codes();
X	      while ((save = get_code()) == clear_code)
X		;
X	      reset_codes();
X	      table_ptr = clear_code + 1;
X	    }
X          else 
X	    {
X	      code_table[table_ptr][0] = prefix;
X	      if (suffix == table_ptr)
X		code_table[table_ptr][1] = code_table[prefix][1];
X	      else 
X		{
X		  while (suffix >= id->colors) 
X		    suffix = code_table[suffix][0];
X		  code_table[table_ptr][1] = suffix;
X		}
X	    }
X	  suffix = 1;
X	  stack_ptr = stack;
X	  while (prefix >= id->colors) 
X	    {
X	      *stack_ptr++ = code_table[prefix][1];
X	      prefix = code_table[prefix][0];
X	      suffix++;
X	    }
X	  *stack_ptr = prefix;
X	  for ( ; suffix > 0; stack_ptr--, suffix--) 
X	    {
X	      *pixel++ = (Uchar)(cmap + *stack_ptr);
X	      if (--row_count == 0) 
X		{
X		  row_count = id->dx;
X		  pixel = pixel_row;
X
X		  origin[1] = (short)(y * Ystep);
X		  vb_pixels(cgidev, origin, 4096, 1, v_width, v_height,
X			   pixel_row);
X		  y -= dy;
X		}
X	    }
X	  table_ptr++;
X	  prefix = save;
X	}
X    }
X}
X
Xvoid	read_sequential(id)
X     image_dscrp *id;
X{
X  int	table_ptr, row_count, y, end_code, clear_code;
X  Uchar	*pixel = pixel_row;
X  short prefix, suffix, save, stack[4096], *stack_ptr;
X  short origin[2], v_width[2], v_height[2];
X
X  v_width[0] = id->x;
X  v_width[1] = (id->x + id->dx - 1 > Xmax) ? Xmax : id->x + id->dx - 1;
X  v_height[0] = v_height[1] = 0;
X  origin[0] = 0;
X
X  y = id->y + id->dy - 1;
X  row_count = id->dx;
X  clear_code = id->colors;
X  end_code = clear_code + 1;
X  while ((prefix = get_code()) == clear_code)
X    ;
X  reset_codes();
X  table_ptr = clear_code + 2;
X  while ((save = suffix = get_code()) != end_code) 
X    {
X      if (suffix == clear_code) 
X	{
X	  reset_codes();
X	  while ((save = get_code()) == clear_code)
X	    ;
X	  reset_codes();
X	  table_ptr = clear_code + 1;
X	}
X      else 
X	{
X	  code_table[table_ptr][0] = prefix;
X	  if (suffix == table_ptr)
X	    code_table[table_ptr][1] = code_table[prefix][1];
X	  else 
X	    {
X	      while (suffix >= id->colors) suffix = code_table[suffix][0];
X	      code_table[table_ptr][1] = suffix;
X	    }
X	}
X      suffix = 1;
X      stack_ptr = stack;
X      while (prefix >= id->colors) 
X	{
X	  *stack_ptr++ = code_table[prefix][1];
X	  prefix = code_table[prefix][0];
X	  suffix++;
X	}
X      *stack_ptr = prefix;
X      for ( ; suffix > 0; stack_ptr--, suffix--) 
X	{
X	  *pixel++ = (Uchar)(cmap + *stack_ptr);
X	  if (--row_count == 0) 
X	    {
X	      row_count = id->dx;
X	      pixel = pixel_row;
X	      origin[1] = (short)(y * Ystep);
X	      vb_pixels(cgidev, origin, 4096, 1, v_width, v_height, pixel_row);
X	      y--;
X	    }
X	}
X      table_ptr++;
X      prefix = save;
X    }
X}
X
Xint	draw_image(infile)
X     FILE *infile;
X{
X  Uchar		lcm[256][3];
X  int		flag;
X  image_dscrp	id;
X
X  flag = scan_ID(infile, &id);
X  if (flag == 0) 
X    {
X      printf("unexpected eof.\n");
X      exit(3);
X    }
X  if (flag == 1) 
X    return(0);
X  if (id.gcm) 
X    {
X      scan_CM(infile, id.colors, (Uchar *)lcm);
X      install_cmap(id.colors, (Uchar *)lcm);
X    }
X  else 
X    {
X      install_cmap(si.colors, (Uchar *)g_colors);
X      id.colors = si.colors;
X      id.bits = si.bits;
X    }
X
X  if (id.bits == 1) 
X    {	/* Need extra bit for 2 color pic. */
X      id.bits = 2;
X      id.colors = 4;
X    }
X  clear_stream(infile, id.bits);
X  setup_codes(id.colors);
X
X  if (id.order) 
X    read_interlaced(&id);
X  else 
X    read_sequential(&id);
X  return(!0);
X}
X
Xvoid	main(argc, argv)
X     int argc;
X     char **argv;
X{
X  FILE	*gif_data;
X  short	gin[19], gout[66];
X  int	i = 1;
X  char	*cgidriver, *getenv();
X  void	(*sig_handler)();
X
X  if (argc < 2 || argc > 3) 
X    {
X      printf("usage: %s [-v] GIF_file\n", argv[0]);
X      exit(1);
X    }
X  if (!strcmp(argv[i], "-v"))
X    i++;
X	
X  gif_data = fopen(argv[i], "r");
X  if (gif_data == NULL) 
X    {
X      printf("can't open %s.\n", argv[i]);
X      exit(1);
X    }
X  if (!mscanf(gif_data, "GIF87a")) 
X    {
X      printf("%s not a gif file.\n", argv[i]);
X      exit(2);
X    }
X
X  if (!scan_SD(gif_data, &si)) 
X    {
X      printf("data format error.\n");
X      exit(3);
X    }
X  if (i == 2)
X    {
X      printf("File %s:\nresolution: %dx%d\ncolors: %d\n",
X	     argv[i], si.dx, si.dy, si.colors);
X      sleep(2);
X    }
X  if (si.gcm) 
X    scan_CM(gif_data, si.colors, (Uchar *)g_colors);
X
X  if (!getenv(cgidriver = "CGIDISP"))
X    {
X      printf("%s: no cgi driver\n", argv[0]);
X      exit(4);
X    }
X  for (i = 0; cgidriver[i]; i++) 
X    gin[11+i] = cgidriver[i];
X  gin[18] = ' ';
X
X  for (i = 1; i < SIGQUIT; i++)
X    signal(i, sig_handler);
X
X  if (v_opnwk(gin, &cgidev, gout) < 0) 
X    {
X      printf("CGI error %d opening %s\n", -vq_error(), cgidriver);
X      exit(5);
X    }
X  if (gout[38] = 0)
X    {
X      printf("%s: %s device is not capable of pixel operations\n",
X	     argv[0], cgidriver);
X      sleep(2);
X      v_clswk(cgidev);
X      exit(6);
X    }
X  Ystep = (short)((long)(gout[52] + 1L) / (long)si.dy);
X  Xmax = gout[51];
X
X  while (draw_image(gif_data))
X    ;
X
X  if (gout[45] == 0)
X    {
X      short ptin[2];
X      char  strin[2];
X      
X      ptin[0] = 0;
X      ptin[1] = 0;
X      vrq_string(cgidev, 1, 0, ptin, strin);
X    }
X  v_clswk(cgidev);
X  exit(0);
X}
X
Xvoid	sig_handler(sig)
X     int sig;
X{
X  v_clswk(cgidev);
X  exit (-sig);
X}
SHAR_EOF
if test 11281 -ne "`wc -c < 'gif.c'`"
then
	echo shar: "error transmitting 'gif.c'" '(should have been 11281 characters)'
fi
fi
exit 0
#	End of shell archive
-- 

				Ronald Florence
				ron@mlfarm.com
Newsgroups: comp.unix.xenix.sco