--- /dev/null
+#=============================================================================#
+# Makefile for Rocks'n'Diamonds 1.2 #
+# (c) 1995-98 Holger Schemel, aeglos@valinor.owl.de #
+#=============================================================================#
+
+#-----------------------------------------------------------------------------#
+# configuration section #
+#-----------------------------------------------------------------------------#
+
+#-----------------------------------------------------------------------------#
+# you shouldn't need to change anything below #
+#-----------------------------------------------------------------------------#
+
+PROGNAME = rocksndiamonds
+SRC_DIR = src
+
+MAKE = make
+RM = rm -f
+
+MAKE_CMD = $(MAKE) -C $(SRC_DIR)
+
+
+all: $(PROGNAME)
+
+$(PROGNAME):
+ $(MAKE_CMD)
+
+clean:
+ $(MAKE_CMD) clean
+ $(RM) $(PROGNAME)
+
+backup:
+ $(MAKE) clean
+ ./scripts/make_backup.sh
+
+depend:
+ $(MAKE_CMD) depend
# configuration section #
#-----------------------------------------------------------------------------#
+# change this to your favorite ANSI C compiler
+CC = gcc
+
+# on Solaris and similar systems, you'll need to uncomment this
+# EXTRA_LIBS = -lnsl -lsocket
+
+# specify X11 library path on your system
+XLIB_PATH = /usr/X11/lib
+
+# change this to the directory where you want to install game data like levels
+GAME_DIR = .
+
+# uncomment this if your system has no joystick include file
+# JOYSTICK = -DNO_JOYSTICK
+
+# uncomment this if your system has no sound
+# SOUNDS = -DNO_SOUNDS
+
+# choose if you want to allow many global score file entries for one player
+# when installing the game in a multi user environment, choose this
+# SCORE_ENTRIES = ONE_PER_NAME
+# when installing the game in a single user environment, choose this
+SCORE_ENTRIES = MANY_PER_NAME
+
+# The XPM-Library is no longer needed to build this program,
+# but is used to load graphics if XPM_INCLUDE_FILE is defined,
+# because the GIF loading routines are still a bit beta.
+# If you want to use the Xpm library, convert the GIF files to Xpm
+# files (and you need corresponding mask files in xbm format).
+
+# XPM_INCLUDE_FILE = -DXPM_INCLUDE_FILE="<X11/xpm.h>"
+# EXTRA_X11_LIBS = -lXpm
+
#-----------------------------------------------------------------------------#
# you shouldn't need to change anything below #
#-----------------------------------------------------------------------------#
PROGNAME = rocksndiamonds
-SRC_DIR = src
-MAKE = make
RM = rm -f
+CPP = $(CC) -E
+
+CONFIG_GAME_DIR = -DGAME_DIR="\"$(GAME_DIR)\""
+CONFIG_SCORE_ENTRIES = -D$(SCORE_ENTRIES)
-MAKE_CMD = $(MAKE) -C $(SRC_DIR)
+CONFIG = $(CONFIG_GAME_DIR) $(SOUNDS) $(JOYSTICK) \
+ $(CONFIG_SCORE_ENTRIES) $(XPM_INCLUDE_FILE)
+# DEBUG = -DDEBUG -g -ansi -pedantic -Wall
+DEBUG = -DDEBUG -g -Wall
+# DEBUG = -O6
+
+# SYSTEM = -Aa -D_HPUX_SOURCE -Dhpux # for HP-UX (obsolete)
+# SYSTEM = -DSYSV -Ae # for HP-UX
+# INCL = -I/usr/include/X11R5 # for HP-UX and others
+# INCL = -I/usr/local/X11/include # for SunOS and others
+# LIBS = -L/usr/lib/X11R5 -lXpm -lX11 -lm
+# # for HP-UX and others
+# LIBS = -L/usr/local/X11/lib -lXpm -lX11 -lm -lsocket -R/usr/local/X11/lib
+# # for SunOS and others
+
+# LIBS = -L/usr/X11R6/lib -lXpm -lX11 -lm
+# LIBS = -L/usr/X11R6/lib -lX11 -lm
+
+# LIBS = -L/usr/X11R6/lib $(EXTRA_X11_LIBS) -lX11 -lm $(EXTRA_LIBS)
+LIBS = -L$(XLIB_PATH) $(EXTRA_X11_LIBS) -lX11 -lm $(EXTRA_LIBS)
+
+# CFLAGS = -O2 $(CONFIG) $(SYSTEM)
+CFLAGS = $(DEBUG) $(CONFIG) $(SYSTEM) $(INCL)
+
+SRCS = main.c \
+ init.c \
+ events.c \
+ tools.c \
+ screens.c \
+ misc.c \
+ game.c \
+ editor.c \
+ buttons.c \
+ files.c \
+ tape.c \
+ sound.c \
+ joystick.c \
+ cartoons.c \
+ random.c \
+ pcx.c \
+ image.c \
+ network.c \
+ netserv.c
+
+OBJS = main.o \
+ init.o \
+ events.o \
+ tools.o \
+ screens.o \
+ misc.o \
+ game.o \
+ editor.o \
+ buttons.o \
+ files.o \
+ tape.o \
+ sound.o \
+ joystick.o \
+ cartoons.o \
+ random.o \
+ pcx.o \
+ image.o \
+ network.o \
+ netserv.o
all: $(PROGNAME)
-$(PROGNAME):
- $(MAKE_CMD)
+$(PROGNAME): $(OBJS)
+ $(CC) $(CFLAGS) $(OBJS) $(LIBS) -o $(PROGNAME)
+
+.c.o:
+ $(CC) $(CFLAGS) -c $*.c
clean:
- $(MAKE_CMD) clean
+ $(RM) $(OBJS)
$(RM) $(PROGNAME)
-backup:
- ./scripts/make_backup.sh
-
depend:
- $(MAKE_CMD) depend
+ for i in $(SRCS); do $(CPP) $(CFLAGS) -M $$i; done > .depend
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* (c) 1995-98 Artsoft Entertainment *
+* Holger Schemel *
+* Oststrasse 11a *
+* 33604 Bielefeld *
+* phone: ++49 +521 290471 *
+* email: aeglos@valinor.owl.de *
+*----------------------------------------------------------*
+* files.h *
+***********************************************************/
+
+#include <ctype.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "files.h"
+#include "tools.h"
+#include "misc.h"
+#include "tape.h"
+#include "joystick.h"
+
+#define MAX_LINE_LEN 1000
+
+static void SaveUserLevelInfo(); /* for 'InitUserLevelDir()' */
+static char *getSetupLine(char *, int); /* for 'SaveUserLevelInfo()' */
+
+static char *getGlobalDataDir()
+{
+ return GAME_DIR;
+}
+
+static char *getUserDataDir()
+{
+ static char *userdata_dir = NULL;
+
+ if (!userdata_dir)
+ {
+ char *home_dir = getHomeDir();
+ char *data_dir = USERDATA_DIRECTORY;
+
+ userdata_dir = checked_malloc(strlen(home_dir) + strlen(data_dir) + 2);
+ sprintf(userdata_dir, "%s/%s", home_dir, data_dir);
+ }
+
+ return userdata_dir;
+}
+
+static char *getSetupDir()
+{
+ return getUserDataDir();
+}
+
+static char *getUserLevelDir(char *level_subdir)
+{
+ static char *userlevel_dir = NULL;
+ char *data_dir = getUserDataDir();
+ char *userlevel_subdir = LEVELS_DIRECTORY;
+
+ if (userlevel_dir)
+ free(userlevel_dir);
+
+ userlevel_dir = checked_malloc(strlen(data_dir) + strlen(userlevel_subdir) +
+ strlen(level_subdir) + 3);
+ sprintf(userlevel_dir, "%s/%s%s%s", data_dir, userlevel_subdir,
+ (strlen(level_subdir) > 0 ? "/" : ""), level_subdir);
+
+ return userlevel_dir;
+}
+
+static char *getTapeDir(char *level_subdir)
+{
+ static char *tape_dir = NULL;
+ char *data_dir = getUserDataDir();
+ char *tape_subdir = TAPES_DIRECTORY;
+
+ if (tape_dir)
+ free(tape_dir);
+
+ tape_dir = checked_malloc(strlen(data_dir) + strlen(tape_subdir) +
+ strlen(level_subdir) + 3);
+ sprintf(tape_dir, "%s/%s%s%s", data_dir, tape_subdir,
+ (strlen(level_subdir) > 0 ? "/" : ""), level_subdir);
+
+ return tape_dir;
+}
+
+static char *getScoreDir(char *level_subdir)
+{
+ static char *score_dir = NULL;
+ char *data_dir = getGlobalDataDir();
+ char *score_subdir = SCORES_DIRECTORY;
+
+ if (score_dir)
+ free(score_dir);
+
+ score_dir = checked_malloc(strlen(data_dir) + strlen(score_subdir) +
+ strlen(level_subdir) + 3);
+ sprintf(score_dir, "%s/%s%s%s", data_dir, score_subdir,
+ (strlen(level_subdir) > 0 ? "/" : ""), level_subdir);
+
+ return score_dir;
+}
+
+static void createDirectory(char *dir, char *text)
+{
+ if (access(dir, F_OK) != 0)
+ if (mkdir(dir, USERDATA_DIR_MODE) != 0)
+ Error(ERR_WARN, "cannot create %s directory '%s'", text, dir);
+}
+
+static void InitUserDataDirectory()
+{
+ createDirectory(getUserDataDir(), "user data");
+}
+
+static void InitTapeDirectory(char *level_subdir)
+{
+ createDirectory(getTapeDir(""), "main tape");
+ createDirectory(getTapeDir(level_subdir), "level tape");
+}
+
+static void InitScoreDirectory(char *level_subdir)
+{
+ createDirectory(getScoreDir(""), "main score");
+ createDirectory(getScoreDir(level_subdir), "level score");
+}
+
+static void InitUserLevelDirectory(char *level_subdir)
+{
+ if (access(getUserLevelDir(level_subdir), F_OK) != 0)
+ {
+ createDirectory(getUserLevelDir(""), "main user level");
+ createDirectory(getUserLevelDir(level_subdir), "user level");
+
+ SaveUserLevelInfo();
+ }
+}
+
+void LoadLevel(int level_nr)
+{
+ int i, x, y;
+ char filename[MAX_FILENAME_LEN];
+ char cookie[MAX_FILENAME_LEN];
+ FILE *file;
+
+ if (leveldir[leveldir_nr].user_defined)
+ sprintf(filename, "%s/%s/%d",
+ getUserLevelDir(""), leveldir[leveldir_nr].filename, level_nr);
+ else
+ sprintf(filename, "%s/%s/%d",
+ options.level_directory, leveldir[leveldir_nr].filename, level_nr);
+
+ if (!(file = fopen(filename, "r")))
+ Error(ERR_WARN, "cannot read level '%s' - creating new level", filename);
+ else
+ {
+ fgets(cookie, LEVEL_COOKIE_LEN, file);
+ fgetc(file);
+
+ if (strcmp(cookie,LEVEL_COOKIE))
+ {
+ Error(ERR_WARN, "wrong format of level file '%s'", filename);
+ fclose(file);
+ file = NULL;
+ }
+ }
+
+ if (file)
+ {
+ lev_fieldx = level.fieldx = fgetc(file);
+ lev_fieldy = level.fieldy = fgetc(file);
+
+ level.time = (fgetc(file)<<8) | fgetc(file);
+ level.edelsteine = (fgetc(file)<<8) | fgetc(file);
+ for(i=0; i<MAX_LEVNAMLEN; i++)
+ level.name[i] = fgetc(file);
+ level.name[MAX_LEVNAMLEN-1] = 0;
+ for(i=0; i<MAX_LEVSCORE_ENTRIES; i++)
+ level.score[i] = fgetc(file);
+ for(i=0; i<4; i++)
+ for(y=0; y<3; y++)
+ for(x=0; x<3; x++)
+ level.mampfer_inhalt[i][x][y] = fgetc(file);
+ level.tempo_amoebe = fgetc(file);
+ level.dauer_sieb = fgetc(file);
+ level.dauer_ablenk = fgetc(file);
+ level.amoebe_inhalt = fgetc(file);
+
+ for(i=0; i<NUM_FREE_LVHD_BYTES; i++) /* Rest frei / Headergröße 80 Bytes */
+ fgetc(file);
+
+ for(y=0; y<MAX_LEV_FIELDY; y++)
+ for(x=0; x<MAX_LEV_FIELDX; x++)
+ Feld[x][y] = Ur[x][y] = EL_ERDREICH;
+
+ for(y=0; y<lev_fieldy; y++)
+ for(x=0; x<lev_fieldx; x++)
+ Feld[x][y] = Ur[x][y] = fgetc(file);
+
+ fclose(file);
+
+ if (level.time <= 10) /* Mindestspieldauer */
+ level.time = 10;
+ }
+ else
+ {
+ lev_fieldx = level.fieldx = STD_LEV_FIELDX;
+ lev_fieldy = level.fieldy = STD_LEV_FIELDY;
+
+ level.time = 100;
+ level.edelsteine = 0;
+ strcpy(level.name, "Nameless Level");
+ for(i=0; i<MAX_LEVSCORE_ENTRIES; i++)
+ level.score[i] = 10;
+ for(i=0; i<4; i++)
+ for(y=0; y<3; y++)
+ for(x=0; x<3; x++)
+ level.mampfer_inhalt[i][x][y] = EL_FELSBROCKEN;
+ level.tempo_amoebe = 10;
+ level.dauer_sieb = 10;
+ level.dauer_ablenk = 10;
+ level.amoebe_inhalt = EL_DIAMANT;
+
+ for(y=0; y<STD_LEV_FIELDY; y++)
+ for(x=0; x<STD_LEV_FIELDX; x++)
+ Feld[x][y] = Ur[x][y] = EL_ERDREICH;
+ Feld[0][0] = Ur[0][0] = EL_SPIELFIGUR;
+ Feld[STD_LEV_FIELDX-1][STD_LEV_FIELDY-1] =
+ Ur[STD_LEV_FIELDX-1][STD_LEV_FIELDY-1] = EL_AUSGANG_ZU;
+ }
+}
+
+void SaveLevel(int level_nr)
+{
+ int i, x, y;
+ char filename[MAX_FILENAME_LEN];
+ FILE *file;
+
+ if (leveldir[leveldir_nr].user_defined)
+ sprintf(filename, "%s/%s/%d",
+ getUserLevelDir(""), leveldir[leveldir_nr].filename, level_nr);
+ else
+ sprintf(filename, "%s/%s/%d",
+ options.level_directory, leveldir[leveldir_nr].filename, level_nr);
+
+ if (!(file = fopen(filename, "w")))
+ {
+ Error(ERR_WARN, "cannot save level file '%s'", filename);
+ return;
+ }
+
+ fputs(LEVEL_COOKIE,file); /* Formatkennung */
+ fputc(0x0a, file);
+
+ fputc(level.fieldx, file);
+ fputc(level.fieldy, file);
+ fputc(level.time / 256, file);
+ fputc(level.time % 256, file);
+ fputc(level.edelsteine / 256, file);
+ fputc(level.edelsteine % 256, file);
+
+ for(i=0; i<MAX_LEVNAMLEN; i++)
+ fputc(level.name[i], file);
+ for(i=0; i<MAX_LEVSCORE_ENTRIES; i++)
+ fputc(level.score[i], file);
+ for(i=0; i<4; i++)
+ for(y=0; y<3; y++)
+ for(x=0; x<3; x++)
+ fputc(level.mampfer_inhalt[i][x][y], file);
+ fputc(level.tempo_amoebe, file);
+ fputc(level.dauer_sieb, file);
+ fputc(level.dauer_ablenk, file);
+ fputc(level.amoebe_inhalt, file);
+
+ for(i=0; i<NUM_FREE_LVHD_BYTES; i++) /* Rest frei / Headergröße 80 Bytes */
+ fputc(0, file);
+
+ for(y=0; y<lev_fieldy; y++)
+ for(x=0; x<lev_fieldx; x++)
+ fputc(Ur[x][y], file);
+
+ fclose(file);
+
+ chmod(filename, LEVEL_PERMS);
+}
+
+void LoadTape(int level_nr)
+{
+ int i;
+ char filename[MAX_FILENAME_LEN];
+ char cookie[MAX_FILENAME_LEN];
+ FILE *file;
+ boolean levelrec_10 = FALSE;
+
+ sprintf(filename, "%s/%d.%s",
+ getTapeDir(leveldir[leveldir_nr].filename),
+ level_nr, TAPEFILE_EXTENSION);
+
+ if ((file = fopen(filename, "r")))
+ {
+ fgets(cookie, LEVELREC_COOKIE_LEN, file);
+ fgetc(file);
+ if (!strcmp(cookie, LEVELREC_COOKIE_10)) /* old 1.0 tape format */
+ levelrec_10 = TRUE;
+ else if (strcmp(cookie, LEVELREC_COOKIE)) /* unknown tape format */
+ {
+ Error(ERR_WARN, "wrong format of level recording file '%s'", filename);
+ fclose(file);
+ file = NULL;
+ }
+ }
+
+ if (!file)
+ return;
+
+ tape.random_seed =
+ (fgetc(file)<<24) | (fgetc(file)<<16) | (fgetc(file)<<8) | fgetc(file);
+ tape.date =
+ (fgetc(file)<<24) | (fgetc(file)<<16) | (fgetc(file)<<8) | fgetc(file);
+ tape.length =
+ (fgetc(file)<<24) | (fgetc(file)<<16) | (fgetc(file)<<8) | fgetc(file);
+
+ tape.level_nr = level_nr;
+ tape.counter = 0;
+ tape.changed = FALSE;
+
+ tape.recording = FALSE;
+ tape.playing = FALSE;
+ tape.pausing = FALSE;
+
+ for(i=0; i<tape.length; i++)
+ {
+ int j;
+
+ if (i >= MAX_TAPELEN)
+ break;
+
+ for(j=0; j<MAX_PLAYERS; j++)
+ {
+ if (levelrec_10 && j > 0)
+ {
+ tape.pos[i].action[j] = MV_NO_MOVING;
+ continue;
+ }
+ tape.pos[i].action[j] = fgetc(file);
+ }
+
+ tape.pos[i].delay = fgetc(file);
+
+ if (levelrec_10)
+ {
+ /* eliminate possible diagonal moves in old tapes */
+ /* this is only for backward compatibility */
+
+ byte joy_dir[4] = { JOY_LEFT, JOY_RIGHT, JOY_UP, JOY_DOWN };
+ byte action = tape.pos[i].action[0];
+ int k, num_moves = 0;
+
+ for (k=0; k<4; k++)
+ {
+ if (action & joy_dir[k])
+ {
+ tape.pos[i + num_moves].action[0] = joy_dir[k];
+ if (num_moves > 0)
+ tape.pos[i + num_moves].delay = 0;
+ num_moves++;
+ }
+ }
+
+ if (num_moves > 1)
+ {
+ num_moves--;
+ i += num_moves;
+ tape.length += num_moves;
+ }
+ }
+
+ if (feof(file))
+ break;
+ }
+
+ fclose(file);
+
+ if (i != tape.length)
+ Error(ERR_WARN, "level recording file '%s' corrupted", filename);
+
+ tape.length_seconds = GetTapeLength();
+}
+
+void SaveTape(int level_nr)
+{
+ int i;
+ char filename[MAX_FILENAME_LEN];
+ FILE *file;
+ boolean new_tape = TRUE;
+
+ InitTapeDirectory(leveldir[leveldir_nr].filename);
+
+ sprintf(filename, "%s/%d.%s",
+ getTapeDir(leveldir[leveldir_nr].filename),
+ level_nr, TAPEFILE_EXTENSION);
+
+ /* if a tape still exists, ask to overwrite it */
+ if ((file = fopen(filename, "r")))
+ {
+ new_tape = FALSE;
+ fclose(file);
+
+ if (!Request("Replace old tape ?", REQ_ASK))
+ return;
+ }
+
+ if (!(file = fopen(filename, "w")))
+ {
+ Error(ERR_WARN, "cannot save level recording file '%s'", filename);
+ return;
+ }
+
+ fputs(LEVELREC_COOKIE, file); /* Formatkennung */
+ fputc(0x0a, file);
+
+ fputc((tape.random_seed >> 24) & 0xff,file);
+ fputc((tape.random_seed >> 16) & 0xff,file);
+ fputc((tape.random_seed >> 8) & 0xff,file);
+ fputc((tape.random_seed >> 0) & 0xff,file);
+
+ fputc((tape.date >> 24) & 0xff,file);
+ fputc((tape.date >> 16) & 0xff,file);
+ fputc((tape.date >> 8) & 0xff,file);
+ fputc((tape.date >> 0) & 0xff,file);
+
+ fputc((tape.length >> 24) & 0xff,file);
+ fputc((tape.length >> 16) & 0xff,file);
+ fputc((tape.length >> 8) & 0xff,file);
+ fputc((tape.length >> 0) & 0xff,file);
+
+ for(i=0; i<tape.length; i++)
+ {
+ int j;
+
+ for(j=0; j<MAX_PLAYERS; j++)
+ fputc(tape.pos[i].action[j], file);
+
+ fputc(tape.pos[i].delay, file);
+ }
+
+ fclose(file);
+
+ chmod(filename, LEVREC_PERMS);
+
+ tape.changed = FALSE;
+
+ if (new_tape)
+ Request("tape saved !",REQ_CONFIRM);
+}
+
+void LoadScore(int level_nr)
+{
+ int i;
+ char filename[MAX_FILENAME_LEN];
+ char cookie[MAX_FILENAME_LEN];
+ char line[MAX_LINE_LEN];
+ char *line_ptr;
+ FILE *file;
+
+ /* start with empty score table */
+ for(i=0; i<MAX_SCORE_ENTRIES; i++)
+ {
+ strcpy(highscore[i].Name, EMPTY_ALIAS);
+ highscore[i].Score = 0;
+ }
+
+ sprintf(filename, "%s/%d.%s",
+ getScoreDir(leveldir[leveldir_nr].filename),
+ level_nr, SCOREFILE_EXTENSION);
+
+ if (!(file = fopen(filename, "r")))
+ return;
+
+ fgets(cookie, SCORE_COOKIE_LEN, file);
+
+ if (strcmp(cookie, SCORE_COOKIE) != 0)
+ {
+ Error(ERR_WARN, "wrong format of score file '%s'", filename);
+ fclose(file);
+ return;
+ }
+
+ for(i=0; i<MAX_SCORE_ENTRIES; i++)
+ {
+ fscanf(file, "%d", &highscore[i].Score);
+ fgets(line, MAX_LINE_LEN, file);
+
+ if (line[strlen(line)-1] == '\n')
+ line[strlen(line)-1] = '\0';
+
+ for (line_ptr = line; *line_ptr; line_ptr++)
+ {
+ if (*line_ptr != ' ' && *line_ptr != '\t' && *line_ptr != '\0')
+ {
+ strncpy(highscore[i].Name, line_ptr, MAX_NAMELEN - 1);
+ highscore[i].Name[MAX_NAMELEN - 1] = '\0';
+ break;
+ }
+ }
+ }
+
+ fclose(file);
+}
+
+void SaveScore(int level_nr)
+{
+ int i;
+ char filename[MAX_FILENAME_LEN];
+ FILE *file;
+
+ InitScoreDirectory(leveldir[leveldir_nr].filename);
+
+ sprintf(filename, "%s/%d.%s",
+ getScoreDir(leveldir[leveldir_nr].filename),
+ level_nr, SCOREFILE_EXTENSION);
+
+ if (!(file = fopen(filename, "w")))
+ {
+ Error(ERR_WARN, "cannot save score for level %d", level_nr);
+ return;
+ }
+
+ fprintf(file, "%s\n\n", SCORE_COOKIE);
+
+ for(i=0; i<MAX_SCORE_ENTRIES; i++)
+ fprintf(file, "%d %s\n", highscore[i].Score, highscore[i].Name);
+
+ fclose(file);
+
+ chmod(filename, SCORE_PERMS);
+}
+
+#define TOKEN_STR_FILE_IDENTIFIER "file_identifier"
+#define TOKEN_STR_LAST_LEVEL_SERIES "last_level_series"
+#define TOKEN_STR_PLAYER_PREFIX "player_"
+
+#define TOKEN_VALUE_POSITION 30
+
+/* global setup */
+#define SETUP_TOKEN_PLAYER_NAME 0
+#define SETUP_TOKEN_SOUND 1
+#define SETUP_TOKEN_SOUND_LOOPS 2
+#define SETUP_TOKEN_SOUND_MUSIC 3
+#define SETUP_TOKEN_SOUND_SIMPLE 4
+#define SETUP_TOKEN_TOONS 5
+#define SETUP_TOKEN_DOUBLE_BUFFERING 6
+#define SETUP_TOKEN_SCROLL_DELAY 7
+#define SETUP_TOKEN_SOFT_SCROLLING 8
+#define SETUP_TOKEN_FADING 9
+#define SETUP_TOKEN_AUTORECORD 10
+#define SETUP_TOKEN_QUICK_DOORS 11
+#define SETUP_TOKEN_TEAM_MODE 12
+
+/* player setup */
+#define SETUP_TOKEN_USE_JOYSTICK 13
+#define SETUP_TOKEN_JOY_DEVICE_NAME 14
+#define SETUP_TOKEN_JOY_XLEFT 15
+#define SETUP_TOKEN_JOY_XMIDDLE 16
+#define SETUP_TOKEN_JOY_XRIGHT 17
+#define SETUP_TOKEN_JOY_YUPPER 18
+#define SETUP_TOKEN_JOY_YMIDDLE 19
+#define SETUP_TOKEN_JOY_YLOWER 20
+#define SETUP_TOKEN_JOY_SNAP 21
+#define SETUP_TOKEN_JOY_BOMB 22
+#define SETUP_TOKEN_KEY_LEFT 23
+#define SETUP_TOKEN_KEY_RIGHT 24
+#define SETUP_TOKEN_KEY_UP 25
+#define SETUP_TOKEN_KEY_DOWN 26
+#define SETUP_TOKEN_KEY_SNAP 27
+#define SETUP_TOKEN_KEY_BOMB 28
+
+/* level directory info */
+#define LEVELINFO_TOKEN_NAME 29
+#define LEVELINFO_TOKEN_LEVELS 30
+#define LEVELINFO_TOKEN_SORT_PRIORITY 31
+#define LEVELINFO_TOKEN_READONLY 32
+
+#define FIRST_GLOBAL_SETUP_TOKEN SETUP_TOKEN_PLAYER_NAME
+#define LAST_GLOBAL_SETUP_TOKEN SETUP_TOKEN_TEAM_MODE
+
+#define FIRST_PLAYER_SETUP_TOKEN SETUP_TOKEN_USE_JOYSTICK
+#define LAST_PLAYER_SETUP_TOKEN SETUP_TOKEN_KEY_BOMB
+
+#define FIRST_LEVELINFO_TOKEN LEVELINFO_TOKEN_NAME
+#define LAST_LEVELINFO_TOKEN LEVELINFO_TOKEN_READONLY
+
+#define TYPE_BOOLEAN 1
+#define TYPE_SWITCH 2
+#define TYPE_KEYSYM 3
+#define TYPE_INTEGER 4
+#define TYPE_STRING 5
+
+static struct SetupInfo si;
+static struct SetupInputInfo sii;
+static struct LevelDirInfo ldi;
+static struct
+{
+ int type;
+ void *value;
+ char *text;
+} token_info[] =
+{
+ /* global setup */
+ { TYPE_STRING, &si.player_name, "player_name" },
+ { TYPE_SWITCH, &si.sound, "sound" },
+ { TYPE_SWITCH, &si.sound_loops, "repeating_sound_loops" },
+ { TYPE_SWITCH, &si.sound_music, "background_music" },
+ { TYPE_SWITCH, &si.sound_simple, "simple_sound_effects" },
+ { TYPE_SWITCH, &si.toons, "toons" },
+ { TYPE_SWITCH, &si.double_buffering, "double_buffering" },
+ { TYPE_SWITCH, &si.scroll_delay, "scroll_delay" },
+ { TYPE_SWITCH, &si.soft_scrolling, "soft_scrolling" },
+ { TYPE_SWITCH, &si.fading, "screen_fading" },
+ { TYPE_SWITCH, &si.autorecord, "automatic_tape_recording" },
+ { TYPE_SWITCH, &si.quick_doors, "quick_doors" },
+ { TYPE_SWITCH, &si.team_mode, "team_mode" },
+
+ /* player setup */
+ { TYPE_BOOLEAN, &sii.use_joystick, ".use_joystick" },
+ { TYPE_STRING, &sii.joy.device_name, ".joy.device_name" },
+ { TYPE_INTEGER, &sii.joy.xleft, ".joy.xleft" },
+ { TYPE_INTEGER, &sii.joy.xmiddle, ".joy.xmiddle" },
+ { TYPE_INTEGER, &sii.joy.xright, ".joy.xright" },
+ { TYPE_INTEGER, &sii.joy.yupper, ".joy.yupper" },
+ { TYPE_INTEGER, &sii.joy.ymiddle, ".joy.ymiddle" },
+ { TYPE_INTEGER, &sii.joy.ylower, ".joy.ylower" },
+ { TYPE_INTEGER, &sii.joy.snap, ".joy.snap_field" },
+ { TYPE_INTEGER, &sii.joy.bomb, ".joy.place_bomb" },
+ { TYPE_KEYSYM, &sii.key.left, ".key.move_left" },
+ { TYPE_KEYSYM, &sii.key.right, ".key.move_right" },
+ { TYPE_KEYSYM, &sii.key.up, ".key.move_up" },
+ { TYPE_KEYSYM, &sii.key.down, ".key.move_down" },
+ { TYPE_KEYSYM, &sii.key.snap, ".key.snap_field" },
+ { TYPE_KEYSYM, &sii.key.bomb, ".key.place_bomb" },
+
+ /* level directory info */
+ { TYPE_STRING, &ldi.name, "name" },
+ { TYPE_INTEGER, &ldi.levels, "levels" },
+ { TYPE_INTEGER, &ldi.sort_priority, "sort_priority" },
+ { TYPE_BOOLEAN, &ldi.readonly, "readonly" }
+};
+
+static char *string_tolower(char *s)
+{
+ static char s_lower[100];
+ int i;
+
+ if (strlen(s) >= 100)
+ return s;
+
+ strcpy(s_lower, s);
+
+ for (i=0; i<strlen(s_lower); i++)
+ s_lower[i] = tolower(s_lower[i]);
+
+ return s_lower;
+}
+
+static int get_string_integer_value(char *s)
+{
+ static char *number_text[][3] =
+ {
+ { "0", "zero", "null", },
+ { "1", "one", "first" },
+ { "2", "two", "second" },
+ { "3", "three", "third" },
+ { "4", "four", "fourth" },
+ { "5", "five", "fifth" },
+ { "6", "six", "sixth" },
+ { "7", "seven", "seventh" },
+ { "8", "eight", "eighth" },
+ { "9", "nine", "ninth" },
+ { "10", "ten", "tenth" },
+ { "11", "eleven", "eleventh" },
+ { "12", "twelve", "twelfth" },
+ };
+
+ int i, j;
+
+ for (i=0; i<13; i++)
+ for (j=0; j<3; j++)
+ if (strcmp(string_tolower(s), number_text[i][j]) == 0)
+ return i;
+
+ return atoi(s);
+}
+
+static boolean get_string_boolean_value(char *s)
+{
+ if (strcmp(string_tolower(s), "true") == 0 ||
+ strcmp(string_tolower(s), "yes") == 0 ||
+ strcmp(string_tolower(s), "on") == 0 ||
+ get_string_integer_value(s) == 1)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static char *getFormattedSetupEntry(char *token, char *value)
+{
+ int i;
+ static char entry[MAX_LINE_LEN];
+
+ sprintf(entry, "%s:", token);
+ for (i=strlen(entry); i<TOKEN_VALUE_POSITION; i++)
+ entry[i] = ' ';
+ entry[i] = '\0';
+
+ strcat(entry, value);
+
+ return entry;
+}
+
+static void freeSetupFileList(struct SetupFileList *setup_file_list)
+{
+ if (!setup_file_list)
+ return;
+
+ if (setup_file_list->token)
+ free(setup_file_list->token);
+ if (setup_file_list->value)
+ free(setup_file_list->value);
+ if (setup_file_list->next)
+ freeSetupFileList(setup_file_list->next);
+ free(setup_file_list);
+}
+
+static struct SetupFileList *newSetupFileList(char *token, char *value)
+{
+ struct SetupFileList *new = checked_malloc(sizeof(struct SetupFileList));
+
+ new->token = checked_malloc(strlen(token) + 1);
+ strcpy(new->token, token);
+
+ new->value = checked_malloc(strlen(value) + 1);
+ strcpy(new->value, value);
+
+ new->next = NULL;
+
+ return new;
+}
+
+static char *getTokenValue(struct SetupFileList *setup_file_list,
+ char *token)
+{
+ if (!setup_file_list)
+ return NULL;
+
+ if (strcmp(setup_file_list->token, token) == 0)
+ return setup_file_list->value;
+ else
+ return getTokenValue(setup_file_list->next, token);
+}
+
+static void setTokenValue(struct SetupFileList *setup_file_list,
+ char *token, char *value)
+{
+ if (!setup_file_list)
+ return;
+
+ if (strcmp(setup_file_list->token, token) == 0)
+ {
+ free(setup_file_list->value);
+ setup_file_list->value = checked_malloc(strlen(value) + 1);
+ strcpy(setup_file_list->value, value);
+ }
+ else if (setup_file_list->next == NULL)
+ setup_file_list->next = newSetupFileList(token, value);
+ else
+ setTokenValue(setup_file_list->next, token, value);
+}
+
+#ifdef DEBUG
+static void printSetupFileList(struct SetupFileList *setup_file_list)
+{
+ if (!setup_file_list)
+ return;
+
+ printf("token: '%s'\n", setup_file_list->token);
+ printf("value: '%s'\n", setup_file_list->value);
+
+ printSetupFileList(setup_file_list->next);
+}
+#endif
+
+static struct SetupFileList *loadSetupFileList(char *filename)
+{
+ int line_len;
+ char line[MAX_LINE_LEN];
+ char *token, *value, *line_ptr;
+ struct SetupFileList *setup_file_list = newSetupFileList("", "");
+ struct SetupFileList *first_valid_list_entry;
+
+ FILE *file;
+
+ if (!(file = fopen(filename, "r")))
+ {
+ Error(ERR_WARN, "cannot open setup/info file '%s'", filename);
+ return NULL;
+ }
+
+ while(!feof(file))
+ {
+ /* read next line of input file */
+ if (!fgets(line, MAX_LINE_LEN, file))
+ break;
+
+ /* cut trailing comment or whitespace from input line */
+ for (line_ptr = line; *line_ptr; line_ptr++)
+ {
+ if (*line_ptr == '#' || *line_ptr == '\n')
+ {
+ *line_ptr = '\0';
+ break;
+ }
+ }
+
+ /* cut trailing whitespaces from input line */
+ for (line_ptr = &line[strlen(line)]; line_ptr > line; line_ptr--)
+ if ((*line_ptr == ' ' || *line_ptr == '\t') && line_ptr[1] == '\0')
+ *line_ptr = '\0';
+
+ /* ignore empty lines */
+ if (*line == '\0')
+ continue;
+
+ line_len = strlen(line);
+
+ /* cut leading whitespaces from token */
+ for (token = line; *token; token++)
+ if (*token != ' ' && *token != '\t')
+ break;
+
+ /* find end of token */
+ for (line_ptr = token; *line_ptr; line_ptr++)
+ {
+ if (*line_ptr == ' ' || *line_ptr == '\t' || *line_ptr == ':')
+ {
+ *line_ptr = '\0';
+ break;
+ }
+ }
+
+ if (line_ptr < line + line_len)
+ value = line_ptr + 1;
+ else
+ value = "\0";
+
+ /* cut leading whitespaces from value */
+ for (; *value; value++)
+ if (*value != ' ' && *value != '\t')
+ break;
+
+ if (*token && *value)
+ setTokenValue(setup_file_list, token, value);
+ }
+
+ fclose(file);
+
+ first_valid_list_entry = setup_file_list->next;
+
+ /* free empty list header */
+ setup_file_list->next = NULL;
+ freeSetupFileList(setup_file_list);
+
+ if (first_valid_list_entry == NULL)
+ Error(ERR_WARN, "setup/info file '%s' is empty", filename);
+
+ return first_valid_list_entry;
+}
+
+static void checkSetupFileListIdentifier(struct SetupFileList *setup_file_list,
+ char *identifier)
+{
+ if (!setup_file_list)
+ return;
+
+ if (strcmp(setup_file_list->token, TOKEN_STR_FILE_IDENTIFIER) == 0)
+ {
+ if (strcmp(setup_file_list->value, identifier) != 0)
+ {
+ Error(ERR_WARN, "setup/info file has wrong version");
+ return;
+ }
+ else
+ return;
+ }
+
+ if (setup_file_list->next)
+ checkSetupFileListIdentifier(setup_file_list->next, identifier);
+ else
+ {
+ Error(ERR_WARN, "setup/info file has no version information");
+ return;
+ }
+}
+
+static void setLevelDirInfoToDefaults(struct LevelDirInfo *ldi)
+{
+ ldi->name = getStringCopy("non-existing");
+ ldi->levels = 0;
+ ldi->sort_priority = 999; /* default: least priority */
+ ldi->readonly = TRUE;
+}
+
+static void setSetupInfoToDefaults(struct SetupInfo *si)
+{
+ int i;
+
+ si->player_name = getStringCopy(getLoginName());
+
+ si->sound = TRUE;
+ si->sound_loops = FALSE;
+ si->sound_music = FALSE;
+ si->sound_simple = FALSE;
+ si->toons = TRUE;
+ si->double_buffering = TRUE;
+ si->direct_draw = !si->double_buffering;
+ si->scroll_delay = FALSE;
+ si->soft_scrolling = TRUE;
+ si->fading = FALSE;
+ si->autorecord = FALSE;
+ si->quick_doors = FALSE;
+
+ for (i=0; i<MAX_PLAYERS; i++)
+ {
+ si->input[i].use_joystick = FALSE;
+ si->input[i].joy.device_name = getStringCopy(joystick_device_name[i]);
+ si->input[i].joy.xleft = JOYSTICK_XLEFT;
+ si->input[i].joy.xmiddle = JOYSTICK_XMIDDLE;
+ si->input[i].joy.xright = JOYSTICK_XRIGHT;
+ si->input[i].joy.yupper = JOYSTICK_YUPPER;
+ si->input[i].joy.ymiddle = JOYSTICK_YMIDDLE;
+ si->input[i].joy.ylower = JOYSTICK_YLOWER;
+ si->input[i].joy.snap = (i == 0 ? JOY_BUTTON_1 : 0);
+ si->input[i].joy.bomb = (i == 0 ? JOY_BUTTON_2 : 0);
+ si->input[i].key.left = (i == 0 ? DEFAULT_KEY_LEFT : KEY_UNDEFINDED);
+ si->input[i].key.right = (i == 0 ? DEFAULT_KEY_RIGHT : KEY_UNDEFINDED);
+ si->input[i].key.up = (i == 0 ? DEFAULT_KEY_UP : KEY_UNDEFINDED);
+ si->input[i].key.down = (i == 0 ? DEFAULT_KEY_DOWN : KEY_UNDEFINDED);
+ si->input[i].key.snap = (i == 0 ? DEFAULT_KEY_SNAP : KEY_UNDEFINDED);
+ si->input[i].key.bomb = (i == 0 ? DEFAULT_KEY_BOMB : KEY_UNDEFINDED);
+ }
+}
+
+static void setSetupInfo(int token_nr, char *token_value)
+{
+ int token_type = token_info[token_nr].type;
+ void *setup_value = token_info[token_nr].value;
+
+ if (token_value == NULL)
+ return;
+
+ /* set setup field to corresponding token value */
+ switch (token_type)
+ {
+ case TYPE_BOOLEAN:
+ case TYPE_SWITCH:
+ *(boolean *)setup_value = get_string_boolean_value(token_value);
+ break;
+
+ case TYPE_KEYSYM:
+ *(KeySym *)setup_value = getKeySymFromX11KeyName(token_value);
+ break;
+
+ case TYPE_INTEGER:
+ *(int *)setup_value = get_string_integer_value(token_value);
+ break;
+
+ case TYPE_STRING:
+ if (*(char **)setup_value != NULL)
+ free(*(char **)setup_value);
+ *(char **)setup_value = getStringCopy(token_value);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void decodeSetupFileList(struct SetupFileList *setup_file_list)
+{
+ int i, pnr;
+
+ if (!setup_file_list)
+ return;
+
+ /* handle global setup values */
+ si = setup;
+ for (i=FIRST_GLOBAL_SETUP_TOKEN; i<=LAST_GLOBAL_SETUP_TOKEN; i++)
+ setSetupInfo(i, getTokenValue(setup_file_list, token_info[i].text));
+ setup = si;
+
+ /* handle player specific setup values */
+ for (pnr=0; pnr<MAX_PLAYERS; pnr++)
+ {
+ char prefix[30];
+
+ sprintf(prefix, "%s%d", TOKEN_STR_PLAYER_PREFIX, pnr + 1);
+
+ sii = setup.input[pnr];
+ for (i=FIRST_PLAYER_SETUP_TOKEN; i<=LAST_PLAYER_SETUP_TOKEN; i++)
+ {
+ char full_token[100];
+
+ sprintf(full_token, "%s%s", prefix, token_info[i].text);
+ setSetupInfo(i, getTokenValue(setup_file_list, full_token));
+ }
+ setup.input[pnr] = sii;
+ }
+}
+
+int getLevelSeriesNrFromLevelSeriesName(char *level_series_name)
+{
+ int i;
+
+ if (!level_series_name)
+ return 0;
+
+ for (i=0; i<num_leveldirs; i++)
+ if (strcmp(level_series_name, leveldir[i].filename) == 0)
+ return i;
+
+ return 0;
+}
+
+int getLastPlayedLevelOfLevelSeries(char *level_series_name)
+{
+ char *token_value;
+ int level_series_nr = getLevelSeriesNrFromLevelSeriesName(level_series_name);
+ int last_level_nr = 0;
+
+ if (!level_series_name)
+ return 0;
+
+ token_value = getTokenValue(level_setup_list, level_series_name);
+
+ if (token_value)
+ {
+ int highest_level_nr = leveldir[level_series_nr].levels - 1;
+
+ last_level_nr = atoi(token_value);
+
+ if (last_level_nr < 0)
+ last_level_nr = 0;
+ if (last_level_nr > highest_level_nr)
+ last_level_nr = highest_level_nr;
+ }
+
+ return last_level_nr;
+}
+
+static int compareLevelDirInfoEntries(const void *object1, const void *object2)
+{
+ const struct LevelDirInfo *entry1 = object1;
+ const struct LevelDirInfo *entry2 = object2;
+ int compare_result;
+
+ if (entry1->sort_priority != entry2->sort_priority)
+ compare_result = entry1->sort_priority - entry2->sort_priority;
+ else
+ {
+ char *name1 = getStringToLower(entry1->name);
+ char *name2 = getStringToLower(entry2->name);
+
+ compare_result = strcmp(name1, name2);
+
+ free(name1);
+ free(name2);
+ }
+
+ return compare_result;
+}
+
+static int LoadLevelInfoFromLevelDir(char *level_directory, int start_entry)
+{
+ DIR *dir;
+ struct stat file_status;
+ char *directory = NULL;
+ char *filename = NULL;
+ struct SetupFileList *setup_file_list = NULL;
+ struct dirent *dir_entry;
+ int i, current_entry = start_entry;
+
+ if ((dir = opendir(level_directory)) == NULL)
+ Error(ERR_EXIT, "cannot read level directory '%s'", level_directory);
+
+ while (current_entry < MAX_LEVDIR_ENTRIES)
+ {
+ if ((dir_entry = readdir(dir)) == NULL) /* last directory entry */
+ break;
+
+ /* skip entries for current and parent directory */
+ if (strcmp(dir_entry->d_name, ".") == 0 ||
+ strcmp(dir_entry->d_name, "..") == 0)
+ continue;
+
+ /* find out if directory entry is itself a directory */
+ directory = getPath2(level_directory, dir_entry->d_name);
+ if (stat(directory, &file_status) != 0 || /* cannot stat file */
+ (file_status.st_mode & S_IFMT) != S_IFDIR) /* not a directory */
+ {
+ free(directory);
+ continue;
+ }
+
+ if (strlen(dir_entry->d_name) >= MAX_LEVDIR_FILENAME)
+ {
+ Error(ERR_WARN, "filename of level directory '%s' too long -- ignoring",
+ dir_entry->d_name);
+ continue;
+ }
+
+ filename = getPath2(directory, LEVELINFO_FILENAME);
+ setup_file_list = loadSetupFileList(filename);
+
+ if (setup_file_list)
+ {
+ checkSetupFileListIdentifier(setup_file_list, LEVELINFO_COOKIE);
+ setLevelDirInfoToDefaults(&leveldir[current_entry]);
+
+ ldi = leveldir[current_entry];
+ for (i=FIRST_LEVELINFO_TOKEN; i<=LAST_LEVELINFO_TOKEN; i++)
+ setSetupInfo(i, getTokenValue(setup_file_list, token_info[i].text));
+ leveldir[current_entry] = ldi;
+
+ leveldir[current_entry].filename = getStringCopy(dir_entry->d_name);
+ leveldir[current_entry].user_defined =
+ (level_directory == options.level_directory ? FALSE : TRUE);
+
+ freeSetupFileList(setup_file_list);
+ current_entry++;
+ }
+ else
+ Error(ERR_WARN, "ignoring level directory '%s'", directory);
+
+ free(directory);
+ free(filename);
+ }
+
+ if (current_entry == MAX_LEVDIR_ENTRIES)
+ Error(ERR_WARN, "using %d level directories -- ignoring the rest",
+ current_entry);
+
+ closedir(dir);
+
+ if (current_entry == start_entry && start_entry != -1)
+ Error(ERR_EXIT, "cannot find any valid level series in directory '%s'",
+ level_directory);
+
+ return current_entry;
+}
+
+void LoadLevelInfo()
+{
+ InitUserLevelDirectory(getLoginName());
+
+ num_leveldirs = 0;
+ leveldir_nr = 0;
+
+ num_leveldirs = LoadLevelInfoFromLevelDir(options.level_directory,
+ num_leveldirs);
+ num_leveldirs = LoadLevelInfoFromLevelDir(getUserLevelDir(""),
+ num_leveldirs);
+ if (num_leveldirs > 1)
+ qsort(leveldir, num_leveldirs, sizeof(struct LevelDirInfo),
+ compareLevelDirInfoEntries);
+}
+
+static void SaveUserLevelInfo()
+{
+ char filename[MAX_FILENAME_LEN];
+ FILE *file;
+ int i;
+
+ sprintf(filename, "%s/%s",
+ getUserLevelDir(getLoginName()), LEVELINFO_FILENAME);
+
+ if (!(file = fopen(filename, "w")))
+ {
+ Error(ERR_WARN, "cannot write level info file '%s'", filename);
+ return;
+ }
+
+ ldi.name = getLoginName();
+ ldi.levels = 100;
+ ldi.sort_priority = 300;
+ ldi.readonly = FALSE;
+
+ fprintf(file, "%s\n\n",
+ getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER, LEVELINFO_COOKIE));
+
+ for (i=FIRST_LEVELINFO_TOKEN; i<=LAST_LEVELINFO_TOKEN; i++)
+ fprintf(file, "%s\n", getSetupLine("", i));
+
+ fclose(file);
+
+ chmod(filename, SETUP_PERMS);
+}
+
+void LoadSetup()
+{
+ char filename[MAX_FILENAME_LEN];
+ struct SetupFileList *setup_file_list = NULL;
+
+ /* always start with reliable default setup values */
+ setSetupInfoToDefaults(&setup);
+
+ sprintf(filename, "%s/%s", getSetupDir(), SETUP_FILENAME);
+
+ setup_file_list = loadSetupFileList(filename);
+
+ if (setup_file_list)
+ {
+ checkSetupFileListIdentifier(setup_file_list, SETUP_COOKIE);
+ decodeSetupFileList(setup_file_list);
+
+ setup.direct_draw = !setup.double_buffering;
+
+ freeSetupFileList(setup_file_list);
+
+ /* needed to work around problems with fixed length strings */
+ if (strlen(setup.player_name) >= MAX_NAMELEN)
+ setup.player_name[MAX_NAMELEN - 1] = '\0';
+ else if (strlen(setup.player_name) < MAX_NAMELEN - 1)
+ {
+ char *new_name = checked_malloc(MAX_NAMELEN);
+
+ strcpy(new_name, setup.player_name);
+ free(setup.player_name);
+ setup.player_name = new_name;
+ }
+ }
+ else
+ Error(ERR_WARN, "using default setup values");
+}
+
+static char *getSetupLine(char *prefix, int token_nr)
+{
+ int i;
+ static char entry[MAX_LINE_LEN];
+ int token_type = token_info[token_nr].type;
+ void *setup_value = token_info[token_nr].value;
+ char *token_text = token_info[token_nr].text;
+
+ /* start with the prefix, token and some spaces to format output line */
+ sprintf(entry, "%s%s:", prefix, token_text);
+ for (i=strlen(entry); i<TOKEN_VALUE_POSITION; i++)
+ strcat(entry, " ");
+
+ /* continue with the token's value (which can have different types) */
+ switch (token_type)
+ {
+ case TYPE_BOOLEAN:
+ strcat(entry, (*(boolean *)setup_value ? "true" : "false"));
+ break;
+
+ case TYPE_SWITCH:
+ strcat(entry, (*(boolean *)setup_value ? "on" : "off"));
+ break;
+
+ case TYPE_KEYSYM:
+ {
+ KeySym keysym = *(KeySym *)setup_value;
+ char *keyname = getKeyNameFromKeySym(keysym);
+
+ strcat(entry, getX11KeyNameFromKeySym(keysym));
+ for (i=strlen(entry); i<50; i++)
+ strcat(entry, " ");
+
+ /* add comment, if useful */
+ if (strcmp(keyname, "(undefined)") != 0 &&
+ strcmp(keyname, "(unknown)") != 0)
+ {
+ strcat(entry, "# ");
+ strcat(entry, keyname);
+ }
+ }
+ break;
+
+ case TYPE_INTEGER:
+ {
+ char buffer[MAX_LINE_LEN];
+
+ sprintf(buffer, "%d", *(int *)setup_value);
+ strcat(entry, buffer);
+ }
+ break;
+
+ case TYPE_STRING:
+ strcat(entry, *(char **)setup_value);
+ break;
+
+ default:
+ break;
+ }
+
+ return entry;
+}
+
+void SaveSetup()
+{
+ int i, pnr;
+ char filename[MAX_FILENAME_LEN];
+ FILE *file;
+
+ InitUserDataDirectory();
+
+ sprintf(filename, "%s/%s", getSetupDir(), SETUP_FILENAME);
+
+ if (!(file = fopen(filename, "w")))
+ {
+ Error(ERR_WARN, "cannot write setup file '%s'", filename);
+ return;
+ }
+
+ fprintf(file, "%s\n",
+ getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER, SETUP_COOKIE));
+ fprintf(file, "\n");
+
+ /* handle global setup values */
+ si = setup;
+ for (i=FIRST_GLOBAL_SETUP_TOKEN; i<=LAST_GLOBAL_SETUP_TOKEN; i++)
+ {
+ fprintf(file, "%s\n", getSetupLine("", i));
+
+ /* just to make things nicer :) */
+ if (i == SETUP_TOKEN_PLAYER_NAME)
+ fprintf(file, "\n");
+ }
+
+ /* handle player specific setup values */
+ for (pnr=0; pnr<MAX_PLAYERS; pnr++)
+ {
+ char prefix[30];
+
+ sprintf(prefix, "%s%d", TOKEN_STR_PLAYER_PREFIX, pnr + 1);
+ fprintf(file, "\n");
+
+ sii = setup.input[pnr];
+ for (i=FIRST_PLAYER_SETUP_TOKEN; i<=LAST_PLAYER_SETUP_TOKEN; i++)
+ fprintf(file, "%s\n", getSetupLine(prefix, i));
+ }
+
+ fclose(file);
+
+ chmod(filename, SETUP_PERMS);
+}
+
+void LoadLevelSetup()
+{
+ char filename[MAX_FILENAME_LEN];
+
+ /* always start with reliable default setup values */
+
+ leveldir_nr = 0;
+ level_nr = 0;
+
+ sprintf(filename, "%s/%s", getSetupDir(), LEVELSETUP_FILENAME);
+
+ if (level_setup_list)
+ freeSetupFileList(level_setup_list);
+
+ level_setup_list = loadSetupFileList(filename);
+
+ if (level_setup_list)
+ {
+ char *last_level_series =
+ getTokenValue(level_setup_list, TOKEN_STR_LAST_LEVEL_SERIES);
+
+ leveldir_nr = getLevelSeriesNrFromLevelSeriesName(last_level_series);
+ level_nr = getLastPlayedLevelOfLevelSeries(last_level_series);
+
+ checkSetupFileListIdentifier(level_setup_list, LEVELSETUP_COOKIE);
+ }
+ else
+ {
+ level_setup_list = newSetupFileList(TOKEN_STR_FILE_IDENTIFIER,
+ LEVELSETUP_COOKIE);
+ Error(ERR_WARN, "using default setup values");
+ }
+}
+
+void SaveLevelSetup()
+{
+ char filename[MAX_FILENAME_LEN];
+ struct SetupFileList *list_entry = level_setup_list;
+ FILE *file;
+
+ InitUserDataDirectory();
+
+ setTokenValue(level_setup_list,
+ TOKEN_STR_LAST_LEVEL_SERIES, leveldir[leveldir_nr].filename);
+
+ setTokenValue(level_setup_list,
+ leveldir[leveldir_nr].filename, int2str(level_nr, 0));
+
+ sprintf(filename, "%s/%s", getSetupDir(), LEVELSETUP_FILENAME);
+
+ if (!(file = fopen(filename, "w")))
+ {
+ Error(ERR_WARN, "cannot write setup file '%s'", filename);
+ return;
+ }
+
+ fprintf(file, "%s\n\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER,
+ LEVELSETUP_COOKIE));
+ while (list_entry)
+ {
+ if (strcmp(list_entry->token, TOKEN_STR_FILE_IDENTIFIER) != 0)
+ fprintf(file, "%s\n",
+ getFormattedSetupEntry(list_entry->token, list_entry->value));
+
+ /* just to make things nicer :) */
+ if (strcmp(list_entry->token, TOKEN_STR_LAST_LEVEL_SERIES) == 0)
+ fprintf(file, "\n");
+
+ list_entry = list_entry->next;
+ }
+
+ fclose(file);
+
+ chmod(filename, SETUP_PERMS);
+}
+++ /dev/null
-/* gadget.c */
-
-#include "gadget.h"
-
-struct Gadget *gadget_list;
-
-void NextGadgetEvent()
+++ /dev/null
-/* gadget.h */
-
-/* gadget types */
-#define GD_TYPE_NORMAL_BUTTON (1<<0)
-#define GD_TYPE_TWO_STATE_BUTTON (1<<1)
-#define GD_TYPE_DRAWING_AREA (1<<2)
-#define GD_TYPE_TEXTINPUT (1<<3)
-#define GD_TYPE_TEXTOUTPUT (1<<4)
-#define GD_TYPE_NUMBERINPUT (1<<5)
-#define GD_TYPE_NUMBEROUTPUT (1<<6)
-
-/* gadget events */
-#define GD_EVENT_PRESSED (1<<0)
-#define GD_EVENT_RELEASED (1<<1)
-#define GD_EVENT_MOVING (1<<2)
-
-/* gadget structure constants */
-#define MAX_GADGET_TEXTSIZE 1024
-
-struct GadgetDesign
-{
- Pixmap pixmap; /* Pixmap with gadget surface */
- int x,y; /* position of rectangle in Pixmap */
-};
-
-struct Gadget
-{
- int x,y; /* screen position */
- int width,height; /* screen size */
- unsigned long type; /* type (button, text input, ...) */
- unsigned long state; /* state (pressed, released, ...) */
- long number_value;
- char text_value[MAX_GADGET_TEXTSIZE];
- struct GadgetDesign *design[2]; /* 0: normal; 1: pressed */
- struct GadgetDesign *alt_design[2]; /* alternative design */
- unsigned long event; /* actual gadget event */
- struct Gadget *next; /* next list entry */
-};
-
-struct NewGadget
-{
- int x,y; /* screen position */
- int width,height; /* screen size */
- unsigned long type; /* type (button, text input, ...) */
- struct GadgetDesign *design[2]; /* 0: normal; 1: pressed */
- struct GadgetDesign *alt_design[2]; /* alternative design */
- unsigned long value_mask; /* actual gadget event */
-};
-
-struct GadgetEvent
-{
- unsigned long state; /* state (pressed, released, ...) */
- int x,y; /* position inside drawing area */
-};
+++ /dev/null
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back! *
-*----------------------------------------------------------*
-* (c) 1995-98 Artsoft Entertainment *
-* Holger Schemel *
-* Oststrasse 11a *
-* 33604 Bielefeld *
-* phone: ++49 +521 290471 *
-* email: aeglos@valinor.owl.de *
-*----------------------------------------------------------*
-* gfxload.c *
-***********************************************************/
-
-#ifndef MSDOS
-#include "gfxload.h"
-
-
-
-
-
-
-extern Window window;
-extern void Delay(long);
-
-
-
-
-
-
-#ifdef DEBUG
-/*
-#define DEBUG_GIF
-#define DEBUG_ILBM
-*/
-#endif
-
-struct IFF_ILBM_FORM_big_endian
-{
- char magic_FORM[4];
- unsigned char chunk_size[4];
- char magic_ILBM[4];
-};
-
-struct IFF_ILBM_BMHD_big_endian
-{
- char Width[2], Height[2];
- char LeftEdge[2], TopEdge[2];
- char Depth;
- char Mask;
- char Compression;
- char pad1;
- char transparentColor[2];
- char xAspect, yAspect;
- char pageWidth[2], pageHeight[2];
-};
-
-struct IFF_ILBM_BMHD
-{
- unsigned int Width, Height;
- int LeftEdge, TopEdge;
- unsigned int Depth;
- unsigned int Mask;
- unsigned int Compression;
- unsigned char pad1;
- unsigned int transparentColor;
- unsigned int xAspect, yAspect;
- int pageWidth, pageHeight;
-};
-
-static int ConvertXImageDepth(Display *, XImage **);
-static int Read_GIF_to_Pixmap_or_Bitmap(Display *, char *, Pixmap *, int);
-
-#define READ_GIF_TO_BITMAP 0
-#define READ_GIF_TO_PIXMAP 1
-
-int Read_GIF_to_Bitmap(Display *display, char *filename, Pixmap *pixmap)
-{
- return(Read_GIF_to_Pixmap_or_Bitmap(display, filename,
- pixmap, READ_GIF_TO_BITMAP));
-}
-
-int Read_GIF_to_Pixmap(Display *display, char *filename, Pixmap *pixmap)
-{
- return(Read_GIF_to_Pixmap_or_Bitmap(display, filename,
- pixmap, READ_GIF_TO_PIXMAP));
-}
-
-int Read_GIF_to_Pixmap_or_Bitmap(Display *display, char *filename,
- Pixmap *pixmap, int mode)
-{
- XImage *image = NULL;
- Pixmap new_pixmap = 0;
- int return_code;
-
- *pixmap = 0;
- return_code = Read_GIF_to_XImage(display, filename, &image);
- if (return_code != GIF_Success)
- return(return_code);
-
- if (image)
- {
- int screen = DefaultScreen(display);
- Drawable root = RootWindow(display,screen);
- int depth = DefaultDepth(display, screen);
- int width = image->width;
- int height = image->height;
-
- if (mode == READ_GIF_TO_BITMAP)
- {
- int i,x,y;
- unsigned long black_pixel = BlackPixel(display,screen);
- int bytes_per_line = (width+7) / 8;
- int size = bytes_per_line * height;
- char *data, *ptr;
-
- data = (char *)malloc(size);
- if (!data)
- return(GIF_NoMemory);
-
- ptr = data;
- for(i=0;i<size;i++)
- *ptr++ = 0;
-
- for(y=0;y<height;y++)
- {
- for(x=0;x<width;x++)
- {
- if (XGetPixel(image,x,y) == black_pixel)
- data[y * bytes_per_line + x/8] |= (1 << (x%8));
- }
- }
-
- new_pixmap = XCreateBitmapFromData(display,root,data,width,height);
- free(data);
-
- if (!new_pixmap)
- return(GIF_NoMemory);
- }
- else
- {
- GC gc;
- XGCValues gcv;
-
- if (ConvertXImageDepth(display, &image) != GIF_Success)
- return(GIF_ColorFailed);
-
- new_pixmap = XCreatePixmap(display,root,width,height,depth);
-
- if (!new_pixmap)
- return(GIF_NoMemory);
-
- gcv.foreground = BlackPixel(display,screen);
- gcv.background = WhitePixel(display,screen);
- gc = XCreateGC(display, root, GCForeground | GCBackground, &gcv);
- XPutImage(display,new_pixmap,gc,image,0,0,0,0,width,height);
-
- XFreeGC(display, gc);
- }
-
- XDestroyImage(image);
- }
-
- *pixmap = new_pixmap;
- return(return_code);
-}
-
-
-/*
- * Read_GIF_to_XImage() - based strongly on...
- *
- * xgifload.c - based strongly on...
- *
- * gif2ras.c - Converts from a Compuserve GIF (tm) image to a Sun Raster image.
- *
- * Copyright (c) 1988, 1989 by Patrick J. Naughton
- *
- * Author: Patrick J. Naughton
- * naughton@wind.sun.com
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation.
- *
- * This file is provided AS IS with no warranties of any kind. The author
- * shall have no liability with respect to the infringement of copyrights,
- * trade secrets or any patents by this file or any part thereof. In no
- * event will the author be liable for any lost revenue or profits or
- * other special, indirect and consequential damages.
- *
- */
-
-typedef int boolean;
-typedef unsigned char byte;
-
-static int ReadCode(void);
-static void AddToPixel(byte);
-static int ColorDicking(Display *);
-
-#define NEXTBYTE (*ptr++)
-#define IMAGESEP 0x2c
-#define INTERLACEMASK 0x40
-#define COLORMAPMASK 0x80
-
-static
-int BitOffset, /* Bit Offset of next code */
- XC, YC, /* Output X and Y coords of current pixel */
- Pass, /* Used by output routine if interlaced pic */
- OutCount, /* Decompressor output 'stack count' */
- RWidth, RHeight, /* screen dimensions */
- Width, Height, /* image dimensions */
- LeftOfs, TopOfs, /* image offset */
- BitsPerPixel, /* Bits per pixel, read from GIF header */
- BytesPerScanline, /* bytes per scanline in output raster */
- ColorMapSize, /* number of colors */
- Background, /* background color */
- CodeSize, /* Code size, read from GIF header */
- InitCodeSize, /* Starting code size, used during Clear */
- Code, /* Value returned by ReadCode */
- MaxCode, /* limiting value for current code size */
- ClearCode, /* GIF clear code */
- EOFCode, /* GIF end-of-information code */
- CurCode, OldCode, InCode, /* Decompressor variables */
- FirstFree, /* First free code, generated per GIF spec */
- FreeCode, /* Decompressor, next free slot in hash table*/
- FinChar, /* Decompressor variable */
- BitMask, /* AND mask for data size */
- ReadMask; /* Code AND mask for current code size */
-
-static boolean Interlace, HasColormap;
-
-static byte *ImageData; /* The result array */
-static byte *RawGIF; /* The heap array to hold it, raw */
-static byte *Raster; /* The raster data stream, unblocked */
-
-/* The color map, read from the GIF header */
-static byte Red[256], Green[256], Blue[256], used[256];
-static int numused;
-
-extern char *progname;
-
-static int numcols;
-static unsigned long cols[256];
-static XColor defs[256];
-
-int Read_GIF_to_XImage(Display *display, char *filename, XImage **image)
-{
- int filesize;
- register byte ch, ch1;
- register byte *ptr, *ptr1;
- register int i;
- int screen = DefaultScreen(display);
- Visual *visual = DefaultVisual(display,screen);
- XImage *new_image = NULL;
- char *id = "GIF87a";
- FILE *file;
- int Prefix[4096]; /* The hash table used by the decompressor */
- int Suffix[4096];
- int OutCode[1025]; /* An output array used by the decompressor */
-
- BitOffset = XC = YC = Pass = OutCount = 0;
- *image = NULL;
-
- if (strcmp(filename,"-")==0)
- {
- file = stdin;
- filename = "<stdin>";
- }
- else
- file = fopen(filename,"r");
-
- if (!file)
- return(GIF_OpenFailed);
-
- /* find the size of the file */
- fseek(file, 0L, 2);
- filesize = ftell(file);
- fseek(file, 0L, 0);
-
- if (!(ptr = RawGIF = (byte *) malloc(filesize)))
- return(GIF_NoMemory);
-
- if (!(Raster = (byte *) malloc(filesize)))
- return(GIF_NoMemory);
-
- if (fread(ptr, filesize, 1, file) != 1)
- return(GIF_ReadFailed);
-
- if (strncmp(ptr, id, 6))
- return(GIF_FileInvalid);
-
- ptr += 6;
-
- /* Get variables from the GIF screen descriptor */
-
- ch = NEXTBYTE;
- RWidth = ch + 0x100 * NEXTBYTE; /* screen dimensions... not used. */
- ch = NEXTBYTE;
- RHeight = ch + 0x100 * NEXTBYTE;
-
- ch = NEXTBYTE;
- HasColormap = ((ch & COLORMAPMASK) ? True : False);
-
- BitsPerPixel = (ch & 7) + 1;
- numcols = ColorMapSize = 1 << BitsPerPixel;
- BitMask = ColorMapSize - 1;
-
- Background = NEXTBYTE; /* background color... not used. */
-
- if (NEXTBYTE) /* supposed to be NULL */
- return(GIF_FileInvalid);
-
- /* Read in global colormap. */
-
- if (HasColormap)
- {
- for (i = 0; i < ColorMapSize; i++)
- {
- Red[i] = NEXTBYTE;
- Green[i] = NEXTBYTE;
- Blue[i] = NEXTBYTE;
- used[i] = 0;
- }
- numused = 0;
- }
- else
- {
- /* no colormap in GIF file */
- fprintf(stderr,"%s: warning! no colortable in this file. Winging it.\n",
- progname);
- if (!numcols)
- numcols=256;
- for (i=0; i<numcols; i++)
- cols[i] = (unsigned long) i;
- }
-
- /* Check for image seperator */
-
- if (NEXTBYTE != IMAGESEP)
- return(GIF_FileInvalid);
-
- /* Now read in values from the image descriptor */
-
- ch = NEXTBYTE;
- LeftOfs = ch + 0x100 * NEXTBYTE;
- ch = NEXTBYTE;
- TopOfs = ch + 0x100 * NEXTBYTE;
- ch = NEXTBYTE;
- Width = ch + 0x100 * NEXTBYTE;
- ch = NEXTBYTE;
- Height = ch + 0x100 * NEXTBYTE;
- Interlace = ((NEXTBYTE & INTERLACEMASK) ? True : False);
-
-#ifdef DEBUG_GIF
- fprintf(stderr, "%s:\n", filename);
- fprintf(stderr, " %dx%d, %d bpp / %d colors, %sinterlaced\n",
- Width,Height, BitsPerPixel,ColorMapSize,(Interlace ? "" : "non-"));
- fprintf(stderr, " Reading file... ");
-#endif
-
- /* Note that I ignore the possible existence of a local color map.
- * I'm told there aren't many files around that use them, and the spec
- * says it's defined for future use. This could lead to an error
- * reading some files.
- */
-
- /* Start reading the raster data. First we get the intial code size
- * and compute decompressor constant values, based on this code size.
- */
-
- CodeSize = NEXTBYTE;
- ClearCode = (1 << CodeSize);
- EOFCode = ClearCode + 1;
- FreeCode = FirstFree = ClearCode + 2;
-
- /* The GIF spec has it that the code size is the code size used to
- * compute the above values is the code size given in the file, but the
- * code size used in compression/decompression is the code size given in
- * the file plus one. (thus the ++).
- */
-
- CodeSize++;
- InitCodeSize = CodeSize;
- MaxCode = (1 << CodeSize);
- ReadMask = MaxCode - 1;
-
- /* Read the raster data. Here we just transpose it from the GIF array
- * to the Raster array, turning it from a series of blocks into one long
- * data stream, which makes life much easier for ReadCode().
- */
-
- ptr1 = Raster;
- do
- {
- ch = ch1 = NEXTBYTE;
- while (ch--) *ptr1++ = NEXTBYTE;
- if ((Raster - ptr1) > filesize)
- return(GIF_FileInvalid);
- }
- while(ch1);
-
- free(RawGIF); /* We're done with the raw data now... */
-
-#ifdef DEBUG_GIF
- fprintf(stderr, "done\n");
- fprintf(stderr, " Decompressing... ");
-#endif
-
- /* Allocate the X Image */
- ImageData = (byte *) malloc(Width*Height);
- if (!ImageData)
- return(GIF_NoMemory);
-
- new_image = XCreateImage(display,visual,8,ZPixmap,0,ImageData,
- Width,Height,8,Width);
- if (!new_image)
- return(GIF_NoMemory);
-
- BytesPerScanline = Width;
-
-
- /* Decompress the file, continuing until you see the GIF EOF code.
- * One obvious enhancement is to add checking for corrupt files here.
- */
-
- Code = ReadCode();
- while (Code != EOFCode)
- {
- /* Clear code sets everything back to its initial value, then reads the
- * immediately subsequent code as uncompressed data.
- */
-
- if (Code == ClearCode)
- {
- CodeSize = InitCodeSize;
- MaxCode = (1 << CodeSize);
- ReadMask = MaxCode - 1;
- FreeCode = FirstFree;
- CurCode = OldCode = Code = ReadCode();
- FinChar = CurCode & BitMask;
- AddToPixel(FinChar);
- }
- else
- {
- /* If not a clear code, then must be data:
- * save same as CurCode and InCode
- */
-
- CurCode = InCode = Code;
-
- /* If greater or equal to FreeCode, not in the hash table yet;
- * repeat the last character decoded
- */
-
- if (CurCode >= FreeCode)
- {
- CurCode = OldCode;
- OutCode[OutCount++] = FinChar;
- }
-
- /* Unless this code is raw data, pursue the chain pointed to by CurCode
- * through the hash table to its end; each code in the chain puts its
- * associated output code on the output queue.
- */
-
- while (CurCode > BitMask)
- {
- if (OutCount > 1024)
- return(GIF_FileInvalid);
-
- OutCode[OutCount++] = Suffix[CurCode];
- CurCode = Prefix[CurCode];
- }
-
- /* The last code in the chain is treated as raw data. */
-
- FinChar = CurCode & BitMask;
- OutCode[OutCount++] = FinChar;
-
- /* Now we put the data out to the Output routine.
- * It's been stacked LIFO, so deal with it that way...
- */
-
- for (i = OutCount - 1; i >= 0; i--)
- AddToPixel(OutCode[i]);
- OutCount = 0;
-
- /* Build the hash table on-the-fly. No table is stored in the file. */
-
- Prefix[FreeCode] = OldCode;
- Suffix[FreeCode] = FinChar;
- OldCode = InCode;
-
- /* Point to the next slot in the table. If we exceed the current
- * MaxCode value, increment the code size unless it's already 12. If it
- * is, do nothing: the next code decompressed better be CLEAR
- */
-
- FreeCode++;
- if (FreeCode >= MaxCode)
- {
- if (CodeSize < 12)
- {
- CodeSize++;
- MaxCode *= 2;
- ReadMask = (1 << CodeSize) - 1;
- }
- }
- }
- Code = ReadCode();
- }
-
- free(Raster);
-
-#ifdef DEBUG_GIF
- fprintf(stderr, "done\n");
- fprintf(stderr," %d colors used\n",numused);
-#endif
-
- if (file != stdin)
- fclose(file);
-
- if (ColorDicking(display) != GIF_Success)
- return(GIF_ColorFailed);
-
- *image = new_image;
- return(GIF_Success);
-}
-
-
-/* Fetch the next code from the raster data stream. The codes can be
- * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
- * maintain our location in the Raster array as a BIT Offset. We compute
- * the byte Offset into the raster array by dividing this by 8, pick up
- * three bytes, compute the bit Offset into our 24-bit chunk, shift to
- * bring the desired code to the bottom, then mask it off and return it.
- */
-
-static int ReadCode()
-{
- int RawCode, ByteOffset;
-
- ByteOffset = BitOffset / 8;
- RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]);
- if (CodeSize >= 8)
- RawCode += (0x10000 * Raster[ByteOffset + 2]);
- RawCode >>= (BitOffset % 8);
- BitOffset += CodeSize;
- return(RawCode & ReadMask);
-}
-
-
-static void AddToPixel(byte Index)
-{
- if (YC<Height)
- *(ImageData + YC * BytesPerScanline + XC) = Index;
-
- if (!used[Index])
- {
- used[Index]=1;
- numused++;
- }
-
- /* Update the X-coordinate, and if it overflows, update the Y-coordinate */
-
- if (++XC == Width)
- {
- /* If a non-interlaced picture, just increment YC to the next scan line.
- * If it's interlaced, deal with the interlace as described in the GIF
- * spec. Put the decoded scan line out to the screen if we haven't gone
- * past the bottom of it
- */
-
- XC = 0;
- if (!Interlace)
- YC++;
- else
- {
- switch (Pass)
- {
- case 0:
- YC += 8;
- if (YC >= Height)
- {
- Pass++;
- YC = 4;
- }
- break;
-
- case 1:
- YC += 8;
- if (YC >= Height)
- {
- Pass++;
- YC = 2;
- }
- break;
-
- case 2:
- YC += 4;
- if (YC >= Height)
- {
- Pass++;
- YC = 1;
- }
- break;
-
- case 3:
- YC += 2;
- break;
-
- default:
- break;
- }
- }
- }
-}
-
-
-static int ColorDicking(Display *display)
-{
- /* we've got the picture loaded, we know what colors are needed. get 'em */
-
- register int i,j;
- static byte lmasks[8] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80};
- byte lmask, *ptr;
- int screen = DefaultScreen(display);
- Colormap cmap = DefaultColormap(display,screen);
- int dispcells = DisplayCells(display,screen);
-
- int strip = 0;
- int nostrip = 0;
-
- if (!HasColormap)
- return(GIF_Success);
- /* no need to allocate any colors if no colormap in GIF file */
-
- /* Allocate the X colors for this picture */
-
- if (nostrip)
- {
- /* nostrip was set. try REAL hard to do it */
- for (i=j=0; i<numcols; i++)
- {
- if (used[i])
- {
- defs[i].red = Red[i]<<8;
- defs[i].green = Green[i]<<8;
- defs[i].blue = Blue[i]<<8;
- defs[i].flags = DoRed | DoGreen | DoBlue;
- if (!XAllocColor(display,cmap,&defs[i]))
- {
- j++;
- defs[i].pixel = 0xffff;
- }
- cols[i] = defs[i].pixel;
- }
- }
-
- if (j)
- {
- /* failed to pull it off */
-
- XColor ctab[256];
- int dc;
-
- dc = (dispcells<256) ? dispcells : 256;
-
- fprintf(stderr,
- "failed to allocate %d out of %d colors. Trying extra hard.\n",
- j,numused);
-
- /* read in the color table */
- for (i=0; i<dc; i++)
- ctab[i].pixel = i;
- XQueryColors(display,cmap,ctab,dc);
-
- /* run through the used colors. any used color that has a pixel
- value of 0xffff wasn't allocated. for such colors, run through
- the entire X colormap and pick the closest color */
-
- for (i=0; i<numcols; i++)
- if (used[i] && cols[i]==0xffff)
- {
- /* an unallocated pixel */
-
- int d, mdist, close;
- unsigned long r,g,b;
-
- mdist = 100000; close = -1;
- r = Red[i];
- g = Green[i];
- b = Blue[i];
- for (j=0; j<dc; j++)
- {
- d = abs(r - (ctab[j].red>>8)) +
- abs(g - (ctab[j].green>>8)) +
- abs(b - (ctab[j].blue>>8));
- if (d<mdist)
- {
- mdist=d;
- close=j;
- }
- }
-
- if (close<0)
- return(GIF_ColorFailed);
-
- bcopy(&defs[close],&defs[i],sizeof(XColor));
- cols[i] = ctab[close].pixel;
- }
- } /* end 'failed to pull it off' */
- }
- else
- {
- /* strip wasn't set, do the best auto-strip */
-
- j = 0;
- while (strip<8)
- {
- lmask = lmasks[strip];
- for (i=0; i<numcols; i++)
- {
- if (used[i])
- {
- defs[i].red = (Red[i] &lmask)<<8;
- defs[i].green = (Green[i]&lmask)<<8;
- defs[i].blue = (Blue[i] &lmask)<<8;
- defs[i].flags = DoRed | DoGreen | DoBlue;
- if (!XAllocColor(display,cmap,&defs[i]))
- break;
- cols[i] = defs[i].pixel;
- }
- }
-
- if (i<numcols)
- {
- /* failed */
- strip++;
- j++;
- for (i--; i>=0; i--)
- if (used[i])
- XFreeColors(display,cmap,cols+i,1,0L);
- }
- else
- break;
- }
-
-#ifdef DEBUG_GIF
- if (j && strip<8)
- fprintf(stderr,"%s: stripped %d bits\n",progname,strip);
-#endif
-
- if (strip==8)
- {
- fprintf(stderr,"UTTERLY failed to allocate the desired colors.\n");
- for (i=0; i<numcols; i++) cols[i]=i;
- }
- }
-
- ptr = ImageData;
- for (i=0; i<Height; i++)
- for (j=0; j<Width; j++,ptr++)
- *ptr = (byte) cols[*ptr];
-
- return(GIF_Success);
-}
-
-
-/******************************************************************************
- * This makes sure the display's depth is the same as the
- * depth of the default 8 bit image. If not, we build a new image
- * that has the correct depth. This works on the fact that
- * the color mapper has already changed every pixel value in the
- * image into the proper number of bits (to fit into the pallet)
- * so we can just chop down the number of bits.
- * This changes the global variable 'expImage' if necessary.
- */
-
-static int ConvertXImageDepth(Display *display, XImage **image)
-{
- int screen = DefaultScreen(display);
- int depth = DefaultDepth(display, screen);
-
-
-
-
-
-
- printf("ConvertXImageDepth:\n");
- printf("(*image)->depth == %d\n",
- (*image)->depth);
- printf("DefaultDepth(display, screen) == %d\n",
- DefaultDepth(display, screen));
-
-
-
-
- if ((*image)->depth != depth)
- {
- XImage *old_image, *new_image;
-
- Visual *visual = DefaultVisual(display,screen);
-
- int width = (*image)->width;
- int height = (*image)->height;
- register int dwx, dwy;
- byte *data;
-
-
-
-
-
- printf("ConvertXImageDepth: ---------> CONVERTING...\n");
-
-
-
-
-
-
- data = (byte *)malloc(width * height * depth);
- old_image = *image;
-
-#if 1
- new_image = XCreateImage(display,visual,depth,
- ZPixmap,0,data,width,height,8,0);
-#else
- new_image = XGetImage(display,RootWindow(display,screen),
- 0,0,width,height,0xffffffff,ZPixmap);
-#endif
-
- if (!new_image)
- return(GIF_NoMemory);
-
- if (old_image->depth == 8 && new_image->depth == 4)
- {
- /* speedup for the most common format change */
-
- register byte *sptr = (byte *)old_image->data;
- register byte *dptr = (byte *)new_image->data;
-
- for (dwy=1; dwy<=height; dwy++)
- {
- for (dwx=1; dwx<width; dwx+=2)
- {
- *dptr = (*sptr) | (*(sptr+1)<<4);
- dptr++;
- sptr+=2;
- }
- if (width & 1)
- {
- /* if extra pixal at end of line, just move it */
- *dptr = *sptr;
- sptr++; dptr++;
- }
- }
- }
- else /* other format change than 8 bit -> 4 bit */
- {
- unsigned long pixel_value;
-
- for (dwx=0; dwx<width; dwx++)
- {
- for (dwy=0; dwy<height; dwy++)
- {
- pixel_value = XGetPixel(old_image, dwx, dwy);
-
- if (pixel_value > 0xff)
- printf("pixel = %lx", pixel_value);
-
- XPutPixel(new_image, dwx, dwy, pixel_value);
- }
- }
- }
-
- free(old_image->data);
- old_image->data = NULL;
- XDestroyImage(old_image);
-
- *image = new_image;
- }
-
- return(GIF_Success);
-}
-
-
-static unsigned long be2long(unsigned char *be) /* big-endian -> long int */
-{
- return((be[0]<<24) | (be[1]<<16) | (be[2]<<8) | be[3]);
-}
-
-static unsigned short be2short(unsigned char *be) /* big-endian -> short int */
-{
- return((be[0]<<8) | be[1]);
-}
-
-static struct IFF_ILBM_BMHD *ConvertBMHD(unsigned char *header_data)
-{
- struct IFF_ILBM_BMHD_big_endian *bmhd_be;
- struct IFF_ILBM_BMHD *bmhd;
-
- bmhd_be = (struct IFF_ILBM_BMHD_big_endian *)header_data;
- bmhd = (struct IFF_ILBM_BMHD *)malloc(sizeof(struct IFF_ILBM_BMHD));
- if (!bmhd)
- return(NULL);
-
- bmhd->Width = be2short(bmhd_be->Width);
- bmhd->Height = be2short(bmhd_be->Height);
- bmhd->LeftEdge = be2short(bmhd_be->LeftEdge);
- bmhd->TopEdge = be2short(bmhd_be->TopEdge);
- bmhd->Depth = (int)bmhd_be->Depth;
- bmhd->Mask = (int)bmhd_be->Mask;
- bmhd->Compression = (int)bmhd_be->Compression;
- bmhd->pad1 = bmhd_be->pad1;
- bmhd->transparentColor = be2short(bmhd_be->transparentColor);
- bmhd->xAspect = (int)bmhd_be->xAspect;
- bmhd->yAspect = (int)bmhd_be->yAspect;
- bmhd->pageWidth = be2short(bmhd_be->pageWidth);
- bmhd->pageHeight = be2short(bmhd_be->pageHeight);
-
- return(bmhd);
-}
-
-static unsigned char MSBitFirst2LSBitFirst(unsigned char msb_byte)
-{
- unsigned char lsb_byte = 0;
- int i;
-
- for(i=7;i>=0;i--)
- {
- lsb_byte |= (msb_byte & 1) << i;
- msb_byte >>= 1;
- }
-
- return(lsb_byte);
-}
-
-int Read_ILBM_to_Bitmap(Display *display, char *filename, Pixmap *pixmap)
-{
- Pixmap new_pixmap = 0;
- int screen = DefaultScreen(display);
- Drawable root = RootWindow(display,screen);
- struct IFF_ILBM_FORM_big_endian *form_header;
- struct IFF_ILBM_BMHD *bitmap_header;
- unsigned long file_len, body_len;
- unsigned char *file_data, *bitmap_data;
- unsigned char *file_ptr, *bitmap_ptr, *body_ptr;
- unsigned char byte_count, byte_value;
- int i,x,y,z;
- int width, height, depth;
- int bytes_per_line, bitmap_size;
- FILE *file;
-
- if (!(file = fopen(filename,"r")))
- return(ILBM_OpenFailed);
-
- if (fseek(file,0,SEEK_END) < 0)
- {
- fclose(file);
- return(ILBM_ReadFailed);
- }
-
- file_len = ftell(file);
- rewind(file);
-
- if (!(file_data = (unsigned char *)malloc(file_len)))
- {
- fclose(file);
- return(ILBM_NoMemory);
- }
-
- if (fread(file_data,1,file_len,file) != file_len)
- {
- free(file_data);
- fclose(file);
- return(ILBM_ReadFailed);
- }
-
- fclose(file);
-
- form_header = (struct IFF_ILBM_FORM_big_endian *)file_data;
-
- if (strncmp(form_header->magic_FORM,"FORM",4) ||
- file_len != be2long(form_header->chunk_size)+8 ||
- strncmp(form_header->magic_ILBM,"ILBM",4))
- {
-#ifdef DEBUG_ILBM
- printf("%s: IFF chunk 'FORM' and/or 'ILBM' not found.\n",filename);
-#endif
- free(file_data);
- return(ILBM_FileInvalid);
- }
-
- bitmap_header = NULL;
- body_ptr = NULL;
- file_ptr = file_data + 12;
-
- while(file_ptr < (unsigned char *)(file_data + file_len))
- {
- if (!strncmp(file_ptr,"BMHD",4))
- {
-#ifdef DEBUG_ILBM
- printf("%s: IFF chunk 'BMHD' found.\n",filename);
-#endif
- bitmap_header = ConvertBMHD(file_ptr + 8);
- file_ptr += be2long(file_ptr + 4) + 8;
- continue;
- }
- else if (!strncmp(file_ptr,"BODY",4))
- {
-#ifdef DEBUG_ILBM
- printf("%s: IFF chunk 'BODY' found.\n",filename);
-#endif
- body_ptr = file_ptr + 8;
- body_len = be2long(file_ptr + 4);
- file_ptr += be2long(file_ptr + 4) + 8;
- continue;
- }
- else
- {
-#ifdef DEBUG_ILBM
- printf("%s: IFF chunk '%c%c%c%c' found (but not used).\n",filename,
- file_ptr[0],file_ptr[1],file_ptr[2],file_ptr[3]);
-#endif
- /* other chunk not recognized here */
- file_ptr += be2long(file_ptr + 4) + 8;
- continue;
- }
- }
-
- if (!bitmap_header || !body_ptr)
- {
-#ifdef DEBUG_ILBM
- printf("%s: IFF chunk 'BMHD' and/or 'BODY' not found.\n",filename);
-#endif
- free(file_data);
- return(ILBM_FileInvalid);
- }
-
- width = bitmap_header->Width;
- height = bitmap_header->Height;
- depth = bitmap_header->Depth;
-
-#ifdef DEBUG_ILBM
- if (depth > 1)
- printf("%s: %d bitplanes found; using only the first plane.\n",
- filename,depth);
-#endif
-
- bytes_per_line = ((width + 15) / 16) * 2;
- bitmap_size = bytes_per_line * height;
-
- bitmap_data = (char *)malloc(bitmap_size);
- if (!bitmap_data)
- {
- free(file_data);
- free(bitmap_header);
- return(ILBM_NoMemory);
- }
-
- bitmap_ptr = bitmap_data;
- for(i=0;i<bitmap_size;i++)
- *bitmap_ptr++ = 0;
-
- for(y=0;y<height;y++)
- {
- /* we only read the first bitplane here to create a black/white bitmap */
-
- for(z=0;z<depth;z++)
- {
- bitmap_ptr = bitmap_data + y * bytes_per_line;
- x = 0;
-
- if (!bitmap_header->Compression)
- {
- while(x++ < bytes_per_line)
- *bitmap_ptr++ |= MSBitFirst2LSBitFirst(*body_ptr++);
- }
- else
- {
- while(x < bytes_per_line)
- {
- byte_count = *body_ptr++;
-
- if (byte_count <= 128)
- {
- for(i=0;i<byte_count+1;i++)
- *bitmap_ptr++ |= MSBitFirst2LSBitFirst(*body_ptr++);
- x += byte_count + 1;
- }
- else
- {
- byte_value = *body_ptr++;
- for(i=0;i<257-byte_count;i++)
- *bitmap_ptr++ |= MSBitFirst2LSBitFirst(byte_value);
- x += 257 - byte_count;
- }
- }
- }
- }
- }
-
- bitmap_ptr = bitmap_data;
- for(i=0;i<bitmap_size;i++)
- *bitmap_ptr++ ^= 0xff;
-
- new_pixmap = XCreateBitmapFromData(display,root,bitmap_data,width,height);
-
- free(file_data);
- free(bitmap_data);
- free(bitmap_header);
-
- if (!new_pixmap)
- return(ILBM_NoMemory);
-
- *pixmap = new_pixmap;
- return(ILBM_Success);
-}
-#endif
+++ /dev/null
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back! *
-*----------------------------------------------------------*
-* (c) 1995-98 Artsoft Entertainment *
-* Holger Schemel *
-* Oststrasse 11a *
-* 33604 Bielefeld *
-* phone: ++49 +521 290471 *
-* email: aeglos@valinor.owl.de *
-*----------------------------------------------------------*
-* gfxload.h *
-***********************************************************/
-
-#ifndef GFXLOAD_H
-#define GFXLOAD_H
-
-#ifndef MSDOS
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-#define GIF_Success 0
-#define GIF_OpenFailed -1
-#define GIF_ReadFailed -2
-#define GIF_FileInvalid -3
-#define GIF_NoMemory -4
-#define GIF_ColorFailed -5
-
-#define ILBM_Success 0
-#define ILBM_OpenFailed -1
-#define ILBM_ReadFailed -2
-#define ILBM_FileInvalid -3
-#define ILBM_NoMemory -4
-#define ILBM_ColorFailed -5
-
-int Read_ILBM_to_Bitmap(Display *, char *, Pixmap *);
-int Read_GIF_to_Bitmap(Display *, char *, Pixmap *);
-int Read_GIF_to_Pixmap(Display *, char *, Pixmap *);
-int Read_GIF_to_XImage(Display *, char *, XImage **);
-
-#endif
-#endif
+++ /dev/null
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back! *
-*----------------------------------------------------------*
-* ©1995 Artsoft Development *
-* Holger Schemel *
-* 33659 Bielefeld-Senne *
-* Telefon: (0521) 493245 *
-* eMail: aeglos@valinor.owl.de *
-* aeglos@uni-paderborn.de *
-* q99492@pbhrzx.uni-paderborn.de *
-*----------------------------------------------------------*
-* gfxloader.c *
-***********************************************************/
-
-#include "gfxloader.h"
-
-
-
-
-
-
-extern Window window;
-extern void Delay(long);
-
-
-
-
-
-
-#ifdef DEBUG
-/*
-#define DEBUG_GIF
-#define DEBUG_ILBM
-*/
-#endif
-
-struct IFF_ILBM_FORM_big_endian
-{
- char magic_FORM[4];
- unsigned char chunk_size[4];
- char magic_ILBM[4];
-};
-
-struct IFF_ILBM_BMHD_big_endian
-{
- char Width[2], Height[2];
- char LeftEdge[2], TopEdge[2];
- char Depth;
- char Mask;
- char Compression;
- char pad1;
- char transparentColor[2];
- char xAspect, yAspect;
- char pageWidth[2], pageHeight[2];
-};
-
-struct IFF_ILBM_BMHD
-{
- unsigned int Width, Height;
- int LeftEdge, TopEdge;
- unsigned int Depth;
- unsigned int Mask;
- unsigned int Compression;
- unsigned char pad1;
- unsigned int transparentColor;
- unsigned int xAspect, yAspect;
- int pageWidth, pageHeight;
-};
-
-static int ConvertXImageDepth(Display *, XImage **);
-static int Read_GIF_to_Pixmap_or_Bitmap(Display *, char *, Pixmap *, int);
-
-#define READ_GIF_TO_BITMAP 0
-#define READ_GIF_TO_PIXMAP 1
-
-
-int Read_GIF_to_Bitmap(Display *display, char *filename, Pixmap *pixmap)
-{
- printf("Read_GIF_to_Bitmap\n");
-
-
-
-
- return(Read_GIF_to_Pixmap_or_Bitmap(display, filename,
- pixmap, READ_GIF_TO_BITMAP));
-}
-
-int Read_GIF_to_Pixmap(Display *display, char *filename, Pixmap *pixmap)
-{
- printf("Read_GIF_to_Pixmap\n");
-
-
-
-
- return(Read_GIF_to_Pixmap_or_Bitmap(display, filename,
- pixmap, READ_GIF_TO_PIXMAP));
-}
-
-int Read_GIF_to_Pixmap_or_Bitmap(Display *display, char *filename,
- Pixmap *pixmap, int mode)
-{
- XImage *image = NULL;
- Pixmap new_pixmap = 0;
- int return_code;
-
- *pixmap = 0;
- return_code = Read_GIF_to_XImage(display, filename, &image);
- if (return_code != GIF_Success)
- return(return_code);
-
- if (image)
- {
- int screen = DefaultScreen(display);
- Drawable root = RootWindow(display,screen);
- int depth = DefaultDepth(display, screen);
- int width = image->width;
- int height = image->height;
-
- if (mode == READ_GIF_TO_BITMAP)
- {
- int i,x,y;
- unsigned long black_pixel = BlackPixel(display,screen);
- int bytes_per_line = (width+7) / 8;
- int size = bytes_per_line * height;
- char *data, *ptr;
-
- data = (char *)malloc(size);
- if (!data)
- return(GIF_NoMemory);
-
- ptr = data;
- for(i=0;i<size;i++)
- *ptr++ = 0;
-
- for(y=0;y<height;y++)
- {
- for(x=0;x<width;x++)
- {
- if (XGetPixel(image,x,y) == black_pixel)
- data[y * bytes_per_line + x/8] |= (1 << (x%8));
- }
- }
-
- new_pixmap = XCreateBitmapFromData(display,root,data,width,height);
- free(data);
-
- if (!new_pixmap)
- return(GIF_NoMemory);
- }
- else
- {
- GC gc;
- XGCValues gcv;
-
- if (ConvertXImageDepth(display, &image) != GIF_Success)
- return(GIF_ColorFailed);
-
- new_pixmap = XCreatePixmap(display,root,width,height,depth);
-
- if (!new_pixmap)
- return(GIF_NoMemory);
-
- gcv.foreground = BlackPixel(display,screen);
- gcv.background = WhitePixel(display,screen);
- gc = XCreateGC(display, root, GCForeground | GCBackground, &gcv);
- XPutImage(display,new_pixmap,gc,image,0,0,0,0,width,height);
-
-
-
-
-
-
- Delay(1000000);
-
- XPutImage(display,window,gc,image,0,0,0,0,width,height);
-
- Delay(3000000);
-
-
-
-
-
- XFreeGC(display, gc);
- }
-
- XDestroyImage(image);
- }
-
- *pixmap = new_pixmap;
- return(return_code);
-}
-
-
-/*
- * Read_GIF_to_XImage() - based strongly on...
- *
- * xgifload.c - based strongly on...
- *
- * gif2ras.c - Converts from a Compuserve GIF (tm) image to a Sun Raster image.
- *
- * Copyright (c) 1988, 1989 by Patrick J. Naughton
- *
- * Author: Patrick J. Naughton
- * naughton@wind.sun.com
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation.
- *
- * This file is provided AS IS with no warranties of any kind. The author
- * shall have no liability with respect to the infringement of copyrights,
- * trade secrets or any patents by this file or any part thereof. In no
- * event will the author be liable for any lost revenue or profits or
- * other special, indirect and consequential damages.
- *
- */
-
-typedef int boolean;
-typedef unsigned char byte;
-
-static int ReadCode(void);
-static void AddToPixel(byte);
-static int ColorDicking(Display *);
-
-#define NEXTBYTE (*ptr++)
-#define IMAGESEP 0x2c
-#define INTERLACEMASK 0x40
-#define COLORMAPMASK 0x80
-
-static
-int BitOffset, /* Bit Offset of next code */
- XC, YC, /* Output X and Y coords of current pixel */
- Pass, /* Used by output routine if interlaced pic */
- OutCount, /* Decompressor output 'stack count' */
- RWidth, RHeight, /* screen dimensions */
- Width, Height, /* image dimensions */
- LeftOfs, TopOfs, /* image offset */
- BitsPerPixel, /* Bits per pixel, read from GIF header */
- BytesPerScanline, /* bytes per scanline in output raster */
- ColorMapSize, /* number of colors */
- Background, /* background color */
- CodeSize, /* Code size, read from GIF header */
- InitCodeSize, /* Starting code size, used during Clear */
- Code, /* Value returned by ReadCode */
- MaxCode, /* limiting value for current code size */
- ClearCode, /* GIF clear code */
- EOFCode, /* GIF end-of-information code */
- CurCode, OldCode, InCode, /* Decompressor variables */
- FirstFree, /* First free code, generated per GIF spec */
- FreeCode, /* Decompressor, next free slot in hash table*/
- FinChar, /* Decompressor variable */
- BitMask, /* AND mask for data size */
- ReadMask; /* Code AND mask for current code size */
-
-static boolean Interlace, HasColormap;
-
-static byte *ImageData; /* The result array */
-static byte *RawGIF; /* The heap array to hold it, raw */
-static byte *Raster; /* The raster data stream, unblocked */
-
-/* The color map, read from the GIF header */
-static byte Red[256], Green[256], Blue[256], used[256];
-static int numused;
-
-extern char *progname;
-
-static int numcols;
-static unsigned long cols[256];
-static XColor defs[256];
-
-int Read_GIF_to_XImage(Display *display, char *filename, XImage **image)
-{
- int filesize;
- register byte ch, ch1;
- register byte *ptr, *ptr1;
- register int i;
- int screen = DefaultScreen(display);
- Visual *visual = DefaultVisual(display,screen);
- XImage *new_image = NULL;
- char *id = "GIF87a";
- FILE *file;
- int Prefix[4096]; /* The hash table used by the decompressor */
- int Suffix[4096];
- int OutCode[1025]; /* An output array used by the decompressor */
-
- BitOffset = XC = YC = Pass = OutCount = 0;
- *image = NULL;
-
- if (strcmp(filename,"-")==0)
- {
- file = stdin;
- filename = "<stdin>";
- }
- else
- file = fopen(filename,"r");
-
- if (!file)
- return(GIF_OpenFailed);
-
- /* find the size of the file */
- fseek(file, 0L, 2);
- filesize = ftell(file);
- fseek(file, 0L, 0);
-
- if (!(ptr = RawGIF = (byte *) malloc(filesize)))
- return(GIF_NoMemory);
-
- if (!(Raster = (byte *) malloc(filesize)))
- return(GIF_NoMemory);
-
- if (fread(ptr, filesize, 1, file) != 1)
- return(GIF_ReadFailed);
-
- if (strncmp(ptr, id, 6))
- return(GIF_FileInvalid);
-
- ptr += 6;
-
- /* Get variables from the GIF screen descriptor */
-
- ch = NEXTBYTE;
- RWidth = ch + 0x100 * NEXTBYTE; /* screen dimensions... not used. */
- ch = NEXTBYTE;
- RHeight = ch + 0x100 * NEXTBYTE;
-
- ch = NEXTBYTE;
- HasColormap = ((ch & COLORMAPMASK) ? True : False);
-
- BitsPerPixel = (ch & 7) + 1;
- numcols = ColorMapSize = 1 << BitsPerPixel;
- BitMask = ColorMapSize - 1;
-
- Background = NEXTBYTE; /* background color... not used. */
-
- if (NEXTBYTE) /* supposed to be NULL */
- return(GIF_FileInvalid);
-
- /* Read in global colormap. */
-
- if (HasColormap)
- {
- for (i = 0; i < ColorMapSize; i++)
- {
- Red[i] = NEXTBYTE;
- Green[i] = NEXTBYTE;
- Blue[i] = NEXTBYTE;
- used[i] = 0;
- }
- numused = 0;
- }
- else
- {
- /* no colormap in GIF file */
- fprintf(stderr,"%s: warning! no colortable in this file. Winging it.\n",
- progname);
- if (!numcols)
- numcols=256;
- for (i=0; i<numcols; i++)
- cols[i] = (unsigned long) i;
- }
-
- /* Check for image seperator */
-
- if (NEXTBYTE != IMAGESEP)
- return(GIF_FileInvalid);
-
- /* Now read in values from the image descriptor */
-
- ch = NEXTBYTE;
- LeftOfs = ch + 0x100 * NEXTBYTE;
- ch = NEXTBYTE;
- TopOfs = ch + 0x100 * NEXTBYTE;
- ch = NEXTBYTE;
- Width = ch + 0x100 * NEXTBYTE;
- ch = NEXTBYTE;
- Height = ch + 0x100 * NEXTBYTE;
- Interlace = ((NEXTBYTE & INTERLACEMASK) ? True : False);
-
-#ifdef DEBUG_GIF
- fprintf(stderr, "%s:\n", filename);
- fprintf(stderr, " %dx%d, %d bpp / %d colors, %sinterlaced\n",
- Width,Height, BitsPerPixel,ColorMapSize,(Interlace ? "" : "non-"));
- fprintf(stderr, " Reading file... ");
-#endif
-
- /* Note that I ignore the possible existence of a local color map.
- * I'm told there aren't many files around that use them, and the spec
- * says it's defined for future use. This could lead to an error
- * reading some files.
- */
-
- /* Start reading the raster data. First we get the intial code size
- * and compute decompressor constant values, based on this code size.
- */
-
- CodeSize = NEXTBYTE;
- ClearCode = (1 << CodeSize);
- EOFCode = ClearCode + 1;
- FreeCode = FirstFree = ClearCode + 2;
-
- /* The GIF spec has it that the code size is the code size used to
- * compute the above values is the code size given in the file, but the
- * code size used in compression/decompression is the code size given in
- * the file plus one. (thus the ++).
- */
-
- CodeSize++;
- InitCodeSize = CodeSize;
- MaxCode = (1 << CodeSize);
- ReadMask = MaxCode - 1;
-
- /* Read the raster data. Here we just transpose it from the GIF array
- * to the Raster array, turning it from a series of blocks into one long
- * data stream, which makes life much easier for ReadCode().
- */
-
- ptr1 = Raster;
- do
- {
- ch = ch1 = NEXTBYTE;
- while (ch--) *ptr1++ = NEXTBYTE;
- if ((Raster - ptr1) > filesize)
- return(GIF_FileInvalid);
- }
- while(ch1);
-
- free(RawGIF); /* We're done with the raw data now... */
-
-#ifdef DEBUG_GIF
- fprintf(stderr, "done\n");
- fprintf(stderr, " Decompressing... ");
-#endif
-
- /* Allocate the X Image */
- ImageData = (byte *) malloc(Width*Height);
- if (!ImageData)
- return(GIF_NoMemory);
-
- new_image = XCreateImage(display,visual,8,ZPixmap,0,ImageData,
- Width,Height,8,Width);
- if (!new_image)
- return(GIF_NoMemory);
-
- BytesPerScanline = Width;
-
-
- /* Decompress the file, continuing until you see the GIF EOF code.
- * One obvious enhancement is to add checking for corrupt files here.
- */
-
- Code = ReadCode();
- while (Code != EOFCode)
- {
- /* Clear code sets everything back to its initial value, then reads the
- * immediately subsequent code as uncompressed data.
- */
-
- if (Code == ClearCode)
- {
- CodeSize = InitCodeSize;
- MaxCode = (1 << CodeSize);
- ReadMask = MaxCode - 1;
- FreeCode = FirstFree;
- CurCode = OldCode = Code = ReadCode();
- FinChar = CurCode & BitMask;
- AddToPixel(FinChar);
- }
- else
- {
- /* If not a clear code, then must be data:
- * save same as CurCode and InCode
- */
-
- CurCode = InCode = Code;
-
- /* If greater or equal to FreeCode, not in the hash table yet;
- * repeat the last character decoded
- */
-
- if (CurCode >= FreeCode)
- {
- CurCode = OldCode;
- OutCode[OutCount++] = FinChar;
- }
-
- /* Unless this code is raw data, pursue the chain pointed to by CurCode
- * through the hash table to its end; each code in the chain puts its
- * associated output code on the output queue.
- */
-
- while (CurCode > BitMask)
- {
- if (OutCount > 1024)
- return(GIF_FileInvalid);
-
- OutCode[OutCount++] = Suffix[CurCode];
- CurCode = Prefix[CurCode];
- }
-
- /* The last code in the chain is treated as raw data. */
-
- FinChar = CurCode & BitMask;
- OutCode[OutCount++] = FinChar;
-
- /* Now we put the data out to the Output routine.
- * It's been stacked LIFO, so deal with it that way...
- */
-
- for (i = OutCount - 1; i >= 0; i--)
- AddToPixel(OutCode[i]);
- OutCount = 0;
-
- /* Build the hash table on-the-fly. No table is stored in the file. */
-
- Prefix[FreeCode] = OldCode;
- Suffix[FreeCode] = FinChar;
- OldCode = InCode;
-
- /* Point to the next slot in the table. If we exceed the current
- * MaxCode value, increment the code size unless it's already 12. If it
- * is, do nothing: the next code decompressed better be CLEAR
- */
-
- FreeCode++;
- if (FreeCode >= MaxCode)
- {
- if (CodeSize < 12)
- {
- CodeSize++;
- MaxCode *= 2;
- ReadMask = (1 << CodeSize) - 1;
- }
- }
- }
- Code = ReadCode();
- }
-
- free(Raster);
-
-#ifdef DEBUG_GIF
- fprintf(stderr, "done\n");
- fprintf(stderr," %d colors used\n",numused);
-#endif
-
- if (file != stdin)
- fclose(file);
-
- if (ColorDicking(display) != GIF_Success)
- return(GIF_ColorFailed);
-
- *image = new_image;
- return(GIF_Success);
-}
-
-
-/* Fetch the next code from the raster data stream. The codes can be
- * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
- * maintain our location in the Raster array as a BIT Offset. We compute
- * the byte Offset into the raster array by dividing this by 8, pick up
- * three bytes, compute the bit Offset into our 24-bit chunk, shift to
- * bring the desired code to the bottom, then mask it off and return it.
- */
-
-static int ReadCode()
-{
- int RawCode, ByteOffset;
-
- ByteOffset = BitOffset / 8;
- RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]);
- if (CodeSize >= 8)
- RawCode += (0x10000 * Raster[ByteOffset + 2]);
- RawCode >>= (BitOffset % 8);
- BitOffset += CodeSize;
- return(RawCode & ReadMask);
-}
-
-
-static void AddToPixel(byte Index)
-{
- if (YC<Height)
- *(ImageData + YC * BytesPerScanline + XC) = Index;
-
- if (!used[Index])
- {
- used[Index]=1;
- numused++;
- }
-
- /* Update the X-coordinate, and if it overflows, update the Y-coordinate */
-
- if (++XC == Width)
- {
- /* If a non-interlaced picture, just increment YC to the next scan line.
- * If it's interlaced, deal with the interlace as described in the GIF
- * spec. Put the decoded scan line out to the screen if we haven't gone
- * past the bottom of it
- */
-
- XC = 0;
- if (!Interlace)
- YC++;
- else
- {
- switch (Pass)
- {
- case 0:
- YC += 8;
- if (YC >= Height)
- {
- Pass++;
- YC = 4;
- }
- break;
-
- case 1:
- YC += 8;
- if (YC >= Height)
- {
- Pass++;
- YC = 2;
- }
- break;
-
- case 2:
- YC += 4;
- if (YC >= Height)
- {
- Pass++;
- YC = 1;
- }
- break;
-
- case 3:
- YC += 2;
- break;
-
- default:
- break;
- }
- }
- }
-}
-
-
-static int ColorDicking(Display *display)
-{
- /* we've got the picture loaded, we know what colors are needed. get 'em */
-
- register int i,j;
- static byte lmasks[8] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80};
- byte lmask, *ptr;
- int screen = DefaultScreen(display);
- Colormap cmap = DefaultColormap(display,screen);
- int dispcells = DisplayCells(display,screen);
-
- int strip = 0;
- int nostrip = 0;
-
- if (!HasColormap)
- return(GIF_Success);
- /* no need to allocate any colors if no colormap in GIF file */
-
- /* Allocate the X colors for this picture */
-
- if (nostrip)
- {
- /* nostrip was set. try REAL hard to do it */
- for (i=j=0; i<numcols; i++)
- {
- if (used[i])
- {
- defs[i].red = Red[i]<<8;
- defs[i].green = Green[i]<<8;
- defs[i].blue = Blue[i]<<8;
- defs[i].flags = DoRed | DoGreen | DoBlue;
- if (!XAllocColor(display,cmap,&defs[i]))
- {
- j++;
- defs[i].pixel = 0xffff;
- }
- cols[i] = defs[i].pixel;
- }
- }
-
- if (j)
- {
- /* failed to pull it off */
-
- XColor ctab[256];
- int dc;
-
- dc = (dispcells<256) ? dispcells : 256;
-
- fprintf(stderr,
- "failed to allocate %d out of %d colors. Trying extra hard.\n",
- j,numused);
-
- /* read in the color table */
- for (i=0; i<dc; i++)
- ctab[i].pixel = i;
- XQueryColors(display,cmap,ctab,dc);
-
- /* run through the used colors. any used color that has a pixel
- value of 0xffff wasn't allocated. for such colors, run through
- the entire X colormap and pick the closest color */
-
- for (i=0; i<numcols; i++)
- if (used[i] && cols[i]==0xffff)
- {
- /* an unallocated pixel */
-
- int d, mdist, close;
- unsigned long r,g,b;
-
- mdist = 100000; close = -1;
- r = Red[i];
- g = Green[i];
- b = Blue[i];
- for (j=0; j<dc; j++)
- {
- d = abs(r - (ctab[j].red>>8)) +
- abs(g - (ctab[j].green>>8)) +
- abs(b - (ctab[j].blue>>8));
- if (d<mdist)
- {
- mdist=d;
- close=j;
- }
- }
-
- if (close<0)
- return(GIF_ColorFailed);
-
- bcopy(&defs[close],&defs[i],sizeof(XColor));
- cols[i] = ctab[close].pixel;
- }
- } /* end 'failed to pull it off' */
- }
- else
- {
- /* strip wasn't set, do the best auto-strip */
-
- j = 0;
- while (strip<8)
- {
- lmask = lmasks[strip];
- for (i=0; i<numcols; i++)
- {
- if (used[i])
- {
- defs[i].red = (Red[i] &lmask)<<8;
- defs[i].green = (Green[i]&lmask)<<8;
- defs[i].blue = (Blue[i] &lmask)<<8;
- defs[i].flags = DoRed | DoGreen | DoBlue;
- if (!XAllocColor(display,cmap,&defs[i]))
- break;
- cols[i] = defs[i].pixel;
- }
- }
-
- if (i<numcols)
- {
- /* failed */
- strip++;
- j++;
- for (i--; i>=0; i--)
- if (used[i])
- XFreeColors(display,cmap,cols+i,1,0L);
- }
- else
- break;
- }
-
-#ifdef DEBUG_GIF
- if (j && strip<8)
- fprintf(stderr,"%s: stripped %d bits\n",progname,strip);
-#endif
-
- if (strip==8)
- {
- fprintf(stderr,"UTTERLY failed to allocate the desired colors.\n");
- for (i=0; i<numcols; i++) cols[i]=i;
- }
- }
-
- ptr = ImageData;
- for (i=0; i<Height; i++)
- for (j=0; j<Width; j++,ptr++)
- *ptr = (byte) cols[*ptr];
-
- return(GIF_Success);
-}
-
-
-/******************************************************************************
- * This makes sure the display's depth is the same as the
- * depth of the default 8 bit image. If not, we build a new image
- * that has the correct depth. This works on the fact that
- * the color mapper has already changed every pixel value in the
- * image into the proper number of bits (to fit into the pallet)
- * so we can just chop down the number of bits.
- * This changes the global variable 'expImage' if necessary.
- */
-
-static int ConvertXImageDepth(Display *display, XImage **image)
-{
- int screen = DefaultScreen(display);
- int depth = DefaultDepth(display, screen);
-
-
-
-
-
-
- printf("ConvertXImageDepth:\n");
- printf("(*image)->depth == %d\n",
- (*image)->depth);
- printf("DefaultDepth(display, screen) == %d\n",
- DefaultDepth(display, screen));
-
-
-
-
- if ((*image)->depth != depth)
- {
- XImage *old_image, *new_image;
- /*
- Visual *visual = DefaultVisual(display,screen);
- */
- int width = (*image)->width;
- int height = (*image)->height;
- register int dwx, dwy;
- byte *data;
-
-
-
-
-
- printf("ConvertXImageDepth: ---------> CONVERTING...\n");
-
-
-
-
-
-
- data = (byte *)malloc(width * height * depth);
- old_image = *image;
-
- /*
- new_image = XCreateImage(display,visual,depth,
- ZPixmap,0,data,width,height,8,0);
- */
-
- new_image = XGetImage(display,RootWindow(display,screen),
- 0,0,width,height,0xffffffff,ZPixmap);
-
-
- if (!new_image)
- return(GIF_NoMemory);
-
- if (old_image->depth == 8 && new_image->depth == 4)
- {
- /* speedup for the most common format change */
-
- register byte *sptr = (byte *)old_image->data;
- register byte *dptr = (byte *)new_image->data;
-
- for (dwy=1; dwy<=height; dwy++)
- {
- for (dwx=1; dwx<width; dwx+=2)
- {
- *dptr = (*sptr) | (*(sptr+1)<<4);
- dptr++;
- sptr+=2;
- }
- if (width & 1)
- {
- /* if extra pixal at end of line, just move it */
- *dptr = *sptr;
- sptr++; dptr++;
- }
- }
- }
- else /* other format change than 8 bit -> 4 bit */
- {
- unsigned long pixel_value;
-
- for (dwx=0; dwx<width; dwx++)
- {
- for (dwy=0; dwy<height; dwy++)
- {
- pixel_value = XGetPixel(old_image, dwx, dwy);
-
- if (pixel_value > 0xff)
- printf("pixel = %lx", pixel_value);
-
- XPutPixel(new_image, dwx, dwy, pixel_value);
- }
- }
- }
-
- free(old_image->data);
- old_image->data = NULL;
- XDestroyImage(old_image);
-
- *image = new_image;
- }
-
- return(GIF_Success);
-}
-
-
-static unsigned long be2long(unsigned char *be) /* big-endian -> long int */
-{
- return((be[0]<<24) | (be[1]<<16) | (be[2]<<8) | be[3]);
-}
-
-static unsigned short be2short(unsigned char *be) /* big-endian -> short int */
-{
- return((be[0]<<8) | be[1]);
-}
-
-static struct IFF_ILBM_BMHD *ConvertBMHD(unsigned char *header_data)
-{
- struct IFF_ILBM_BMHD_big_endian *bmhd_be;
- struct IFF_ILBM_BMHD *bmhd;
-
- bmhd_be = (struct IFF_ILBM_BMHD_big_endian *)header_data;
- bmhd = (struct IFF_ILBM_BMHD *)malloc(sizeof(struct IFF_ILBM_BMHD));
- if (!bmhd)
- return(NULL);
-
- bmhd->Width = be2short(bmhd_be->Width);
- bmhd->Height = be2short(bmhd_be->Height);
- bmhd->LeftEdge = be2short(bmhd_be->LeftEdge);
- bmhd->TopEdge = be2short(bmhd_be->TopEdge);
- bmhd->Depth = (int)bmhd_be->Depth;
- bmhd->Mask = (int)bmhd_be->Mask;
- bmhd->Compression = (int)bmhd_be->Compression;
- bmhd->pad1 = bmhd_be->pad1;
- bmhd->transparentColor = be2short(bmhd_be->transparentColor);
- bmhd->xAspect = (int)bmhd_be->xAspect;
- bmhd->yAspect = (int)bmhd_be->yAspect;
- bmhd->pageWidth = be2short(bmhd_be->pageWidth);
- bmhd->pageHeight = be2short(bmhd_be->pageHeight);
-
- return(bmhd);
-}
-
-static unsigned char MSBitFirst2LSBitFirst(unsigned char msb_byte)
-{
- unsigned char lsb_byte = 0;
- int i;
-
- for(i=7;i>=0;i--)
- {
- lsb_byte |= (msb_byte & 1) << i;
- msb_byte >>= 1;
- }
-
- return(lsb_byte);
-}
-
-int Read_ILBM_to_Bitmap(Display *display, char *filename, Pixmap *pixmap)
-{
- Pixmap new_pixmap = 0;
- int screen = DefaultScreen(display);
- Drawable root = RootWindow(display,screen);
- struct IFF_ILBM_FORM_big_endian *form_header;
- struct IFF_ILBM_BMHD *bitmap_header;
- unsigned long file_len, body_len;
- unsigned char *file_data, *bitmap_data;
- unsigned char *file_ptr, *bitmap_ptr, *body_ptr;
- unsigned char byte_count, byte_value;
- int i,x,y,z;
- int width, height, depth;
- int bytes_per_line, bitmap_size;
- FILE *file;
-
-
-
-
-
- printf("Read_ILBM_to_Bitmap\n");
-
-
-
-
- if (!(file = fopen(filename,"r")))
- return(ILBM_OpenFailed);
-
- if (fseek(file,0,SEEK_END) < 0)
- {
- fclose(file);
- return(ILBM_ReadFailed);
- }
-
- file_len = ftell(file);
- rewind(file);
-
- if (!(file_data = (unsigned char *)malloc(file_len)))
- {
- fclose(file);
- return(ILBM_NoMemory);
- }
-
- if (fread(file_data,1,file_len,file) != file_len)
- {
- free(file_data);
- fclose(file);
- return(ILBM_ReadFailed);
- }
-
- fclose(file);
-
- form_header = (struct IFF_ILBM_FORM_big_endian *)file_data;
-
- if (strncmp(form_header->magic_FORM,"FORM",4) ||
- file_len != be2long(form_header->chunk_size)+8 ||
- strncmp(form_header->magic_ILBM,"ILBM",4))
- {
-#ifdef DEBUG_ILBM
- printf("%s: IFF chunk 'FORM' and/or 'ILBM' not found.\n",filename);
-#endif
- free(file_data);
- return(ILBM_FileInvalid);
- }
-
- bitmap_header = NULL;
- body_ptr = NULL;
- file_ptr = file_data + 12;
-
- while(file_ptr < (unsigned char *)(file_data + file_len))
- {
- if (!strncmp(file_ptr,"BMHD",4))
- {
-#ifdef DEBUG_ILBM
- printf("%s: IFF chunk 'BMHD' found.\n",filename);
-#endif
- bitmap_header = ConvertBMHD(file_ptr + 8);
- file_ptr += be2long(file_ptr + 4) + 8;
- continue;
- }
- else if (!strncmp(file_ptr,"BODY",4))
- {
-#ifdef DEBUG_ILBM
- printf("%s: IFF chunk 'BODY' found.\n",filename);
-#endif
- body_ptr = file_ptr + 8;
- body_len = be2long(file_ptr + 4);
- file_ptr += be2long(file_ptr + 4) + 8;
- continue;
- }
- else
- {
-#ifdef DEBUG_ILBM
- printf("%s: IFF chunk '%c%c%c%c' found (but not used).\n",filename,
- file_ptr[0],file_ptr[1],file_ptr[2],file_ptr[3]);
-#endif
- /* other chunk not recognized here */
- file_ptr += be2long(file_ptr + 4) + 8;
- continue;
- }
- }
-
- if (!bitmap_header || !body_ptr)
- {
-#ifdef DEBUG_ILBM
- printf("%s: IFF chunk 'BMHD' and/or 'BODY' not found.\n",filename);
-#endif
- free(file_data);
- return(ILBM_FileInvalid);
- }
-
- width = bitmap_header->Width;
- height = bitmap_header->Height;
- depth = bitmap_header->Depth;
-
-#ifdef DEBUG_ILBM
- if (depth > 1)
- printf("%s: %d bitplanes found; using only the first plane.\n",
- filename,depth);
-#endif
-
- bytes_per_line = ((width + 15) / 16) * 2;
- bitmap_size = bytes_per_line * height;
-
- bitmap_data = (char *)malloc(bitmap_size);
- if (!bitmap_data)
- {
- free(file_data);
- free(bitmap_header);
- return(ILBM_NoMemory);
- }
-
- bitmap_ptr = bitmap_data;
- for(i=0;i<bitmap_size;i++)
- *bitmap_ptr++ = 0;
-
- for(y=0;y<height;y++)
- {
- /* we only read the first bitplane here to create a black/white bitmap */
-
- for(z=0;z<depth;z++)
- {
- bitmap_ptr = bitmap_data + y * bytes_per_line;
- x = 0;
-
- if (!bitmap_header->Compression)
- {
- while(x++ < bytes_per_line)
- *bitmap_ptr++ |= MSBitFirst2LSBitFirst(*body_ptr++);
- }
- else
- {
- while(x < bytes_per_line)
- {
- byte_count = *body_ptr++;
-
- if (byte_count <= 128)
- {
- for(i=0;i<byte_count+1;i++)
- *bitmap_ptr++ |= MSBitFirst2LSBitFirst(*body_ptr++);
- x += byte_count + 1;
- }
- else
- {
- byte_value = *body_ptr++;
- for(i=0;i<257-byte_count;i++)
- *bitmap_ptr++ |= MSBitFirst2LSBitFirst(byte_value);
- x += 257 - byte_count;
- }
- }
- }
- }
- }
-
- bitmap_ptr = bitmap_data;
- for(i=0;i<bitmap_size;i++)
- *bitmap_ptr++ ^= 0xff;
-
- new_pixmap = XCreateBitmapFromData(display,root,bitmap_data,width,height);
-
- free(file_data);
- free(bitmap_data);
- free(bitmap_header);
-
- if (!new_pixmap)
- return(ILBM_NoMemory);
-
- *pixmap = new_pixmap;
- return(ILBM_Success);
-}
+++ /dev/null
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back! *
-*----------------------------------------------------------*
-* ©1995 Artsoft Development *
-* Holger Schemel *
-* 33659 Bielefeld-Senne *
-* Telefon: (0521) 493245 *
-* eMail: aeglos@valinor.owl.de *
-* aeglos@uni-paderborn.de *
-* q99492@pbhrzx.uni-paderborn.de *
-*----------------------------------------------------------*
-* gfxloader.h *
-***********************************************************/
-
-#ifndef GFXLOADER_H
-#define GFXLOADER_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-#define GIF_Success 0
-#define GIF_OpenFailed -1
-#define GIF_ReadFailed -2
-#define GIF_FileInvalid -3
-#define GIF_NoMemory -4
-#define GIF_ColorFailed -5
-
-#define ILBM_Success 0
-#define ILBM_OpenFailed -1
-#define ILBM_ReadFailed -2
-#define ILBM_FileInvalid -3
-#define ILBM_NoMemory -4
-#define ILBM_ColorFailed -5
-
-int Read_ILBM_to_Bitmap(Display *, char *, Pixmap *);
-int Read_GIF_to_Bitmap(Display *, char *, Pixmap *);
-int Read_GIF_to_Pixmap(Display *, char *, Pixmap *);
-int Read_GIF_to_XImage(Display *, char *, XImage **);
-
-#endif
+++ /dev/null
-
-/* gif.c */
-
-#define GIF_C
-
-#include "gif.h"
-#include "image.h"
-
-#define PUSH_PIXEL(p) \
-{ \
- if (pstk_idx == PSTK_SIZE) \
- return GIFIN_ERR_PSO; \
- else \
- pstk[pstk_idx++] = (p); \
-}
-
-/*
- * push a string (denoted by a code) onto the pixel stack
- * (returns the code of the first pixel in the string in ps_rslt)
- */
-
-int ps_rslt; /* return result */
-
-#define GIFIN_PUSH_STRING(code) \
-{ \
- int ps_code; \
- ps_code = code; \
- \
- while (((unsigned int)ps_code) < STAB_SIZE && prefix[ps_code] != NULL_CODE) \
- { \
- PUSH_PIXEL(extnsn[ps_code]); \
- ps_code = prefix[ps_code]; \
- } \
- \
- if (((unsigned int)ps_code) >= STAB_SIZE) \
- return GIFIN_ERR_TAO; \
- PUSH_PIXEL(extnsn[ps_code]); \
- ps_rslt = extnsn[ps_code]; \
- if (((unsigned int)ps_rslt) >= STAB_SIZE) \
- return GIFIN_ERR_TAO; \
-}
-
-/*
- * Look up the ascii message coresponding to
- * the error number.
- */
-static char *get_err_string(int errno)
-{
- int i;
- for (i=0;gif_err_strings[i].err_no != 0;i++)
- {
- if (gif_err_strings[i].err_no == errno)
- return gif_err_strings[i].name;
- }
- return "";
-}
-
-
-static int interlace_start[4] = /* start line for interlacing */
-{
- 0, 4, 2, 1
-};
-
-static int interlace_rate[4] = /* rate at which we accelerate vertically */
-{
- 8, 8, 4, 2
-};
-
-static BYTE file_open = 0; /* status flags */
-static BYTE image_open = 0;
-
-static FILE *ins; /* input stream */
-
-static int root_size; /* root code size */
-static int clr_code; /* clear code */
-static int eoi_code; /* end of information code */
-static int code_size; /* current code size */
-static int code_mask; /* current code mask */
-static int prev_code; /* previous code */
-
-static long work_data; /* working bit buffer */
-static int work_bits; /* working bit count */
-
-static BYTE buf[256]; /* byte buffer */
-static int buf_cnt; /* byte count */
-static int buf_idx; /* buffer index */
-
-static int table_size; /* string table size */
-static int prefix[STAB_SIZE]; /* string table : prefixes */
-static int extnsn[STAB_SIZE]; /* string table : extensions */
-
-static BYTE pstk[PSTK_SIZE]; /* pixel stack */
-static int pstk_idx; /* pixel stack pointer */
-
-
-static int gifin_rast_width; /* raster width */
-static int gifin_rast_height; /* raster height */
-static BYTE gifin_g_cmap_flag; /* global colormap flag */
-static int gifin_g_pixel_bits; /* bits per pixel, global colormap */
-static int gifin_g_ncolors; /* number of colors, global colormap */
-static BYTE gifin_g_cmap[3][256]; /* global colormap */
-static BYTE gifin_g_cmap_sorted; /* global colormap sorted (GIF89a only) */
-static int gifin_bg_color; /* background color index */
-static int gifin_color_bits; /* bits of color resolution */
-static double gifin_aspect; /* pixel aspect ratio (width/height) */
-static int gifin_version; /* gif file version */
-
-static int gifin_img_left; /* image position on raster */
-static int gifin_img_top; /* image position on raster */
-static int gifin_img_width; /* image width */
-static int gifin_img_height; /* image height */
-static BYTE gifin_l_cmap_flag; /* local colormap flag */
-static int gifin_l_pixel_bits; /* bits per pixel, local colormap */
-static int gifin_l_ncolors; /* number of colors, local colormap */
-static BYTE gifin_l_cmap[3][256]; /* local colormap */
-static BYTE gifin_interlace_flag; /* interlace image format flag */
-
-/*
- * open a GIF file, using s as the input stream
- */
-
-static int gifin_open_file(FILE *s)
-{
- int errno;
- /* make sure there isn't already a file open */
- if (file_open)
- return GIFIN_ERR_FAO;
-
- /* remember that we've got this file open */
- file_open = 1;
- ins = s;
-
- /* check GIF signature */
- if (fread(buf, 1, GIF_SIG_LEN, ins) != GIF_SIG_LEN)
- return GIFIN_ERR_EOF;
-
- buf[GIF_SIG_LEN] = '\0';
- if (strcmp((char *) buf, GIF_SIG) == 0)
- gifin_version = GIF87a;
- else if (strcmp((char *) buf, GIF_SIG_89) == 0)
- gifin_version = GIF89a;
- else
- return GIFIN_ERR_BAD_SIG;
-
- /* read screen descriptor */
- if (fread(buf, 1, GIF_SD_SIZE, ins) != GIF_SD_SIZE)
- return GIFIN_ERR_EOF;
-
- /* decode screen descriptor */
- gifin_rast_width = (buf[1] << 8) + buf[0];
- gifin_rast_height = (buf[3] << 8) + buf[2];
- gifin_g_cmap_flag = (buf[4] & 0x80) ? 1 : 0;
- gifin_color_bits = (((int)(buf[4] & 0x70)) >> 4) + 1;
- gifin_g_pixel_bits = (buf[4] & 0x07) + 1;
- gifin_bg_color = buf[5];
- gifin_aspect = 1.0;
-
- if (gifin_version == GIF87a)
- {
- if (buf[4] & 0x08 || buf[6] != 0)
- return GIFIN_ERR_BAD_SD;
- }
- else
- {
- gifin_g_cmap_sorted = ((buf[4] & 0x08) != 0);
- if (buf[6] != 0)
- gifin_aspect = ((double)buf[6] + 15.0) / 64.0;
- }
-
- /* load global colormap */
- if (gifin_g_cmap_flag)
- {
- gifin_g_ncolors = (1 << gifin_g_pixel_bits);
-
- if ((errno = gifin_load_cmap(gifin_g_cmap, gifin_g_ncolors)) != GIFIN_SUCCESS)
- return errno;
- }
- else
- {
- gifin_g_ncolors = 0;
- }
-
- /* done! */
- return GIFIN_SUCCESS;
-}
-
-
-/*
- * open next GIF image in the input stream; returns GIFIN_SUCCESS if
- * successful. if there are no more images, returns GIFIN_DONE. (might
- * also return various GIFIN_ERR codes.)
- */
-
-static int gifin_open_image()
-{
- int i;
- int separator;
- int errno;
-
- /* make sure there's a file open */
- if (!file_open)
- return GIFIN_ERR_NFO;
-
- /* make sure there isn't already an image open */
- if (image_open)
- return GIFIN_ERR_IAO;
-
- /* remember that we've got this image open */
- image_open = 1;
-
- /* skip over any extension blocks */
- do
- {
- separator = fgetc(ins);
- if (separator == GIF_EXTENSION)
- {
- if ((errno = gifin_skip_extension()) != GIFIN_SUCCESS)
- return errno;
- }
- }
- while (separator == GIF_EXTENSION);
-
- /* check for end of file marker */
- if (separator == GIF_TERMINATOR)
- return GIFIN_DONE;
-
- /* make sure we've got an image separator */
- if (separator != GIF_SEPARATOR)
- return GIFIN_ERR_BAD_SEP;
-
- /* read image descriptor */
- if (fread(buf, 1, GIF_ID_SIZE, ins) != GIF_ID_SIZE)
- return GIFIN_ERR_EOF;
-
- /* decode image descriptor */
- gifin_img_left = (buf[1] << 8) + buf[0];
- gifin_img_top = (buf[3] << 8) + buf[2];
- gifin_img_width = (buf[5] << 8) + buf[4];
- gifin_img_height = (buf[7] << 8) + buf[6];
- gifin_l_cmap_flag = (buf[8] & 0x80) ? 1 : 0;
- gifin_interlace_flag = (buf[8] & 0x40) ? 1 : 0;
- gifin_l_pixel_bits = (buf[8] & 0x07) + 1;
-
- /* load local colormap */
- if (gifin_l_cmap_flag)
- {
- gifin_l_ncolors = (1 << gifin_l_pixel_bits);
-
- if ((errno = gifin_load_cmap(gifin_l_cmap, gifin_l_ncolors)) != GIFIN_SUCCESS)
- return errno;
- }
- else
- {
- gifin_l_ncolors = 0;
- }
-
- /* initialize raster data stream decoder */
- root_size = fgetc(ins);
- clr_code = 1 << root_size;
- eoi_code = clr_code + 1;
- code_size = root_size + 1;
- code_mask = (1 << code_size) - 1;
- work_bits = 0;
- work_data = 0;
- buf_cnt = 0;
- buf_idx = 0;
-
- /* initialize string table */
- for (i=0; i<STAB_SIZE; i++)
- {
- prefix[i] = NULL_CODE;
- extnsn[i] = i;
- }
-
- /* initialize pixel stack */
- pstk_idx = 0;
-
- /* done! */
- return GIFIN_SUCCESS;
-}
-
-/*
- * try to read next pixel from the raster, return result in *pel
- */
-
-static int gifin_get_pixel(pel)
- int *pel;
-{
- int code;
- int first;
- int place;
- int errno;
-
- /* decode until there are some pixels on the pixel stack */
- while (pstk_idx == 0)
- {
- /* load bytes until we have enough bits for another code */
- while (work_bits < code_size)
- {
- if (buf_idx == buf_cnt)
- {
- /* read a new data block */
- if ((errno = gifin_read_data_block()) != GIFIN_SUCCESS)
- return errno;
-
- if (buf_cnt == 0)
- return GIFIN_ERR_EOD;
- }
-
- work_data |= ((long) buf[buf_idx++]) << work_bits;
- work_bits += 8;
- }
-
- /* get the next code */
- code = work_data & code_mask;
- work_data >>= code_size;
- work_bits -= code_size;
-
- /* interpret the code */
- if (code == clr_code)
- {
- /* reset decoder stream */
- code_size = root_size + 1;
- code_mask = (1 << code_size) - 1;
- prev_code = NULL_CODE;
- table_size = eoi_code + 1;
- }
- else if (code == eoi_code)
- {
- /* Ooops! no more pixels */
- return GIFIN_ERR_EOF;
- }
- else if (prev_code == NULL_CODE)
- {
- GIFIN_PUSH_STRING(code);
- prev_code = code;
- }
- else
- {
- if (code < table_size)
- {
- GIFIN_PUSH_STRING(code);
- first = ps_rslt;
- }
- else
- {
- place = pstk_idx;
- PUSH_PIXEL(NULL_CODE);
- GIFIN_PUSH_STRING(prev_code);
- first = ps_rslt;
- pstk[place] = first;
- }
-
- if ((errno = gifin_add_string(prev_code, first)) != GIFIN_SUCCESS)
- return errno;
- prev_code = code;
- }
- }
-
- /* pop a pixel off the pixel stack */
- *pel = (int) pstk[--pstk_idx];
-
- /* done! */
- return GIFIN_SUCCESS;
-}
-
-/*
- * close an open GIF file
- */
-
-static int gifin_close_file()
-{
- /* make sure there's a file open */
- if (!file_open)
- return GIFIN_ERR_NFO;
-
- /* mark file (and image) as closed */
- file_open = 0;
- image_open = 0;
-
- /* done! */
- return GIFIN_SUCCESS;
-}
-
-/*
- * load a colormap from the input stream
- */
-
-static int gifin_load_cmap(BYTE cmap[3][256], int ncolors)
-{
- int i;
-
- for (i=0; i<ncolors; i++)
- {
- if (fread(buf, 1, 3, ins) != 3)
- return GIFIN_ERR_EOF;
-
- cmap[GIF_RED][i] = buf[GIF_RED];
- cmap[GIF_GRN][i] = buf[GIF_GRN];
- cmap[GIF_BLU][i] = buf[GIF_BLU];
- }
-
- /* done! */
- return GIFIN_SUCCESS;
-}
-
-/*
- * skip an extension block in the input stream
- */
-
-static int gifin_skip_extension()
-{
- int errno;
-
- /* get the extension function byte */
- fgetc(ins);
-
- /* skip any remaining raster data */
- do
- {
- if ((errno = gifin_read_data_block()) != GIFIN_SUCCESS)
- return errno;
- }
- while (buf_cnt > 0);
-
- /* done! */
- return GIFIN_SUCCESS;
-}
-
-/*
- * read a new data block from the input stream
- */
-
-static int gifin_read_data_block()
-{
- /* read the data block header */
- buf_cnt = fgetc(ins);
-
- /* read the data block body */
- if (fread(buf, 1, buf_cnt, ins) != buf_cnt)
- return GIFIN_ERR_EOF;
-
- buf_idx = 0;
-
- /* done! */
- return GIFIN_SUCCESS;
-}
-
-
-/*
- * add a new string to the string table
- */
-
-static int gifin_add_string(int p, int e)
-{
- prefix[table_size] = p;
- extnsn[table_size] = e;
-
- if ((table_size == code_mask) && (code_size < 12))
- {
- code_size += 1;
- code_mask = (1 << code_size) - 1;
- }
-
- table_size += 1;
- if (table_size > STAB_SIZE)
- return GIFIN_ERR_TAO;
- return GIFIN_SUCCESS;
-}
-
-Image *Read_GIF_to_Image(char *fullname)
-{
- FILE *f;
- Image *image;
- int x, y, pixel, pass, scanlen;
- byte *pixptr, *pixline;
- int errno;
-
- if (!(f = fopen(fullname,"r")))
- {
- perror("gifLoad");
- return(NULL);
- }
-
- if ((gifin_open_file(f) != GIFIN_SUCCESS) || /* read GIF header */
- (gifin_open_image() != GIFIN_SUCCESS)) /* read image header */
- {
- printf("gifin_open_file or gifin_open_image failed!\n");
-
- gifin_close_file();
- fclose(f);
- return(NULL);
- }
-
-
-
- /*
- printf("%s:\n %dx%d %s%s image with %d colors at depth %d\n",
- fullname, gifin_img_width, gifin_img_height,
- (gifin_interlace_flag ? "interlaced " : ""),
- gif_version_name[gifin_version],
- (gifin_l_cmap_flag ? gifin_l_ncolors : gifin_g_ncolors),
- (gifin_l_cmap_flag ? gifin_l_pixel_bits : gifin_g_pixel_bits));
- */
-
-
-
- image = newRGBImage(gifin_img_width, gifin_img_height, (gifin_l_cmap_flag ?
- gifin_l_pixel_bits :
- gifin_g_pixel_bits));
-
- /* if image has a local colormap, override global colormap
- */
-
- if (gifin_l_cmap_flag)
- {
- for (x=0; x<gifin_l_ncolors; x++)
- {
- image->rgb.red[x] = gifin_l_cmap[GIF_RED][x] << 8;
- image->rgb.green[x] = gifin_l_cmap[GIF_GRN][x] << 8;
- image->rgb.blue[x] = gifin_l_cmap[GIF_BLU][x] << 8;
- }
- image->rgb.used = gifin_l_ncolors;
- }
- else
- {
- for (x=0; x<gifin_g_ncolors; x++)
- {
- image->rgb.red[x] = gifin_g_cmap[GIF_RED][x] << 8;
- image->rgb.green[x] = gifin_g_cmap[GIF_GRN][x] << 8;
- image->rgb.blue[x] = gifin_g_cmap[GIF_BLU][x] << 8;
- }
- image->rgb.used = gifin_g_ncolors;
- }
-
- /* interlaced image -- futz with the vertical trace. i wish i knew what
- * kind of drugs the GIF people were on when they decided that they
- * needed to support interlacing.
- */
-
- if (gifin_interlace_flag)
- {
- scanlen = image->height * image->pixlen;
-
- /* interlacing takes four passes to read, each starting at a different
- * vertical point.
- */
-
- for (pass=0; pass<4; pass++)
- {
- y = interlace_start[pass];
- scanlen = image->width * image->pixlen * interlace_rate[pass];
- pixline = image->data + (y * image->width * image->pixlen);
- while (y < gifin_img_height)
- {
- pixptr = pixline;
- for (x=0; x<gifin_img_width; x++)
- {
- if ((errno = gifin_get_pixel(&pixel)) != GIFIN_SUCCESS)
- {
- fprintf(stderr, "gifLoad: %s - Short read within image data, '%s'\n", fullname, get_err_string(errno));
- y = gifin_img_height;
- x = gifin_img_width;
- }
- valToMem(pixel, pixptr, image->pixlen);
- pixptr += image->pixlen;
- }
- y += interlace_rate[pass];
- pixline += scanlen;
- }
- }
- }
- else
- {
- /* not an interlaced image, just read in sequentially
- */
-
- if (image->pixlen == 1) /* the usual case */
- {
- pixptr = image->data;
- for (y=0; y<gifin_img_height; y++)
- for (x=0; x<gifin_img_width; x++)
- {
- if ((errno = gifin_get_pixel(&pixel)) != GIFIN_SUCCESS)
- {
- fprintf(stderr, "gifLoad: %s - Short read within image data, '%s'\n", fullname, get_err_string(errno));
- y = gifin_img_height;
- x = gifin_img_width;
- }
- valToMem(pixel, pixptr, 1);
- pixptr += 1;
- }
- }
- else /* less ususal case */
- {
- pixptr = image->data;
- for (y=0; y<gifin_img_height; y++)
- for (x=0; x<gifin_img_width; x++)
- {
- if ((errno = gifin_get_pixel(&pixel)) != GIFIN_SUCCESS)
- {
- fprintf(stderr, "gifLoad: %s - Short read within image data, '%s'\n", fullname, get_err_string(errno));
- y = gifin_img_height;
- x = gifin_img_width;
- }
- valToMem(pixel, pixptr, image->pixlen);
- pixptr += image->pixlen;
- }
- }
- }
-
- gifin_close_file();
- fclose(f);
-
- return(image);
-}
+++ /dev/null
-
-/* gif.h:
- *
- * gifin.h
- * kirk johnson
- * november 1989
- * external interface to gifin.c
- *
- * Copyright 1989 Kirk L. Johnson (see the included file
- * "kljcpyrght.h" for complete copyright information)
- */
-
-/*
- * gifin return codes
- */
-#define GIFIN_SUCCESS 0 /* success */
-#define GIFIN_DONE 1 /* no more images */
-
-#define GIFIN_ERR_BAD_SD -1 /* bad screen descriptor */
-#define GIFIN_ERR_BAD_SEP -2 /* bad image separator */
-#define GIFIN_ERR_BAD_SIG -3 /* bad signature */
-#define GIFIN_ERR_EOD -4 /* unexpected end of raster data */
-#define GIFIN_ERR_EOF -5 /* unexpected end of input stream */
-#define GIFIN_ERR_FAO -6 /* file already open */
-#define GIFIN_ERR_IAO -7 /* image already open */
-#define GIFIN_ERR_NFO -8 /* no file open */
-#define GIFIN_ERR_NIO -9 /* no image open */
-#define GIFIN_ERR_PSO -10 /* pixel stack overflow */
-#define GIFIN_ERR_TAO -11 /* table overflow */
-#define GIFIN_ERR_BAD_DES -12 /* bad image descriptor */
-
-#define GIFIN_ERR_BAD_SD_STR "Bad screen descriptor"
-#define GIFIN_ERR_BAD_SEP_STR "Bad image separator"
-#define GIFIN_ERR_BAD_SIG_STR "Bad signature"
-#define GIFIN_ERR_EOD_STR "Unexpected end of raster data"
-#define GIFIN_ERR_EOF_STR "Unexpected end of input stream"
-#define GIFIN_ERR_FAO_STR "File already open"
-#define GIFIN_ERR_IAO_STR "Image already open"
-#define GIFIN_ERR_NFO_STR "No file open"
-#define GIFIN_ERR_NIO_STR "No image open"
-#define GIFIN_ERR_PSO_STR "Pixel stack overflow"
-#define GIFIN_ERR_TAO_STR "Table overflow"
-#define GIFIN_ERR_BAD_DES_STR "Bad image descriptor"
-
-typedef struct {
- int err_no;
- char *name;
- } gif_err_string;
-
-#ifdef GIF_C
-gif_err_string gif_err_strings[] = {
- {GIFIN_ERR_BAD_SD, GIFIN_ERR_BAD_SD_STR},
- {GIFIN_ERR_BAD_SEP, GIFIN_ERR_BAD_SEP_STR},
- {GIFIN_ERR_BAD_SIG, GIFIN_ERR_BAD_SIG_STR},
- {GIFIN_ERR_EOD, GIFIN_ERR_EOD_STR},
- {GIFIN_ERR_EOF, GIFIN_ERR_EOF_STR},
- {GIFIN_ERR_FAO, GIFIN_ERR_FAO_STR},
- {GIFIN_ERR_IAO, GIFIN_ERR_IAO_STR},
- {GIFIN_ERR_NFO, GIFIN_ERR_NFO_STR},
- {GIFIN_ERR_NIO, GIFIN_ERR_NIO_STR},
- {GIFIN_ERR_PSO, GIFIN_ERR_PSO_STR},
- {GIFIN_ERR_TAO, GIFIN_ERR_TAO_STR},
- {GIFIN_ERR_BAD_DES, GIFIN_ERR_BAD_DES_STR},
- {0}
- };
-#endif
-
-/*
- * colormap indices
- */
-
-#define GIF_RED 0
-#define GIF_GRN 1
-#define GIF_BLU 2
-
-/*
- * typedef BYTE for convenience
- */
-
-typedef unsigned char BYTE;
-
-static int gifin_open_file();
-static int gifin_open_image();
-static int gifin_get_pixel();
-#if 0
-static int gifin_close_image();
-#endif
-static int gifin_close_file();
-static int gifin_load_cmap();
-static int gifin_skip_extension();
-static int gifin_read_data_block();
-static int gifin_add_string();
-
-/* #defines, typedefs, and such
- */
-
-#define GIF_SIG "GIF87a"
-#define GIF_SIG_89 "GIF89a"
-
-#define GIF87a 0 /* Gif file version type */
-#define GIF89a 1 /* Gif file version type */
-
-#define GIF_SIG_LEN 6 /* GIF signature length */
-#define GIF_SD_SIZE 7 /* GIF screen descriptor size */
-#define GIF_ID_SIZE 9 /* GIF image descriptor size */
-
-#define GIF_SEPARATOR ',' /* GIF image separator */
-#define GIF_EXTENSION '!' /* GIF extension block marker */
-#define GIF_TERMINATOR ';' /* GIF terminator */
-
-#define STAB_SIZE 4096 /* string table size */
-#define PSTK_SIZE 4096 /* pixel stack size */
-
-#define NULL_CODE -1 /* string table null code */
-
-#ifdef GIF_C
-char *gif_version_name[] = {
- GIF_SIG,
- GIF_SIG_89
- };
-#endif
+++ /dev/null
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back! *
-*----------------------------------------------------------*
-* (c) 1995-98 Artsoft Entertainment *
-* Holger Schemel *
-* Oststrasse 11a *
-* 33604 Bielefeld *
-* phone: ++49 +521 290471 *
-* email: aeglos@valinor.owl.de *
-*----------------------------------------------------------*
-* gifload.c *
-***********************************************************/
-
-#ifndef MSDOS
-#include "gifload.h"
-
-#include "image.h"
-
-#endif
+++ /dev/null
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back! *
-*----------------------------------------------------------*
-* (c) 1995-98 Artsoft Entertainment *
-* Holger Schemel *
-* Oststrasse 11a *
-* 33604 Bielefeld *
-* phone: ++49 +521 290471 *
-* email: aeglos@valinor.owl.de *
-*----------------------------------------------------------*
-* gifload.h *
-***********************************************************/
-
-#ifndef GIFLOAD_H
-#define GIFLOAD_H
-
-#ifndef MSDOS
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#endif
-
-#endif
+++ /dev/null
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back! *
-*----------------------------------------------------------*
-* (c) 1995-98 Artsoft Entertainment *
-* Holger Schemel *
-* Oststrasse 11a *
-* 33604 Bielefeld *
-* phone: ++49 +521 290471 *
-* email: aeglos@valinor.owl.de *
-*----------------------------------------------------------*
-* msdos.c *
-***********************************************************/
-
-#ifdef MSDOS
-#include "main.h"
-#include "tools.h"
-#include "sound.h"
-#include "files.h"
-#include "joystick.h"
-
-DECLARE_GFX_DRIVER_LIST(
- GFX_DRIVER_VBEAF
- GFX_DRIVER_VESA2L
- GFX_DRIVER_VESA1)
-DECLARE_COLOR_DEPTH_LIST(COLOR_DEPTH_8)
-DECLARE_DIGI_DRIVER_LIST(DIGI_DRIVER_SB)
-DECLARE_MIDI_DRIVER_LIST()
-DECLARE_JOYSTICK_DRIVER_LIST(JOYSTICK_DRIVER_STANDARD)
-
-static int key_buffer[OSD_MAX_KEY];
-static XEvent event_buffer[MAX_EVENT_BUFFER];
-static int pending_events;
-static boolean joystick_event;
-static boolean mouse_installed = FALSE;
-static int last_mouse_pos;
-static int last_mouse_b;
-static int last_joystick_state;
-static BITMAP* video_bitmap;
-
-boolean wait_for_vsync;
-
-extern int playing_sounds;
-extern struct SoundControl playlist[MAX_SOUNDS_PLAYING];
-extern struct SoundControl emptySoundControl;
-
-void allegro_drivers()
-{
- int i;
-
- for(i = 0; i < MAX_EVENT_BUFFER; i++);
- event_buffer[i].type = 0;
- for(i=0; i < OSD_MAX_KEY; i++) key_buffer[i] = KeyReleaseMask;
- last_mouse_pos = mouse_pos;
- last_mouse_b = 0;
-
- pending_events = 0;
- clear_keybuf();
-
- i_love_bill = TRUE;
- install_keyboard();
- install_timer();
- if (install_mouse() > 0) mouse_installed = TRUE;
- install_joystick(JOY_TYPE_2PADS);
-
- load_joystick_data(JOYDAT_FILE);
- last_joystick_state = 0;
- joystick_event = FALSE;
-
- reserve_voices(MAX_SOUNDS_PLAYING, 0);
- if(install_sound(DIGI_AUTODETECT, MIDI_NONE, "ROCKS.SND") == -1)
- if(install_sound(DIGI_SB, MIDI_NONE, NULL) == -1) sound_status = SOUND_OFF;
-
-}
-
-boolean hide_mouse(Display *display, int x, int y,
- unsigned int width, unsigned int height)
-{
- if(mouse_x + display->mouse_ptr->w < x || mouse_x > x+width) return FALSE;
- if(mouse_y + display->mouse_ptr->h < y || mouse_y > y+height) return FALSE;
- show_mouse(NULL);
- return(TRUE);
-}
-
-void unhide_mouse(Display *display)
-{
- if(mouse_installed) show_mouse(video_bitmap);
-}
-
-int get_joystick_state()
-{
- int state = 0;
- poll_joystick();
-
- if (joy[joystick_nr].stick[0].axis[0].d1) state |= JOY_LEFT;
- if (joy[joystick_nr].stick[0].axis[0].d2) state |= JOY_RIGHT;
- if (joy[joystick_nr].stick[0].axis[1].d1) state |= JOY_UP;
- if (joy[joystick_nr].stick[0].axis[1].d2) state |= JOY_DOWN;
- if (joy[joystick_nr].button[0].b) state |= JOY_BUTTON_1;
-
- switch (state)
- {
- case (JOY_DOWN | JOY_LEFT):
- state = XK_KP_1;
- break;
- case (JOY_DOWN):
- state = XK_KP_2;
- break;
- case (JOY_DOWN | JOY_RIGHT):
- state = XK_KP_3;
- break;
- case (JOY_LEFT):
- state = XK_KP_4;
- break;
- case (JOY_RIGHT):
- state = XK_KP_6;
- break;
- case (JOY_UP | JOY_LEFT):
- state = XK_KP_7;
- break;
- case (JOY_UP):
- state = XK_KP_8;
- break;
- case (JOY_UP | JOY_RIGHT):
- state = XK_KP_9;
- break;
-
- case (JOY_DOWN | JOY_BUTTON_1):
- state = XK_X;
- break;
- case (JOY_LEFT | JOY_BUTTON_1):
- state = XK_S;
- break;
- case (JOY_RIGHT | JOY_BUTTON_1):
- state = XK_D;
- break;
- case (JOY_UP | JOY_BUTTON_1):
- state = XK_E;
- break;
-
- default:
- state = 0;
- }
-
- return(state);
-}
-
-unsigned char get_ascii(KeySym key)
-{
- switch(key) {
-
- case OSD_KEY_Q: return 'Q';
- case OSD_KEY_W: return 'W';
- case OSD_KEY_E: return 'E';
- case OSD_KEY_R: return 'R';
- case OSD_KEY_T: return 'T';
- case OSD_KEY_Y: return 'Y';
- case OSD_KEY_U: return 'U';
- case OSD_KEY_I: return 'I';
- case OSD_KEY_O: return 'O';
- case OSD_KEY_P: return 'P';
- case OSD_KEY_A: return 'A';
- case OSD_KEY_S: return 'S';
- case OSD_KEY_D: return 'D';
- case OSD_KEY_F: return 'F';
- case OSD_KEY_G: return 'G';
- case OSD_KEY_H: return 'H';
- case OSD_KEY_J: return 'J';
- case OSD_KEY_K: return 'K';
- case OSD_KEY_L: return 'L';
- case OSD_KEY_Z: return 'Z';
- case OSD_KEY_X: return 'X';
- case OSD_KEY_C: return 'C';
- case OSD_KEY_V: return 'V';
- case OSD_KEY_B: return 'B';
- case OSD_KEY_N: return 'N';
- case OSD_KEY_M: return 'M';
- case OSD_KEY_1: return '1';
- case OSD_KEY_2: return '2';
- case OSD_KEY_3: return '3';
- case OSD_KEY_4: return '4';
- case OSD_KEY_5: return '5';
- case OSD_KEY_6: return '6';
- case OSD_KEY_7: return '7';
- case OSD_KEY_8: return '8';
- case OSD_KEY_9: return '9';
- case OSD_KEY_0: return '0';
- case OSD_KEY_SPACE: return ' ';
- }
- return (0);
-}
-
-long osd_key_pressed(int keycode)
-{
- if (keycode == OSD_KEY_RCONTROL) keycode = KEY_RCONTROL;
- if (keycode == OSD_KEY_ALTGR) keycode = KEY_ALTGR;
-
- if (key[keycode])
- return(KeyPressMask);
- else
- return(KeyReleaseMask);
-}
-
-void XMapWindow(Display* display, Window w)
-{
- int x, y;
- unsigned int width, height;
- boolean mouse_off;
-
- x = display->screens[display->default_screen].x;
- y = display->screens[display->default_screen].y;
- width = display->screens[display->default_screen].width;
- height = display->screens[display->default_screen].height;
-
- mouse_off = hide_mouse(display, x, y, width, height);
- blit((BITMAP *)w, video_bitmap, 0, 0, x, y, width, height);
- if(mouse_off) unhide_mouse(display);
-}
-
-Display *XOpenDisplay(char* dummy)
-{
- Screen *MyScreens;
- Display *MyDisplay;
- BITMAP *MyMouse = NULL;
- RGB pal[256];
-
- MyScreens = malloc(sizeof(Screen));
- MyDisplay = malloc(sizeof(Display));
-
- if(MOUSE_FILENAME)
- MyMouse = load_gif(MOUSE_FILENAME, pal);
-
- MyScreens[0].cmap = 0;
- MyScreens[0].root = 0;
- MyScreens[0].white_pixel = 0xFF;
- MyScreens[0].black_pixel = 0x00;
- MyScreens[0].video_bitmap = NULL;
-
- MyDisplay->default_screen = 0;
- MyDisplay->screens = MyScreens;
- MyDisplay->mouse_ptr = MyMouse;
-
- allegro_init();
- allegro_drivers();
- set_color_depth(8);
- set_gfx_mode(GFX_AUTODETECT, 320, 200, 0, 0); // force Windows 95 to switch to fullscreen mode
- rest(200);
- set_gfx_mode(GFX_AUTODETECT, XRES, YRES, 0, 0);
-
- return(MyDisplay);
-}
-
-Window XCreateSimpleWindow(
- Display* display,
- Window parent,
- int x,
- int y,
- unsigned int width,
- unsigned int height,
- unsigned int border_width,
- unsigned long border,
- unsigned long background)
-{
- video_bitmap = create_video_bitmap(XRES, YRES);
- clear_to_color(video_bitmap, background);
-
- display->screens[display->default_screen].video_bitmap = video_bitmap;
- display->screens[display->default_screen].x = x;
- display->screens[display->default_screen].y = y;
- display->screens[display->default_screen].width = XRES;
- display->screens[display->default_screen].height = YRES;
-
- set_mouse_sprite(display->mouse_ptr);
- set_mouse_range(display->screens[display->default_screen].x+1,
- display->screens[display->default_screen].y+1,
- display->screens[display->default_screen].x+WIN_XSIZE+1,
- display->screens[display->default_screen].y+WIN_YSIZE+1);
-
- show_video_bitmap(video_bitmap);
-
- return((Window) video_bitmap);
-}
-
-int XReadBitmapFile(
- Display* display,
- Drawable d,
- char* filename,
- unsigned int* width_return,
- unsigned int* height_return,
- Pixmap* bitmap_return,
- int* x_hot_return,
- int* y_hot_return)
-{
- BITMAP *bmp;
- RGB pal[256];
-
- if((bmp = load_gif(filename, pal)) == NULL)
- return(BitmapOpenFailed);
-
- *width_return = bmp->w;
- *height_return = bmp->h;
- *x_hot_return = -1;
- *y_hot_return = -1;
- *bitmap_return = (Pixmap) bmp;
-
- return(BitmapSuccess);
-}
-
-Status XStringListToTextProperty(char** list, int count, XTextProperty* text_prop_return)
-{
- char *string;
-
- if(count >= 1)
- {
- string = malloc(strlen(list[0]+1));
- strcpy(string, list[0]);
- text_prop_return->value = (unsigned char *) string;
- return(1);
- }
- else
- {
- text_prop_return = NULL;
- }
- return(0);
-}
-
-void XFree(void* data)
-{
- if(data) free(data);
-}
-
-GC XCreateGC(Display* display, Drawable d, unsigned long value_mask, XGCValues* values)
-{
- XGCValues *gcv;
- gcv = malloc(sizeof(XGCValues));
- gcv->foreground = values->foreground;
- gcv->background = values->background;
- gcv->graphics_exposures = values->graphics_exposures;
- gcv->clip_mask = values->clip_mask;
- gcv->clip_x_origin = values->clip_x_origin;
- gcv->clip_y_origin = values->clip_y_origin;
- gcv->value_mask = value_mask;
- return((GC) gcv);
-}
-
-void XFillRectangle(
- Display* display,
- Drawable d,
- GC gc,
- int x,
- int y,
- unsigned int width,
- unsigned int height)
-{
- boolean mouse_off;
-
- if((BITMAP *) d == video_bitmap)
- {
- x += display->screens[display->default_screen].x;
- y += display->screens[display->default_screen].y;
- freeze_mouse_flag = TRUE;
- mouse_off = hide_mouse(display, x, y, width, height);
- }
-
- rectfill((BITMAP *) d, x, y, x+width, y+height, ((XGCValues *)gc)->foreground);
- if(mouse_off) unhide_mouse(display);
- freeze_mouse_flag = FALSE;
-}
-
-Pixmap XCreatePixmap(
- Display* display,
- Drawable d,
- unsigned int width,
- unsigned int height,
- unsigned int depth)
-{
- BITMAP *MyBitmap = NULL;
-
- if(GFX_HW_VRAM_BLIT&gfx_capabilities && width == FXSIZE && height == FYSIZE)
- MyBitmap = create_video_bitmap(width, height);
-
- if(MyBitmap == NULL)
- MyBitmap = create_bitmap(width, height);
-
- return((Pixmap) MyBitmap);
-}
-
-inline void XCopyArea(
- Display* display,
- Drawable src,
- Drawable dest,
- GC gc,
- int src_x,
- int src_y,
- unsigned int width,
- unsigned int height,
- int dest_x,
- int dest_y)
-{
- boolean mouse_off;
-
- if((BITMAP *) src == video_bitmap )
- {
- src_x += display->screens[display->default_screen].x;
- src_y += display->screens[display->default_screen].y;
- }
- if((BITMAP *) dest == video_bitmap )
- {
- dest_x += display->screens[display->default_screen].x;
- dest_y += display->screens[display->default_screen].y;
- freeze_mouse_flag = TRUE;
- mouse_off = hide_mouse(display, dest_x, dest_y, width, height);
- }
-
- if(wait_for_vsync)
- {
- wait_for_vsync = FALSE;
- vsync();
- }
-
- if(((XGCValues *)gc)->value_mask&GCClipMask)
- masked_blit((BITMAP *) src, (BITMAP *) dest, src_x, src_y, dest_x, dest_y, width, height);
- else
- blit((BITMAP *) src, (BITMAP *) dest, src_x, src_y, dest_x, dest_y, width, height);
-
- if(mouse_off) unhide_mouse(display);
- freeze_mouse_flag = FALSE;
-}
-
-int XpmReadFileToPixmap(
- Display* display,
- Drawable d,
- char* filename,
- Pixmap* pixmap_return,
- Pixmap* shapemask_return,
- XpmAttributes* attributes)
-{
- BITMAP *bmp;
- RGB pal[256];
-
- if((bmp = load_gif(filename, pal)) == NULL)
- return(XpmOpenFailed);
-
- *pixmap_return = (Pixmap) bmp;
- set_pallete(pal);
-
- return(XpmSuccess);
-}
-
-void XFreePixmap(Display* display, Pixmap pixmap)
-{
- if( pixmap != DUMMY_MASK &&
- (is_memory_bitmap((BITMAP *) pixmap) || is_screen_bitmap((BITMAP *) pixmap)) )
- destroy_bitmap((BITMAP *) pixmap);
-}
-
-void XFreeGC(Display* display, GC gc)
-{
- XGCValues *gcv;
-
- gcv = (XGCValues *) gc;
- if(gcv) free(gcv);
-}
-
-void XCloseDisplay(Display* display)
-{
- BITMAP * bmp;
- bmp = video_bitmap;
-
- if(is_screen_bitmap(bmp))
- destroy_bitmap(bmp);
- if(display->screens)
- free(display->screens);
- if(display)
- free(display);
-}
-
-void XNextEvent(Display* display, XEvent* event_return)
-{
- while(!pending_events) XPending(display);
-
- memcpy(event_return, &event_buffer[pending_events], sizeof(XEvent));
- pending_events--;
-}
-
-int XPending(Display* display)
-{
- int i, state;
- static boolean joy_button_2 = FALSE;
-
- XKeyEvent *xkey;
- XButtonEvent *xbutton;
- XMotionEvent *xmotion;
-
- // joystick event (simulating keyboard event)
-
- state = get_joystick_state();
-
- if (joy[joystick_nr].button[1].b && !joy_button_2)
- {
- pending_events++;
- xkey = (XKeyEvent *) &event_buffer[pending_events];
- xkey->type = KeyPress;
- xkey->state = XK_B;
- joy_button_2 = TRUE;
- }
- else if (!joy[joystick_nr].button[1].b && joy_button_2)
- {
- pending_events++;
- xkey = (XKeyEvent *) &event_buffer[pending_events];
- xkey->type = KeyRelease;
- xkey->state = XK_B;
- joy_button_2 = FALSE;
- }
-
- if(state && !joystick_event)
- {
- pending_events++;
- xkey = (XKeyEvent *) &event_buffer[pending_events];
- xkey->type = KeyPress;
- xkey->state = state;
- joystick_event = TRUE;
- last_joystick_state = state;
- }
- else if((state != last_joystick_state) && joystick_event)
- {
- pending_events++;
- xkey = (XKeyEvent *) &event_buffer[pending_events];
- xkey->type = KeyRelease;
- xkey->state = last_joystick_state;
- joystick_event = FALSE;
- }
-
- // keyboard event
-
- for(i=0; i < OSD_MAX_KEY+1 && pending_events < MAX_EVENT_BUFFER; i++)
- {
- state = osd_key_pressed(i);
-
- if(state != key_buffer[i])
- {
- key_buffer[i] = state;
- pending_events++;
- xkey = (XKeyEvent *) &event_buffer[pending_events];
- xkey->type = state&KeyPressMask ? KeyPress : KeyRelease;
- xkey->state = i;
- }
- }
-
- // mouse motion event
-
- if((mouse_pos != last_mouse_pos && mouse_b != last_mouse_b))
- {
- last_mouse_pos = mouse_pos;
- pending_events++;
- xmotion = (XMotionEvent *) &event_buffer[pending_events];
- xmotion->type = MotionNotify;
- xmotion->x = mouse_x - display->screens[display->default_screen].x;
- xmotion->y = mouse_y - display->screens[display->default_screen].y;
- return;
- }
-
- // mouse button event
-
- if(mouse_b != last_mouse_b)
- {
- for(i = 1; i<4; i<<=1)
- {
- if((last_mouse_b&i) != (mouse_b&i))
- {
- pending_events++;
- xbutton = (XButtonEvent *) &event_buffer[pending_events];
- xbutton->type = mouse_b&i ? ButtonPress : ButtonRelease;
- xbutton->button = i;
- xbutton->x = mouse_x - display->screens[display->default_screen].x;
- xbutton->y = mouse_y - display->screens[display->default_screen].y;
- }
- }
- last_mouse_b = mouse_b;
- }
-
- return pending_events;
-}
-
-KeySym XLookupKeysym(XKeyEvent* key_event, int index)
-{
- return(key_event->state);
-}
-
-void sound_handler(struct SoundControl snd_ctrl)
-{
- int i;
-
- if (snd_ctrl.fade_sound)
- {
- if (!playing_sounds)
- return;
-
- for(i=0;i<MAX_SOUNDS_PLAYING;i++)
- if ((snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr) && !playlist[i].fade_sound) {
- playlist[i].fade_sound = TRUE;
- if(voice_check(playlist[i].voice))
- voice_ramp_volume(playlist[i].voice, 1000, 0);
- playlist[i].loop = PSND_NO_LOOP;
- }
- }
- else if (snd_ctrl.stop_all_sounds)
- {
- if (!playing_sounds)
- return;
- SoundServer_StopAllSounds();
- }
- else if (snd_ctrl.stop_sound)
- {
- if (!playing_sounds)
- return;
- SoundServer_StopSound(snd_ctrl.nr);
- }
-
- for(i=0;i<MAX_SOUNDS_PLAYING;i++)
- {
- if (!playlist[i].active || playlist[i].loop)
- continue;
-
- playlist[i].playingpos = voice_get_position(playlist[i].voice);
- playlist[i].volume = voice_get_volume(playlist[i].voice);
- if (playlist[i].playingpos == -1 || !playlist[i].volume)
- {
- deallocate_voice(playlist[i].voice);
- playlist[i] = emptySoundControl;
- playing_sounds--;
- }
- }
-
- if (snd_ctrl.active)
- SoundServer_InsertNewSound(snd_ctrl);
-
-}
-
-
-// GIF Loader
-// by Paul Bartrum
-
-int _color_load_depth(int depth);
-
-struct LZW_STRING
-{
- short base;
- char new;
- short length;
-};
-
-PACKFILE *f;
-int empty_string, curr_bit_size, bit_overflow;
-int bit_pos, data_pos, data_len, entire, code;
-int cc, string_length, i, bit_size;
-unsigned char string[4096];
-struct LZW_STRING str[4096];
-BITMAP *bmp;
-int image_x, image_y, image_w, image_h, x, y;
-int interlace;
-
-
-void clear_table(void)
-{
- empty_string = cc + 2;
- curr_bit_size = bit_size + 1;
- bit_overflow = 0;
-}
-
-
-void get_code(void)
-{
- if(bit_pos + curr_bit_size > 8) {
- if(data_pos >= data_len) { data_len = pack_getc(f); data_pos = 0; }
- entire = (pack_getc(f) << 8) + entire;
- data_pos ++;
- }
- if(bit_pos + curr_bit_size > 16) {
- if(data_pos >= data_len) { data_len = pack_getc(f); data_pos = 0; }
- entire = (pack_getc(f) << 16) + entire;
- data_pos ++;
- }
- code = (entire >> bit_pos) & ((1 << curr_bit_size) - 1);
- if(bit_pos + curr_bit_size > 8)
- entire >>= 8;
- if(bit_pos + curr_bit_size > 16)
- entire >>= 8;
- bit_pos = (bit_pos + curr_bit_size) % 8;
- if(bit_pos == 0) {
- if(data_pos >= data_len) { data_len = pack_getc(f); data_pos = 0; }
- entire = pack_getc(f);
- data_pos ++;
- }
-}
-
-
-void get_string(int num)
-{
- if(num < cc)
- {
- string_length = 1;
- string[0] = str[num].new;
- }
- else
- {
- i = str[num].length;
- string_length = i;
- while(i > 0)
- {
- i --;
- string[i] = str[num].new;
- num = str[num].base;
- }
- /* if(num != -1) **-{[ERROR]}-** */
- }
-}
-
-
-void output_string(void)
-{
- for(i = 0; i < string_length; i ++)
- {
- putpixel(bmp, x, y, string[i]);
- x ++;
- if(x >= image_x + image_w)
- {
- x = image_x;
- y += interlace;
- if(interlace)
- {
- if(y >= image_y + image_h)
- {
- if(interlace == 8 && (y - image_y) % 8 == 0) {
- interlace = 8;
- y = image_y + 4;
- }
- else if(interlace == 8 && (y - image_y) % 8 == 4) {
- interlace = 4;
- y = image_y + 2;
- }
- else if(interlace == 4) {
- interlace = 2;
- y = image_y + 1;
- }
- }
- }
- }
- }
-}
-
-/* load_gif:
- * Loads a 2-256 colour GIF file onto a bitmap, returning the bitmap
- * structure and storing the pallete data in the specified pallete (this
- * should be an array of at least 256 RGB structures).
- */
-BITMAP *load_gif(char *filename, RGB *pal)
-{
- int width, height, depth;
- int old;
- BITMAP *bmp2;
- int dest_depth;
-
- f = pack_fopen(filename, F_READ);
- if (!f) /* can't open file */
- return NULL;
-
- i = pack_mgetw(f) << 8;
- i += pack_getc(f);
- if(i != 0x474946) /* is it really a GIF? */
- {
- pack_fclose(f);
- return NULL;
- }
- pack_fseek(f, 3); /* skip version */
-
- width = pack_igetw(f);
- height = pack_igetw(f);
-
- bmp = create_bitmap_ex(8, width, height);
- if(bmp == NULL) {
- pack_fclose(f);
- return NULL;
- }
- clear(bmp);
-
- i = pack_getc(f);
- if(i & 128) /* no global colour table? */
- depth = (i & 7) + 1;
- else
- depth = 0;
-
- pack_fseek(f, 2); /* skip background colour and aspect ratio */
-
- if(pal && depth) /* only read palette if pal and depth are not 0 */
- {
- for(i = 0; i < (1 << depth); i ++)
- {
- pal[i].r = pack_getc(f) / 4;
- pal[i].g = pack_getc(f) / 4;
- pal[i].b = pack_getc(f) / 4;
- }
- }
- else
- if(depth)
- pack_fseek(f, (1 << depth) * 3);
-
- do
- {
- i = pack_getc(f);
- switch(i)
- {
- case 0x2C: /* Image Descriptor */
- image_x = pack_igetw(f);
- image_y = pack_igetw(f); /* individual image dimensions */
- image_w = pack_igetw(f);
- image_h = pack_igetw(f);
-
- i = pack_getc(f);
- if(i & 64)
- interlace = 8;
- else
- interlace = 1;
-
- if(i & 128)
- {
- depth = (i & 7) + 1;
- if(pal)
- {
- for(i = 0; i < (1 << depth); i ++)
- {
- pal[i].r = pack_getc(f) / 4;
- pal[i].g = pack_getc(f) / 4;
- pal[i].b = pack_getc(f) / 4;
- }
- }
- else
- pack_fseek(f, (1 << depth) * 3);
- }
-
- /* lzw stream starts now */
- bit_size = pack_getc(f);
- cc = 1 << bit_size;
-
- /* initialise string table */
- for(i = 0; i < cc; i ++)
- {
- str[i].base = -1;
- str[i].new = i;
- str[i].length = 1;
- }
-
- /* initialise the variables */
- bit_pos = 0;
- data_len = pack_getc(f); data_pos = 0;
- entire = pack_getc(f); data_pos ++;
- string_length = 0; x = image_x; y = image_y;
-
- /* starting code */
- clear_table();
- get_code();
- if(code == cc)
- get_code();
- get_string(code);
- output_string();
- old = code;
-
- while(TRUE)
- {
- get_code();
-
- if(code == cc)
- {
- /* starting code */
- clear_table();
- get_code();
- get_string(code);
- output_string();
- old = code;
- }
- else if(code == cc + 1)
- {
- break;
- }
- else if(code < empty_string)
- {
- get_string(code);
- output_string();
-
- if(bit_overflow == 0) {
- str[empty_string].base = old;
- str[empty_string].new = string[0];
- str[empty_string].length = str[old].length + 1;
- empty_string ++;
- if(empty_string == (1 << curr_bit_size))
- curr_bit_size ++;
- if(curr_bit_size == 13) {
- curr_bit_size = 12;
- bit_overflow = 1;
- }
- }
-
- old = code;
- }
- else
- {
- get_string(old);
- string[str[old].length] = string[0];
- string_length ++;
-
- if(bit_overflow == 0) {
- str[empty_string].base = old;
- str[empty_string].new = string[0];
- str[empty_string].length = str[old].length + 1;
- empty_string ++;
- if(empty_string == (1 << curr_bit_size))
- curr_bit_size ++;
- if(curr_bit_size == 13) {
- curr_bit_size = 12;
- bit_overflow = 1;
- }
- }
-
- output_string();
- old = code;
- }
- }
- break;
- case 0x21: /* Extension Introducer */
- i = pack_getc(f);
- if(i == 0xF9) /* Graphic Control Extension */
- {
- pack_fseek(f, 1); /* skip size (it's 4) */
- i = pack_getc(f);
- if(i & 1) /* is transparency enabled? */
- {
- pack_fseek(f, 2);
- pack_getc(f); /* transparent colour */
- }
- else
- pack_fseek(f, 3);
- }
- i = pack_getc(f);
- while(i) /* skip Data Sub-blocks */
- {
- pack_fseek(f, i);
- i = pack_getc(f);
- }
- break;
- case 0x3B: /* Trailer - end of data */
- pack_fclose(f);
-
- /* convert to correct colour depth */
- dest_depth = _color_load_depth(8);
-
- if (dest_depth != 8)
- {
- bmp2 = create_bitmap_ex(dest_depth, bmp->w, bmp->h);
- if (!bmp2)
- {
- destroy_bitmap(bmp);
- return NULL;
- }
-
- select_palette(pal);
- blit(bmp, bmp2, 0, 0, 0, 0, bmp->w, bmp->h);
- unselect_palette();
-
- destroy_bitmap(bmp);
- bmp = bmp2;
- }
-
- return bmp;
- }
- } while(TRUE);
-
- /* this is never executed but DJGPP complains if you leave it out */
- return NULL;
-}
-
-#endif
+++ /dev/null
-/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back! *
-*----------------------------------------------------------*
-* (c) 1995-98 Artsoft Entertainment *
-* Holger Schemel *
-* Oststrasse 11a *
-* 33604 Bielefeld *
-* phone: ++49 +521 290471 *
-* email: aeglos@valinor.owl.de *
-*----------------------------------------------------------*
-* msdos.h *
-***********************************************************/
-
-#ifndef XPM_INCLUDE_FILE
-#define XPM_INCLUDE_FILE
-#endif
-
-#define XRES 800
-#define YRES 600
-
-#define TRUE 1
-#define FALSE 0
-
-#include <allegro.h>
-#include <time.h>
-
-/* some file path definitions */
-
-#define JOYDAT_PATH GAME_DIR
-#define JOYDAT_FILENAME "ROCKS.joy"
-#define JOYDAT_FILE JOYDAT_PATH "/" JOYDAT_FILENAME
-
-/* Allegro keyboard mapping */
-
-#define OSD_KEY_ESC 1 /* keyboard scan codes */
-#define OSD_KEY_1 2 /* (courtesy of allegro.h) */
-#define OSD_KEY_2 3
-#define OSD_KEY_3 4
-#define OSD_KEY_4 5
-#define OSD_KEY_5 6
-#define OSD_KEY_6 7
-#define OSD_KEY_7 8
-#define OSD_KEY_8 9
-#define OSD_KEY_9 10
-#define OSD_KEY_0 11
-#define OSD_KEY_MINUS 12
-#define OSD_KEY_EQUALS 13
-#define OSD_KEY_BACKSPACE 14
-#define OSD_KEY_TAB 15
-#define OSD_KEY_Q 16
-#define OSD_KEY_W 17
-#define OSD_KEY_E 18
-#define OSD_KEY_R 19
-#define OSD_KEY_T 20
-#define OSD_KEY_Y 21
-#define OSD_KEY_U 22
-#define OSD_KEY_I 23
-#define OSD_KEY_O 24
-#define OSD_KEY_P 25
-#define OSD_KEY_OPENBRACE 26
-#define OSD_KEY_CLOSEBRACE 27
-#define OSD_KEY_ENTER 28
-#define OSD_KEY_LCONTROL 29
-#define OSD_KEY_A 30
-#define OSD_KEY_S 31
-#define OSD_KEY_D 32
-#define OSD_KEY_F 33
-#define OSD_KEY_G 34
-#define OSD_KEY_H 35
-#define OSD_KEY_J 36
-#define OSD_KEY_K 37
-#define OSD_KEY_L 38
-#define OSD_KEY_COLON 39
-#define OSD_KEY_QUOTE 40
-#define OSD_KEY_TILDE 41
-#define OSD_KEY_LSHIFT 42
-/* 43 */
-#define OSD_KEY_Z 44
-#define OSD_KEY_X 45
-#define OSD_KEY_C 46
-#define OSD_KEY_V 47
-#define OSD_KEY_B 48
-#define OSD_KEY_N 49
-#define OSD_KEY_M 50
-#define OSD_KEY_COMMA 51
-#define OSD_KEY_STOP 52
-#define OSD_KEY_SLASH 53
-#define OSD_KEY_RSHIFT 54
-#define OSD_KEY_ASTERISK 55
-#define OSD_KEY_ALT 56
-#define OSD_KEY_SPACE 57
-#define OSD_KEY_CAPSLOCK 58
-#define OSD_KEY_F1 59
-#define OSD_KEY_F2 60
-#define OSD_KEY_F3 61
-#define OSD_KEY_F4 62
-#define OSD_KEY_F5 63
-#define OSD_KEY_F6 64
-#define OSD_KEY_F7 65
-#define OSD_KEY_F8 66
-#define OSD_KEY_F9 67
-#define OSD_KEY_F10 68
-#define OSD_KEY_NUMLOCK 69
-#define OSD_KEY_SCRLOCK 70
-#define OSD_KEY_HOME 71
-#define OSD_KEY_UP 72
-#define OSD_KEY_PGUP 73
-#define OSD_KEY_MINUS_PAD 74
-#define OSD_KEY_LEFT 75
-#define OSD_KEY_5_PAD 76
-#define OSD_KEY_RIGHT 77
-#define OSD_KEY_PLUS_PAD 78
-#define OSD_KEY_END 79
-#define OSD_KEY_DOWN 80
-#define OSD_KEY_PGDN 81
-#define OSD_KEY_INSERT 82
-#define OSD_KEY_DEL 83
-#define OSD_KEY_RCONTROL 84 /* different from Allegro */
-#define OSD_KEY_ALTGR 85 /* different from Allegro */
-/* 86 */
-#define OSD_KEY_F11 87
-#define OSD_KEY_F12 88
-#define OSD_KEY_COMMAND 89
-#define OSD_KEY_OPTION 90
-/* 91 - 100 */
-/* The following are all undefined in Allegro */
-#define OSD_KEY_1_PAD 101
-#define OSD_KEY_2_PAD 102
-#define OSD_KEY_3_PAD 103
-#define OSD_KEY_4_PAD 104
-/* 105 */
-#define OSD_KEY_6_PAD 106
-#define OSD_KEY_7_PAD 107
-#define OSD_KEY_8_PAD 108
-#define OSD_KEY_9_PAD 109
-#define OSD_KEY_0_PAD 110
-#define OSD_KEY_STOP_PAD 111
-#define OSD_KEY_EQUALS_PAD 112
-#define OSD_KEY_SLASH_PAD 113
-#define OSD_KEY_ASTER_PAD 114
-#define OSD_KEY_ENTER_PAD 115
-
-#define OSD_MAX_KEY 115
-
-/* X11 keyboard mapping */
-
-#define XK_KP_Enter OSD_KEY_ENTER_PAD
-#define XK_KP_0 OSD_KEY_0_PAD
-#define XK_KP_1 OSD_KEY_1_PAD
-#define XK_KP_2 OSD_KEY_2_PAD
-#define XK_KP_3 OSD_KEY_3_PAD
-#define XK_KP_4 OSD_KEY_4_PAD
-#define XK_KP_6 OSD_KEY_6_PAD
-#define XK_KP_7 OSD_KEY_7_PAD
-#define XK_KP_8 OSD_KEY_8_PAD
-#define XK_KP_9 OSD_KEY_9_PAD
-/*
-#define XK_KP_Home OSD_KEY_7_PAD
-#define XK_KP_Page_Up OSD_KEY_9_PAD
-#define XK_KP_Page_Down OSD_KEY_3_PAD
-#define XK_KP_End OSD_KEY_1_PAD
-#define XK_KP_Left OSD_KEY_4_PAD
-#define XK_KP_Up OSD_KEY_8_PAD
-#define XK_KP_Right OSD_KEY_6_PAD
-#define XK_KP_Down OSD_KEY_2_PAD
-*/
-#define XK_0 OSD_KEY_1
-#define XK_1 OSD_KEY_2
-#define XK_2 OSD_KEY_3
-#define XK_3 OSD_KEY_4
-#define XK_4 OSD_KEY_5
-#define XK_5 OSD_KEY_6
-#define XK_6 OSD_KEY_7
-#define XK_7 OSD_KEY_8
-#define XK_8 OSD_KEY_9
-#define XK_9 OSD_KEY_0
-#define XK_A OSD_KEY_A
-#define XK_B OSD_KEY_B
-#define XK_C OSD_KEY_C
-#define XK_D OSD_KEY_D
-#define XK_E OSD_KEY_E
-#define XK_F OSD_KEY_F
-#define XK_G OSD_KEY_G
-#define XK_H OSD_KEY_H
-#define XK_I OSD_KEY_I
-#define XK_J OSD_KEY_J
-#define XK_K OSD_KEY_K
-#define XK_L OSD_KEY_L
-#define XK_M OSD_KEY_M
-#define XK_N OSD_KEY_N
-#define XK_O OSD_KEY_O
-#define XK_P OSD_KEY_P
-#define XK_Q OSD_KEY_Q
-#define XK_R OSD_KEY_R
-#define XK_S OSD_KEY_S
-#define XK_T OSD_KEY_T
-#define XK_U OSD_KEY_U
-#define XK_V OSD_KEY_V
-#define XK_W OSD_KEY_W
-#define XK_X OSD_KEY_X
-#define XK_Y OSD_KEY_Y
-#define XK_Z OSD_KEY_Z
-#define XK_a OSD_KEY_A
-#define XK_b OSD_KEY_B
-#define XK_c OSD_KEY_C
-#define XK_d OSD_KEY_D
-#define XK_e OSD_KEY_E
-#define XK_f OSD_KEY_F
-#define XK_g OSD_KEY_G
-#define XK_h OSD_KEY_H
-#define XK_i OSD_KEY_I
-#define XK_j OSD_KEY_J
-#define XK_k OSD_KEY_K
-#define XK_l OSD_KEY_L
-#define XK_m OSD_KEY_M
-#define XK_n OSD_KEY_N
-#define XK_o OSD_KEY_O
-#define XK_p OSD_KEY_P
-#define XK_q OSD_KEY_Q
-#define XK_r OSD_KEY_R
-#define XK_s OSD_KEY_S
-#define XK_t OSD_KEY_T
-#define XK_u OSD_KEY_U
-#define XK_v OSD_KEY_V
-#define XK_w OSD_KEY_W
-#define XK_x OSD_KEY_X
-#define XK_y OSD_KEY_Y
-#define XK_z OSD_KEY_Z
-#define XK_Return OSD_KEY_ENTER
-#define XK_Escape OSD_KEY_ESC
-#define XK_Shift_L OSD_KEY_LSHIFT
-#define XK_Shift_R OSD_KEY_RSHIFT
-#define XK_Left OSD_KEY_LEFT
-#define XK_Up OSD_KEY_UP
-#define XK_Right OSD_KEY_RIGHT
-#define XK_Down OSD_KEY_DOWN
-#define XK_BackSpace OSD_KEY_BACKSPACE
-#define XK_Delete OSD_KEY_DEL
-#define XK_Space OSD_KEY_SPACE
-#define XK_F12 OSD_KEY_F12
-#define XK_F11 OSD_KEY_F11
-#define XK_F10 OSD_KEY_F10
-
-#define MOUSE_FILENAME "graphics\\mouse.gif"
-#define screen myscreen
-
-#define XFlush(a)
-#define XSync(a,b)
-#define XSetClipOrigin(a,b,c,d)
-#define XGetImage(a,b,c,d,e,f,g,h) ((XImage *) NULL)
-#define XAutoRepeatOn(a)
-#define XAutoRepeatOff(a)
-#define XDisplayName(a) ((char *) NULL)
-#define XFreeColors(a,b,c,d,e)
-#define XpmFreeAttributes(a)
-#define XSelectInput(a,b,c)
-#define XDefaultDepth(a,b) (8)
-#define XSetWMProperties(a,b,c,d,e,f,g,h,i)
-
-#define MAX_EVENT_BUFFER 256
-
-#define Status int
-#define Bool int
-#define True 1
-#define False 0
-
-#define DUMMY_FILE (void*) -1
-#define DUMMY_MASK -1
-
-#define KeyPressMask (1L<<0)
-#define KeyReleaseMask (1L<<1)
-#define ButtonPressMask (1L<<2)
-#define ButtonReleaseMask (1L<<3)
-#define ButtonMotionMask (1L<<13)
-#define ExposureMask (1L<<15)
-#define StructureNotifyMask (1L<<17)
-#define FocusChangeMask (1L<<21)
-
-#define KeyPress 2
-#define KeyRelease 3
-#define ButtonPress 4
-#define ButtonRelease 5
-#define MotionNotify 6
-#define FocusIn 9
-#define FocusOut 10
-#define Expose 12
-#define UnmapNotify 18
-#define MapNotify 19
-
-#define GCForeground (1L<<2)
-#define GCBackground (1L<<3)
-#define GCGraphicsExposures (1L<<16)
-#define GCClipMask (1L<<19)
-
-#define NormalState 1 /* most applications want to start this way */
-#define InputHint (1L << 0)
-#define StateHint (1L << 1)
-#define IconPixmapHint (1L << 2)
-#define IconMaskHint (1L << 5)
-#define PSize (1L << 3) /* program specified size */
-#define PMinSize (1L << 4) /* program specified minimum size */
-#define PMaxSize (1L << 5) /* program specified maximum size */
-
-#define XpmSuccess 0
-#define XpmOpenFailed -1
-#define XpmFileInvalid -2
-#define XpmNoMemory -3
-#define XpmColorFailed -4
-#define XpmCloseness (1L<<12)
-
-#define BitmapSuccess 0
-#define BitmapOpenFailed 1
-#define BitmapFileInvalid 2
-#define BitmapNoMemory 3
-
-#define ZPixmap 2 /* depth == drawable depth */
-
-#define DefaultScreen(dpy) (((_XPrivDisplay)dpy)->default_screen)
-#define DefaultColormap(dpy, scr)(ScreenOfDisplay(dpy,scr)->cmap)
-#define ScreenOfDisplay(dpy, scr)(&((_XPrivDisplay)dpy)->screens[scr])
-#define BlackPixel(dpy, scr) (ScreenOfDisplay(dpy,scr)->black_pixel)
-#define WhitePixel(dpy, scr) (ScreenOfDisplay(dpy,scr)->white_pixel)
-#define RootWindow(dpy, scr) (ScreenOfDisplay(dpy,scr)->root)
-#define AllPlanes ((unsigned long)~0L)
-
-#define XGetPixel(ximage, x, y) \
- ((*((ximage)->f.get_pixel))((ximage), (x), (y)))
-
-typedef unsigned long Pixel; /* Index into colormap */
-typedef unsigned long XID;
-typedef XID Window;
-typedef XID Drawable;
-typedef XID Pixmap;
-typedef XID Colormap;
-typedef XID KeySym;
-typedef XID GContext;
-typedef struct _XDisplay Display;
-
-typedef struct _XGC
-{
- GContext gid; /* protocol ID for graphics context */
-} *GC;
-
-typedef struct {
- Colormap cmap; /* default color map */
- Window root; /* Root window id. */
- unsigned long white_pixel;
- unsigned long black_pixel; /* White and Black pixel values */
- int x;
- int y;
- unsigned int width;
- unsigned int height;
- BITMAP *video_bitmap;
-} Screen;
-
-typedef struct _XDisplay
-{
- int default_screen; /* default screen for operations */
- Screen *screens; /* pointer to list of screens */
- BITMAP *mouse_ptr;
-} *_XPrivDisplay;
-
-typedef struct _XImage {
- struct funcs {
- unsigned long (*get_pixel) (struct _XImage *, int, int);
- } f;
-} XImage;
-
-typedef struct {
- long flags; /* marks which fields in this structure are defined */
- int width, height; /* should set so old wm's don't mess up */
- int min_width, min_height;
- int max_width, max_height;
-} XSizeHints;
-
-typedef struct {
- long flags; /* marks which fields in this structure are defined */
- Bool input; /* does this application rely on the window manager to
- get keyboard input? */
- int initial_state; /* see below */
- Pixmap icon_pixmap; /* pixmap to be used as icon */
- Pixmap icon_mask; /* icon mask bitmap */
-} XWMHints;
-
-typedef struct {
- char *res_name;
- char *res_class;
-} XClassHint;
-
-typedef struct {
- unsigned char *value; /* same as Property routines */
-} XTextProperty;
-
-typedef struct {
- unsigned long foreground;/* foreground pixel */
- unsigned long background;/* background pixel */
- Bool graphics_exposures;/* boolean, should exposures be generated */
- Pixmap clip_mask; /* bitmap clipping; other calls for rects */
- int clip_x_origin; /* origin for clipping */
- int clip_y_origin;
- unsigned long value_mask;
-} XGCValues;
-
-typedef struct {
- unsigned long valuemask; /* Specifies which attributes are */
- unsigned int closeness; /* Allowable RGB deviation */
- Pixel *pixels; /* List of used color pixels */
- unsigned int npixels; /* Number of used pixels */
-} XpmAttributes;
-
-typedef struct {
- int type;
- int x, y;
- int width, height;
-} XExposeEvent;
-
-typedef struct {
- int type; /* of event */
- int x, y; /* pointer x, y coordinates in event window */
- unsigned int button; /* detail */
-} XButtonEvent;
-
-typedef struct {
- int type;
- int x, y; /* pointer x, y coordinates in event window */
-} XMotionEvent;
-
-typedef struct {
- int type; /* of event */
- unsigned int state; /* key or button mask */
-} XKeyEvent;
-
-typedef struct {
- int type; /* FocusIn or FocusOut */
-} XFocusChangeEvent;
-
-
-typedef union _XEvent {
- int type; /* must not be changed; first element */
- XExposeEvent xexpose;
- XButtonEvent xbutton;
- XMotionEvent xmotion;
- XKeyEvent xkey;
-} XEvent;
-
-
-extern void XMapWindow(Display*, Window);
-// extern void XFlush(Display*);
-extern Display *XOpenDisplay(char*);
-// extern char *XDisplayName(char*);
-extern Window XCreateSimpleWindow(Display*, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned long, unsigned long);
-extern int XReadBitmapFile(Display*, Drawable, char*, unsigned int*, unsigned int*, Pixmap*, int*, int*);
-extern Status XStringListToTextProperty(char**, int, XTextProperty*);
-// extern void XSetWMProperties(Display*, Window, XTextProperty*, XTextProperty*, char**, int, XSizeHints*, XWMHints*, XClassHint*);
-extern void XFree(void*);
-// extern void XSelectInput(Display*, Window, long);
-extern GC XCreateGC(Display*, Drawable, unsigned long, XGCValues*);
-extern void XFillRectangle(Display*, Drawable, GC, int, int, unsigned int, unsigned int);
-extern Pixmap XCreatePixmap(Display*, Drawable, unsigned int, unsigned int, unsigned int);
-// extern int XDefaultDepth(Display*, int);
-extern inline void XCopyArea(Display*, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int);
-extern int XpmReadFileToPixmap(Display*, Drawable, char*, Pixmap*, Pixmap*, XpmAttributes*);
-// extern void XFreeColors(Display*, Colormap, unsigned long*, int, unsigned long);
-// extern void XpmFreeAttributes(XpmAttributes*);
-extern void XFreePixmap(Display*, Pixmap);
-extern void XFreeGC(Display*, GC);
-extern void XCloseDisplay(Display*);
-extern int XPending(Display*);
-extern void XNextEvent(Display*, XEvent*);
-// extern void XSync(Display*, Bool);
-// extern void XAutoRepeatOn(Display*);
-// extern void XAutoRepeatOff(Display*);
-extern KeySym XLookupKeysym(XKeyEvent*, int);
-// extern void XSetClipOrigin(Display*, GC, int, int);
-// extern XImage *XGetImage(Display*, Drawable, int, int, unsigned int, unsigned int, unsigned long, int);
-
-BITMAP *load_gif(char *filename, RGB *pal);
--- /dev/null
+/*
+ * A server for a multi-player version of Tetris
+ *
+ * Copyright (C) 1996 Roger Espel Llima <roger.espel.llima@pobox.com>
+ *
+ * Started: 10 Oct 1996
+ *
+ * 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. See the file COPYING for details.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include "netserv.h"
+#include "misc.h"
+
+static int clients = 0;
+static int bots = 0;
+static int onceonly = 0;
+static int timetoplay = 0;
+static int is_daemon = 0;
+static int levelnr = 5;
+static int mode = -1;
+static int paused = 0;
+
+struct user
+{
+ int fd;
+ unsigned char nick[16];
+ unsigned char number;
+ struct user *next, *nextvictim;
+ char active;
+ char introduced;
+ unsigned char readbuf[MAX_BUFFER_SIZE];
+ int nread;
+ unsigned char writbuf[MAX_BUFFER_SIZE];
+ int nwrite;
+ char playing;
+ char isbot;
+ int lines;
+ unsigned int games;
+ unsigned char action;
+ int action_received;
+};
+
+static struct user *user0 = NULL;
+
+#define NEXT(u) ((u)->next ? (u)->next : user0)
+
+static struct sockaddr_in saddr;
+static int lfd;
+static unsigned char realbuf[512], *buf = realbuf + 4;
+
+static int interrupt;
+static int tcp = -1;
+
+static unsigned long frame_counter = 0;
+
+static fd_set fds;
+
+static void syserr(char *s)
+{
+ if (!is_daemon)
+ fprintf(stderr, "fatal: %s failed.\n", s);
+ exit(1);
+}
+
+static void addtobuffer(struct user *u, unsigned char *b, int len)
+{
+ if (u->nwrite + len >= MAX_BUFFER_SIZE)
+ Error(ERR_EXIT, "internal error: network send buffer overflow");
+
+ memcpy(u->writbuf + u->nwrite, b, len);
+ u->nwrite += len;
+}
+
+static void flushuser(struct user *u)
+{
+ if (u->nwrite)
+ {
+ write(u->fd, u->writbuf, u->nwrite);
+ u->nwrite = 0;
+ }
+}
+
+static void broadcast(struct user *except, int len, int activeonly)
+{
+ struct user *u;
+
+ realbuf[0] = realbuf[1] = realbuf[2] = 0;
+ realbuf[3] = (unsigned char)len;
+ for (u=user0; u; u=u->next)
+ if (u != except && (u->active || !activeonly) && u->introduced)
+ addtobuffer(u, realbuf, 4 + len);
+}
+
+static void sendtoone(struct user *to, int len)
+{
+ realbuf[0] = realbuf[1] = realbuf[2] = 0;
+ realbuf[3] = (unsigned char)len;
+ addtobuffer(to, realbuf, 4 + len);
+}
+
+static void dropuser(struct user *u)
+{
+ struct user *v, *w;
+
+ if (options.verbose)
+ printf("RND_SERVER: dropping client %d (%s)\n", u->number, u->nick);
+
+ if (u == user0)
+ user0 = u->next;
+ else
+ {
+ for (v=user0; v; v=v->next)
+ {
+ if (v->next && v->next == u)
+ {
+ v->next = u->next;
+ break;
+ }
+ }
+ }
+ close(u->fd);
+
+ if (u->introduced)
+ {
+ buf[0] = u->number;
+ buf[1] = OP_PLAYER_DISCONNECTED;
+ broadcast(u, 2, 0);
+ }
+
+ for (v=user0; v; v=v->next)
+ {
+ if (v->nextvictim == u)
+ {
+ for (w=NEXT(v); w!=v; w=NEXT(w))
+ {
+ if (w->active && w->playing)
+ {
+ v->nextvictim = w;
+ break;
+ }
+ }
+ if (v->nextvictim == u)
+ v->nextvictim = NULL;
+ }
+ }
+
+ if (u->isbot)
+ bots--;
+
+ free(u);
+ clients--;
+
+ if (onceonly && clients == bots)
+ {
+ if (options.verbose)
+ {
+ printf("RND_SERVER: no clients left\n");
+ printf("RND_SERVER: aborting\n");
+ }
+ exit(0);
+ }
+
+ if (clients == 0)
+ {
+ mode = -1;
+ levelnr = 5;
+ timetoplay = 0;
+ }
+}
+
+static void new_connect(int fd)
+{
+ struct user *u, *v;
+ unsigned char nxn;
+
+ u = checked_malloc(sizeof (struct user));
+
+ u->fd = fd;
+ u->nick[0] = 0;
+ u->next = user0;
+ u->nextvictim = NULL;
+ u->active = 0;
+ u->nread = 0;
+ u->nwrite = 0;
+ u->playing = 0;
+ u->isbot = 0;
+ u->introduced = 0;
+ u->games = 0;
+ u->action = 0;
+ u->action_received = 0;
+
+ user0 = u;
+
+ nxn = 1;
+
+ again:
+ v = u->next;
+ while(v)
+ {
+ if (v->number == nxn)
+ {
+ nxn++;
+ goto again;
+ }
+ v = v->next;
+ }
+
+ u->number = nxn;
+ if (options.verbose)
+ printf("RND_SERVER: client %d connecting from %s\n", nxn, inet_ntoa(saddr.sin_addr));
+ clients++;
+
+ buf[0] = 0;
+ buf[1] = OP_YOUR_NUMBER;
+ buf[2] = u->number;
+ sendtoone(u, 3);
+}
+
+static void Handle_OP_PROTOCOL_VERSION(struct user *u, unsigned int len)
+{
+ if (len != 5 || buf[2] != PROT_VERS_1 || buf[3] != PROT_VERS_2)
+ {
+ if (options.verbose)
+ printf("RND_SERVER: client %d (%s) has wrong protocol version %d.%d.%d\n", u->number, u->nick, buf[2], buf[3], buf[4]);
+
+ buf[0] = 0;
+ buf[1] = OP_BADVERS;
+ buf[2] = PROT_VERS_1;
+ buf[3] = PROT_VERS_2;
+ buf[4] = PROT_VERS_3;
+ sendtoone(u, 5);
+ flushuser(u);
+
+ dropuser(u);
+ interrupt = 1;
+ }
+ else
+ {
+ if (options.verbose)
+ printf("RND_SERVER: client %d (%s) uses protocol version %d.%d.%d\n", u->number, u->nick, buf[2], buf[3], buf[4]);
+ }
+}
+
+static void Handle_OP_NUMBER_WANTED(struct user *u)
+{
+ struct user *v;
+ int client_nr = u->number;
+ int nr_wanted = buf[2];
+ int nr_is_free = 1;
+
+ if (options.verbose)
+ printf("RND_SERVER: client %d (%s) wants to switch to # %d\n",
+ u->number, u->nick, nr_wanted);
+
+ for (v=user0; v; v=v->next)
+ {
+ if (v->number == nr_wanted)
+ {
+ nr_is_free = 0;
+ break;
+ }
+ }
+
+ if (options.verbose)
+ {
+ if (nr_is_free)
+ printf("RND_SERVER: client %d (%s) switches to # %d\n",
+ u->number, u->nick, nr_wanted);
+ else if (u->number == nr_wanted)
+ printf("RND_SERVER: client %d (%s) still has # %d\n",
+ u->number, u->nick, nr_wanted);
+ else
+ printf("RND_SERVER: client %d (%s) cannot switch (client %d still exists)\n",
+ u->number, u->nick, nr_wanted);
+ }
+
+ if (nr_is_free)
+ u->number = nr_wanted;
+
+ buf[0] = client_nr;
+ buf[1] = OP_NUMBER_WANTED;
+ buf[2] = nr_wanted;
+ buf[3] = u->number;
+
+ /*
+ sendtoone(u, 4);
+ */
+
+ broadcast(NULL, 4, 0);
+}
+
+static void Handle_OP_NICKNAME(struct user *u, unsigned int len)
+{
+ struct user *v;
+ int i;
+
+ if (len>16)
+ len=16;
+ memcpy(u->nick, &buf[2], len-2);
+ u->nick[len-2] = 0;
+ for (i=0; i<len-2; i++)
+ {
+ if (u->nick[i] < ' ' ||
+ (u->nick[i] > 0x7e && u->nick[i] <= 0xa0))
+ {
+ u->nick[i] = 0;
+ break;
+ }
+ }
+
+ if (!u->introduced)
+ {
+ buf[0] = u->number;
+ buf[1] = OP_PLAYER_CONNECTED;
+ broadcast(u, 2, 0);
+ }
+
+ if (options.verbose)
+ printf("RND_SERVER: client %d calls itself \"%s\"\n", u->number, u->nick);
+ buf[1] = OP_NICKNAME;
+ broadcast(u, len, 0);
+
+ if (!u->introduced)
+ {
+ for (v=user0; v; v=v->next)
+ {
+ if (v != u && v->introduced)
+ {
+ buf[0] = v->number;
+ buf[1] = OP_PLAYER_CONNECTED;
+ buf[2] = (v->games >> 8);
+ buf[3] = (v->games & 0xff);
+ sendtoone(u, 4);
+ buf[1] = OP_NICKNAME;
+ memcpy(&buf[2], v->nick, 14);
+ sendtoone(u, 2+strlen(v->nick));
+ }
+ }
+ if (levelnr != 5)
+ {
+ buf[0] = 0;
+ buf[1] = OP_LEVEL;
+ buf[2] = levelnr;
+ sendtoone(u, 3);
+ }
+ if (mode >= 0)
+ {
+ buf[1] = OP_MODE;
+ buf[2] = mode;
+ sendtoone(u, 3);
+ }
+ }
+
+ u->introduced = 1;
+}
+
+static void Handle_OP_START_PLAYING(struct user *u)
+{
+ struct user *v, *w;
+
+ if (options.verbose)
+ printf("RND_SERVER: client %d (%s) starts game [level %d from levedir %d (%s)]\n",
+ u->number, u->nick,
+ (buf[2] << 8) + buf[3],
+ (buf[4] << 8) + buf[5],
+ &buf[6]);
+ timetoplay = 0;
+
+ for (w=user0; w; w=w->next)
+ {
+ if (w->introduced)
+ {
+ w->active = 1;
+ w->playing = 1;
+ w->lines = 0;
+ w->nextvictim = NULL;
+ for (v=NEXT(w); v!=w; v=NEXT(v))
+ {
+ if (v->introduced)
+ {
+ w->nextvictim = v;
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ if (paused)
+ {
+ paused = 0;
+ buf[1] = OP_CONT;
+ broadcast(NULL, 2, 0);
+ }
+ buf[1] = OP_START_PLAYING;
+ broadcast(NULL, 2, 0);
+ */
+
+ /* reset frame counter */
+ frame_counter = 0;
+
+ /* reset player actions */
+ for (v=user0; v; v=v->next)
+ {
+ v->action = 0;
+ v->action_received = 0;
+ }
+
+ broadcast(NULL, 10 + strlen(&buf[10])+1, 0);
+}
+
+static void Handle_OP_PAUSE_PLAYING(struct user *u)
+{
+ if (options.verbose)
+ printf("RND_SERVER: client %d (%s) pauses game\n", u->number, u->nick);
+ broadcast(NULL, 2, 0);
+ paused = 1;
+}
+
+static void Handle_OP_CONTINUE_PLAYING(struct user *u)
+{
+ if (options.verbose)
+ printf("RND_SERVER: client %d (%s) continues game\n", u->number, u->nick);
+ broadcast(NULL, 2, 0);
+ paused = 0;
+}
+
+static void Handle_OP_STOP_PLAYING(struct user *u)
+{
+ if (options.verbose)
+ printf("RND_SERVER: client %d (%s) stops game\n", u->number, u->nick);
+ broadcast(NULL, 2, 0);
+}
+
+static void Handle_OP_MOVE_FIGURE(struct user *u)
+{
+ struct user *v;
+ int last_client_nr = 0;
+ int i;
+
+ /* store player action */
+ for (v=user0; v; v=v->next)
+ {
+ if (v->number == u->number)
+ {
+ v->action = buf[2];
+ v->action_received = 1;
+ }
+ }
+
+ /* check if server received action from each player */
+ for (v=user0; v; v=v->next)
+ {
+ if (!v->action_received)
+ return;
+
+ if (v->number > last_client_nr)
+ last_client_nr = v->number;
+ }
+
+ /* initialize all player actions to zero */
+ for (i=0; i<last_client_nr; i++)
+ buf[6 + i] = 0;
+
+ /* broadcast actions of all players to all players */
+ for (v=user0; v; v=v->next)
+ {
+ buf[6 + v->number-1] = v->action;
+ v->action = 0;
+ v->action_received = 0;
+ }
+
+ buf[2] = (unsigned char)((frame_counter >> 24) & 0xff);
+ buf[3] = (unsigned char)((frame_counter >> 16) & 0xff);
+ buf[4] = (unsigned char)((frame_counter >> 8) & 0xff);
+ buf[5] = (unsigned char)((frame_counter >> 0) & 0xff);
+
+ broadcast(NULL, 6 + last_client_nr, 0);
+
+ frame_counter++;
+
+ /*
+ if (verbose)
+ printf("RND_SERVER: frame %d: client %d (%s) moves player [0x%02x]\n",
+ frame_counter,
+ u->number, u->nick, buf[2]);
+ */
+}
+
+void NetworkServer(int port, int serveronly)
+{
+ int i, sl, on;
+ struct user *u, *v, *w;
+ int mfd;
+ int r;
+ unsigned int len;
+ struct protoent *tcpproto;
+ struct timeval tv;
+ int is_daemon = 0;
+
+#ifndef NeXT
+ struct sigaction sact;
+#endif
+
+ if (port == 0)
+ port = DEFAULTPORT;
+
+ if (!serveronly)
+ onceonly = 1;
+
+ if ((tcpproto = getprotobyname("tcp")) != NULL)
+ tcp = tcpproto->p_proto;
+
+#ifdef NeXT
+ signal(SIGPIPE, SIG_IGN);
+#else
+ sact.sa_handler = SIG_IGN;
+ sigemptyset(&sact.sa_mask);
+ sact.sa_flags = 0;
+ sigaction(SIGPIPE, &sact, NULL);
+#endif
+
+
+ lfd = socket(PF_INET, SOCK_STREAM, 0);
+ saddr.sin_family = AF_INET;
+ saddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ saddr.sin_port = htons(port);
+
+ if (lfd < 0)
+ syserr("socket");
+ on = 1;
+
+ setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(int));
+ if (bind(lfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
+ syserr("bind");
+
+ listen(lfd, 5);
+
+ if (is_daemon)
+ {
+ /* become a daemon, breaking all ties with the controlling terminal */
+ options.verbose = 0;
+ for (i=0; i<255; i++)
+ {
+ if (i != lfd)
+ close(i);
+ }
+
+ if (fork())
+ exit(0);
+ setsid();
+ if (fork())
+ exit(0);
+ chdir("/");
+
+ /* open a fake stdin, stdout, stderr, just in case */
+ open("/dev/null", O_RDONLY);
+ open("/dev/null", O_WRONLY);
+ open("/dev/null", O_WRONLY);
+ }
+
+ if (options.verbose)
+ {
+ printf("rocksndiamonds network server: started up, listening on port %d\n",
+ port);
+ printf("rocksndiamonds network server: using protocol version %d.%d.%d\n",
+ PROT_VERS_1, PROT_VERS_2, PROT_VERS_3);
+ }
+
+ while(1)
+ {
+ interrupt = 0;
+
+ /*
+ if (timetoplay && time(NULL) >= timetoplay)
+ {
+ buf[0] = 0;
+ do_play();
+ if (options.verbose)
+ printf("RND_SERVER: everyone lost... restarting game\n");
+ timetoplay = 0;
+ }
+ */
+
+ for (u=user0; u; u=u->next)
+ flushuser(u);
+
+ FD_ZERO(&fds);
+ mfd = lfd;
+ u = user0;
+ while (u)
+ {
+ FD_SET(u->fd, &fds);
+ if (u->fd > mfd)
+ mfd = u->fd;
+ u = u->next;
+ }
+ FD_SET(lfd, &fds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 500000;
+ if ((sl = select(mfd + 1, &fds, NULL, NULL, &tv)) < 0)
+ {
+ if (errno != EINTR)
+ syserr("select");
+ else
+ continue;
+ }
+
+ if (sl < 0)
+ continue;
+
+ if (clients > 0 && clients == bots)
+ {
+ if (options.verbose)
+ printf("RND_SERVER: only bots left... dropping all bots\n");
+ while (user0)
+ dropuser(user0);
+ continue;
+ }
+
+ if (sl == 0)
+ continue;
+
+ if (FD_ISSET(lfd, &fds))
+ {
+ int newfd, slen;
+
+ slen = sizeof(saddr);
+ newfd = accept(lfd, (struct sockaddr *)&saddr, &slen);
+ if (newfd < 0)
+ {
+ if (errno != EINTR)
+ syserr("accept");
+ }
+ else
+ {
+ if (tcp != -1)
+ {
+ on = 1;
+ setsockopt(newfd, tcp, TCP_NODELAY, (char *)&on, sizeof(int));
+ }
+ new_connect(newfd);
+ }
+ continue;
+ }
+
+ u = user0;
+
+ do
+ {
+ if (FD_ISSET(u->fd, &fds))
+ {
+ r = read(u->fd, u->readbuf + u->nread, MAX_BUFFER_SIZE - u->nread);
+ if (r <= 0)
+ {
+ if (options.verbose)
+ printf("RND_SERVER: EOF from client %d (%s)\n", u->number, u->nick);
+ dropuser(u);
+ interrupt = 1;
+ break;
+ }
+ u->nread += r;
+ while (u->nread >= 4 && u->nread >= 4 + u->readbuf[3])
+ {
+ len = u->readbuf[3];
+ if (u->readbuf[0] || u->readbuf[1] || u->readbuf[2])
+ {
+ if (options.verbose)
+ printf("RND_SERVER: crap from client %d (%s)\n", u->number, u->nick);
+ write(u->fd, "\033]50;kanji24\007\033#8\033(0", 19);
+ dropuser(u);
+ interrupt = 1;
+ break;
+ }
+ memcpy(buf, &u->readbuf[4], len);
+ u->nread -= 4 + len;
+ memmove(u->readbuf, u->readbuf + 4 + len, u->nread);
+
+ buf[0] = u->number;
+ if (!u->introduced && buf[1] != OP_NICKNAME)
+ {
+ if (options.verbose)
+ printf("RND_SERVER: !(client %d)->introduced && buf[1]==%d (expected OP_NICKNAME)\n", buf[0], buf[1]);
+
+ dropuser(u);
+ interrupt = 1;
+ break;
+ }
+
+ switch(buf[1])
+ {
+ case OP_NICKNAME:
+ Handle_OP_NICKNAME(u, len);
+ break;
+
+ case OP_PROTOCOL_VERSION:
+ Handle_OP_PROTOCOL_VERSION(u, len);
+ break;
+
+ case OP_NUMBER_WANTED:
+ Handle_OP_NUMBER_WANTED(u);
+ break;
+
+ case OP_START_PLAYING:
+ Handle_OP_START_PLAYING(u);
+ break;
+
+ case OP_PAUSE_PLAYING:
+ Handle_OP_PAUSE_PLAYING(u);
+ break;
+
+ case OP_CONTINUE_PLAYING:
+ Handle_OP_CONTINUE_PLAYING(u);
+ break;
+
+ case OP_STOP_PLAYING:
+ Handle_OP_STOP_PLAYING(u);
+ break;
+
+ case OP_MOVE_FIGURE:
+ Handle_OP_MOVE_FIGURE(u);
+ break;
+
+ case OP_KILL:
+ for (v=user0; v; v=v->next)
+ {
+ if (v->number == buf[2])
+ break;
+ }
+ if (v)
+ {
+ if (v->isbot)
+ {
+ if (options.verbose)
+ printf("RND_SERVER: client %d (%s) kills bot %d (%s)\n", u->number, u->nick, v->number, v->nick);
+
+ dropuser(v);
+ interrupt = 1;
+ break;
+ }
+ else
+ {
+ if (options.verbose)
+ printf("RND_SERVER: client %d (%s) attempting to kill non-bot %d (%s)\n", u->number, u->nick, v->number, v->nick);
+ }
+ }
+ break;
+
+ case OP_MODE:
+ mode = buf[2];
+ if (options.verbose)
+ printf("RND_SERVER: client %d (%s) sets mode %d (%s)\n", u->number, u->nick, buf[2], buf[2] == 0 ? "normal" : (buf[2] == 1 ? "fun" : "unknown"));
+ broadcast(NULL, 3, 0);
+ break;
+
+ case OP_BOT:
+ if (!u->isbot)
+ bots++;
+ u->isbot = 1;
+ if (options.verbose)
+ printf("RND_SERVER: client %d (%s) declares itself to be a bot\n", u->number, u->nick);
+ break;
+
+ case OP_LEVEL:
+ levelnr = buf[2];
+ if (options.verbose)
+ printf("RND_SERVER: client %d (%s) sets level %d\n", u->number, u->nick, buf[2]);
+ broadcast(NULL, 3, 0);
+ break;
+
+ case OP_LOST:
+ {
+ struct user *won = NULL;
+
+ if (options.verbose)
+ printf("RND_SERVER: client %d (%s) has lost\n", u->number, u->nick);
+ u->playing = 0;
+ broadcast(u, 2, 1);
+ i = 0;
+ for (v=user0; v; v=v->next)
+ {
+ if (v->nextvictim == u)
+ {
+ for (w=NEXT(v); w!=v; w=NEXT(w))
+ {
+ if (w->active && w->playing)
+ {
+ v->nextvictim = w;
+ break;
+ }
+ }
+ if (v->nextvictim == u)
+ v->nextvictim = NULL;
+ }
+ }
+ for (v=user0; v; v=v->next)
+ {
+ if (v->playing)
+ {
+ i++;
+ won = v;
+ }
+ }
+ if (i == 1)
+ {
+ buf[0] = won->number;
+ buf[1] = OP_WON;
+ won->games++;
+ broadcast(NULL, 2, 0);
+ }
+ else if (i == 0)
+ {
+ buf[0] = u->number;
+ buf[1] = OP_WON;
+ u->games++;
+ broadcast(NULL, 2, 0);
+ }
+ if (i < 2 && clients > 1)
+ timetoplay = time(NULL) + 4;
+ }
+ break;
+
+ case OP_ZERO:
+ broadcast(NULL, 2, 0);
+ if (options.verbose)
+ printf("RND_SERVER: client %d (%s) resets the game counters\n", u->number, u->nick);
+ for (v=user0; v; v=v->next)
+ v->games = 0;
+ break;
+
+ case OP_CLEAR:
+ case OP_GROW:
+ broadcast(u, 2, 1);
+ break;
+
+ case OP_MSG:
+ buf[len] = '\0';
+ if (options.verbose)
+ printf("RND_SERVER: client %d (%s) sends message: %s\n", u->number, u->nick, &buf[2]);
+ broadcast(u, len, 0);
+ break;
+
+ case OP_LINES:
+ if (len != 3)
+ {
+ if (options.verbose)
+ printf("RND_SERVER: client %d (%s) sends crap for an OP_LINES\n", u->number, u->nick);
+
+ dropuser(u);
+ interrupt = 1;
+ break;
+ }
+ if (u->nextvictim)
+ {
+ if (options.verbose)
+ printf("RND_SERVER: client %d (%s) sends %d %s to client %d (%s)\n", u->number, u->nick, (int)buf[2], buf[2] == 1 ? "line" : "lines", u->nextvictim->number, u->nextvictim->nick);
+ sendtoone(u->nextvictim, 3);
+ buf[3] = u->nextvictim->number;
+ buf[1] = OP_LINESTO;
+ broadcast(u->nextvictim, 4, 1);
+ for (v=NEXT(u->nextvictim); v!=u->nextvictim; v=NEXT(v))
+ {
+ if (v->active && v != u && v->playing)
+ {
+ u->nextvictim = v;
+ break;
+ }
+ }
+ }
+ else if (options.verbose)
+ printf("RND_SERVER: client %d (%s) makes %d %s but has no victim\n", u->number, u->nick, (int)buf[2], buf[2] == 1 ? "line" : "lines");
+ break;
+
+ default:
+ if (options.verbose)
+ printf("RND_SERVER: opcode %d from client %d (%s) not understood\n", buf[0], u->number, u->nick);
+ }
+ }
+ }
+
+ if (u && !interrupt)
+ u = u->next;
+ }
+ while (u && !interrupt);
+ }
+}
+++ /dev/null
-
-/* new.c */
-
-#include "image.h"
-#include "misc.h"
+++ /dev/null
-
-/* send.c */
-
-#include "xli.h"
-
-/* extra colors to try allocating in private color maps to minimise flashing */
-#define NOFLASH_COLORS 256
-
-Image *monochrome(Image *cimage)
-{
- Image *image;
- unsigned char *sp, *dp, *dp2; /* data pointers */
- unsigned int spl; /* source pixel length in bytes */
- unsigned int dll; /* destination line length in bytes */
- Pixel color; /* pixel color */
- unsigned int x, y; /* random counters */
- int bitmap_pixel;
-
- if (BITMAPP(cimage))
- return(NULL);
-
- /*
- printf(" Converting to monochrome...");
- fflush(stdout);
- */
-
- image= newBitImage(cimage->width, cimage->height);
- if (cimage->title)
- {
- image->title= (char *)lmalloc(strlen(cimage->title) + 13);
- sprintf(image->title, "%s (monochrome)", cimage->title);
- }
-
- spl = cimage->pixlen;
- dll = (image->width / 8) + (image->width % 8 ? 1 : 0);
-
- sp = cimage->data;
- dp = image->data;
-
- for (y= 0; y < cimage->height; y++)
- {
- for (x= 0; x < cimage->width; x++)
- {
- dp2 = dp + (x / 8); /* dp + x/8 */
- color= memToVal(sp, spl);
-
- if (cimage->rgb.red[color] > 0x0000 ||
- cimage->rgb.green[color] > 0x0000 ||
- cimage->rgb.blue[color] > 0x0000)
- bitmap_pixel = 0x00;
- else
- bitmap_pixel = 0x80;
-
- *dp2 |= bitmap_pixel >> ( x % 8);
- sp += spl;
- }
-
- dp += dll; /* next row */
- }
-
- /*
- printf("done\n");
- */
-
- return(image);
-}
-
-static unsigned int *buildIndex(unsigned int width,
- unsigned int zoom,
- unsigned int *rwidth)
-{
- float fzoom;
- unsigned int *index;
- unsigned int a;
-
- if (!zoom)
- {
- fzoom= 100.0;
- *rwidth= width;
- }
- else
- {
- fzoom= (float)zoom / 100.0;
- *rwidth= (unsigned int)(fzoom * width + 0.5);
- }
- index= (unsigned int *)lmalloc(sizeof(unsigned int) * *rwidth);
- for (a= 0; a < *rwidth; a++)
- {
- if (zoom)
- *(index + a)= (unsigned int)((float)a / fzoom + 0.5);
- else
- *(index + a)= a;
- }
- return(index);
-}
-
-Image *zoom(Image *oimage, unsigned int xzoom, unsigned int yzoom)
-{
- Image *image;
- unsigned int *xindex, *yindex;
- unsigned int xwidth, ywidth;
- unsigned int x, y, xsrc, ysrc;
- unsigned int pixlen;
- unsigned int srclinelen;
- unsigned int destlinelen;
- byte *srcline, *srcptr;
- byte *destline, *destptr;
- byte srcmask, destmask, bit;
- Pixel value;
-
- if ((!xzoom || xzoom==100) && (!yzoom || yzoom==100))
- return(oimage);
-
- if (!xzoom)
- printf(" Zooming image Y axis by %d%%...", yzoom);
- else if (!yzoom)
- printf(" Zooming image X axis by %d%%...", xzoom);
- else if (xzoom == yzoom)
- printf(" Zooming image by %d%%...", xzoom);
- else
- printf(" Zooming image X axis by %d%% and Y axis by %d%%...",
- xzoom, yzoom);
- fflush(stdout);
-
- xindex= buildIndex(oimage->width, xzoom, &xwidth);
- yindex= buildIndex(oimage->height, yzoom, &ywidth);
-
- switch (oimage->type)
- {
- case IBITMAP:
- image= newBitImage(xwidth, ywidth);
- for (x= 0; x < oimage->rgb.used; x++)
- {
- *(image->rgb.red + x)= *(oimage->rgb.red + x);
- *(image->rgb.green + x)= *(oimage->rgb.green + x);
- *(image->rgb.blue + x)= *(oimage->rgb.blue + x);
- }
- image->rgb.used= oimage->rgb.used;
- destline= image->data;
- destlinelen= (xwidth / 8) + (xwidth % 8 ? 1 : 0);
- srcline= oimage->data;
- srclinelen= (oimage->width / 8) + (oimage->width % 8 ? 1 : 0);
- for (y= 0, ysrc= *(yindex + y); y < ywidth; y++)
- {
- while (ysrc != *(yindex + y))
- {
- ysrc++;
- srcline += srclinelen;
- }
- srcptr= srcline;
- destptr= destline;
- srcmask= 0x80;
- destmask= 0x80;
- bit= srcmask & *srcptr;
- for (x= 0, xsrc= *(xindex + x); x < xwidth; x++)
- {
- if (xsrc != *(xindex + x))
- {
- do
- {
- xsrc++;
- if (!(srcmask >>= 1))
- {
- srcmask= 0x80;
- srcptr++;
- }
- }
- while (xsrc != *(xindex + x));
-
- bit= srcmask & *srcptr;
- }
- if (bit)
- *destptr |= destmask;
- if (!(destmask >>= 1))
- {
- destmask= 0x80;
- destptr++;
- }
- }
- destline += destlinelen;
- }
- break;
-
- case IRGB:
- image= newRGBImage(xwidth, ywidth, oimage->depth);
- for (x= 0; x < oimage->rgb.used; x++)
- {
- *(image->rgb.red + x)= *(oimage->rgb.red + x);
- *(image->rgb.green + x)= *(oimage->rgb.green + x);
- *(image->rgb.blue + x)= *(oimage->rgb.blue + x);
- }
- image->rgb.used= oimage->rgb.used;
-
- pixlen= oimage->pixlen;
- destptr= image->data;
- srcline= oimage->data;
- srclinelen= oimage->width * pixlen;
- for (y= 0, ysrc= *(yindex + y); y < ywidth; y++)
- {
- while (ysrc != *(yindex + y))
- {
- ysrc++;
- srcline += srclinelen;
- }
-
- srcptr = srcline;
- value = memToVal(srcptr, image->pixlen);
-
- for (x=0, xsrc= *(xindex + x); x<xwidth; x++)
- {
- if (xsrc != *(xindex + x))
- {
- do
- {
- xsrc++;
- srcptr++;
- }
- while (xsrc != *(xindex + x));
- value = memToVal(srcptr, 1);
- }
- valToMem(value, destptr, 1);
- destptr++;
- }
- }
- break;
-
- default:
- /* no zooming */
- return(oimage);
- break;
- }
-
- image->title = dupString(oimage->title);
- free((byte *)xindex);
- free((byte *)yindex);
-
- printf("done\n");
-
- return(image);
-}
-
-void compress(Image *image)
-{
- unsigned char *used, fast[32][32][32];
- unsigned int dmask; /* Depth mask protection */
- Pixel *map;
- unsigned int next_index;
- Intensity *red = image->rgb.red,
- *green = image->rgb.green,
- *blue = image->rgb.blue;
- Intensity r,g,b;
- unsigned int x, y, badcount = 0, dupcount = 0, unusedcount = 0;
- unsigned char *pixptr, *pixend;
-
- if (!RGBP(image) || image->rgb.compressed)
- return;
-
- /*
- printf(" Compressing colormap...");
- fflush(stdout);
- */
-
- used = (unsigned char *)lcalloc(sizeof(unsigned char) * depthToColors(image->depth));
- dmask = (1 << image->depth) -1; /* Mask any illegal bits for that depth */
- map = (Pixel *)lcalloc(sizeof(Pixel) * depthToColors(image->depth));
-
- /* init fast duplicate check table */
- for(r=0;r<32;r++)
- for(g=0;g<32;g++)
- for(b=0;b<32;b++)
- fast[r][g][b] = 0;
-
- /* do pass 1 through the image to check index usage */
-
- pixptr = image->data;
- pixend = pixptr + (image->height * image->width);
- for(;pixptr < pixend; pixptr++)
- used[(*pixptr) & dmask] = 1;
-
- /* count the bad pixels */
- for (x = image->rgb.used; x < depthToColors(image->depth); x++)
- if (used[x])
- badcount++;
-
- /* figure out duplicates and unuseds, and create the new mapping */
- next_index = 0;
- for (x = 0; x < image->rgb.used; x++)
- {
- if (!used[x])
- {
- unusedcount++;
- continue; /* delete this index */
- }
-
- /* check for duplicate */
- r = red[x];
- g = green[x];
- b = blue[x];
- if (fast[r>>11][g>>11][b>>11]) /* if matches fast check */
- {
- /* then do a linear search */
- for (y = x+1; y < image->rgb.used; y++)
- {
- if (r == red[y] && g == green[y] && b == blue[y])
- break;
- }
- if (y < image->rgb.used) /* found match */
- {
- map[x] = y;
- dupcount++;
- continue; /* delete this index */
- }
- fast[r>>11][g>>11][b>>11] = 1;
- }
- /* will map to this index */
- map[x] = next_index;
- next_index++;
- }
-
- /* change the image pixels */
- pixptr = image->data;
- pixend = pixptr + (image->height * image->width);
- for(;pixptr < pixend; pixptr++)
- *pixptr = map[(*pixptr) & dmask];
-
- /* change the colormap */
- for (x = 0; x < image->rgb.used; x++)
- {
- if (!used[x])
- continue;
- red[map[x]] = red[x];
- green[map[x]] = green[x];
- blue[map[x]] = blue[x];
- }
- image->rgb.used = next_index;
-
- /* clean up */
- free(map);
- free(used);
-
- /*
- if (badcount)
- printf("%d out-of-range pixels, ", badcount);
-
- if (!unusedcount && !dupcount)
- printf("no improvment\n");
- else
- {
- if (dupcount)
- printf("%d duplicate%s and %d unused color%s removed...",
- dupcount, (dupcount == 1 ? "" : "s"),
- unusedcount, (unusedcount == 1 ? "" : "s"));
- printf("%d unique color%s\n",
- next_index, (next_index == 1 ? "" : "s"));
- }
- */
-
- image->rgb.compressed= TRUE; /* don't do it again */
-}
-
-
-
-
-Pixmap ximageToPixmap(Display *disp, Window parent, XImageInfo *ximageinfo)
-{
- Pixmap pixmap;
-
- pixmap = XCreatePixmap(disp, parent,
- ximageinfo->ximage->width, ximageinfo->ximage->height,
- ximageinfo->depth);
-
- ximageinfo->drawable = pixmap;
-
- sendXImage(ximageinfo, 0, 0, 0, 0,
- ximageinfo->ximage->width, ximageinfo->ximage->height);
- return(pixmap);
-}
-
-/* find the best pixmap depth supported by the server for a particular
- * visual and return that depth.
- *
- * this is complicated by R3's lack of XListPixmapFormats so we fake it
- * by looking at the structure ourselves.
- */
-
-static unsigned int bitsPerPixelAtDepth(Display *disp, int scrn,
- unsigned int depth)
-{
-#if defined(XlibSpecificationRelease) && (XlibSpecificationRelease >= 4)
- /* the way things are */
- XPixmapFormatValues *xf;
- int nxf, a;
-
- xf = XListPixmapFormats(disp, &nxf);
- for (a = 0; a < nxf; a++)
- {
- if (xf[a].depth == depth)
- {
- int bpp;
- bpp = xf[a].bits_per_pixel;
- XFree(xf);
- return (unsigned int) bpp;
- }
- }
- XFree(xf);
-#else /* the way things were (X11R3) */
- unsigned int a;
-
- for (a= 0; a < disp->nformats; a++)
- if (disp->pixmap_format[a].depth == depth)
- return(disp->pixmap_format[a].bits_per_pixel);
-#endif
-
- /* this should never happen; if it does, we're in trouble
- */
-
- fprintf(stderr, "bitsPerPixelAtDepth: Can't find pixmap depth info!\n");
- exit(1);
-}
-
-XImageInfo *imageToXImage(Display *disp, int scrn, Visual *visual,
- unsigned int ddepth, Image *image)
-{
- static XColor xcolor_private[NOFLASH_COLORS];
- static int colorcell_used[NOFLASH_COLORS];
- static Colormap global_cmap = 0;
- static Pixel *global_cmap_index;
- static int num_cmap_entries, free_cmap_entries;
- static private_cmap = FALSE;
- Pixel *redvalue, *greenvalue, *bluevalue;
- unsigned int a, c=0, x, y, linelen, dpixlen, dbits;
- XColor xcolor;
- XGCValues gcv;
- XImageInfo *ximageinfo;
-
- if (!global_cmap)
- {
- if (visual == DefaultVisual(disp, scrn))
- global_cmap = DefaultColormap(disp, scrn);
- else
- {
- global_cmap = XCreateColormap(disp, RootWindow(disp, scrn),
- visual, AllocNone);
- private_cmap = TRUE;
- }
- }
-
- xcolor.flags = DoRed | DoGreen | DoBlue;
- redvalue = greenvalue = bluevalue = NULL;
- ximageinfo = (XImageInfo *)lmalloc(sizeof(XImageInfo));
- ximageinfo->disp = disp;
- ximageinfo->scrn = scrn;
- ximageinfo->depth = 0;
- ximageinfo->drawable = None;
- ximageinfo->index = NULL;
- ximageinfo->rootimage = FALSE;
- ximageinfo->foreground = ximageinfo->background= 0;
- ximageinfo->gc = NULL;
- ximageinfo->ximage = NULL;
-
- switch (visual->class)
- {
- case TrueColor:
- case DirectColor:
- {
- Pixel pixval;
- unsigned int redcolors, greencolors, bluecolors;
- unsigned int redstep, greenstep, bluestep;
- unsigned int redbottom, greenbottom, bluebottom;
- unsigned int redtop, greentop, bluetop;
-
- redvalue = (Pixel *)lmalloc(sizeof(Pixel) * 256);
- greenvalue = (Pixel *)lmalloc(sizeof(Pixel) * 256);
- bluevalue = (Pixel *)lmalloc(sizeof(Pixel) * 256);
-
- ximageinfo->cmap = global_cmap;
-
- retry_direct: /* tag we hit if a DirectColor allocation fails on
- * default colormap */
-
- /* calculate number of distinct colors in each band
- */
-
- redcolors = greencolors = bluecolors = 1;
- for (pixval=1; pixval; pixval <<= 1)
- {
- if (pixval & visual->red_mask)
- redcolors <<= 1;
- if (pixval & visual->green_mask)
- greencolors <<= 1;
- if (pixval & visual->blue_mask)
- bluecolors <<= 1;
- }
-
- /* sanity check
- */
-
- if ((redcolors > visual->map_entries) ||
- (greencolors > visual->map_entries) ||
- (bluecolors > visual->map_entries))
- {
- fprintf(stderr, "Warning: inconsistency in color information (this may be ugly)\n");
- }
-
- redstep = 256 / redcolors;
- greenstep = 256 / greencolors;
- bluestep = 256 / bluecolors;
- redbottom = greenbottom = bluebottom = 0;
- redtop = greentop = bluetop = 0;
- for (a=0; a<visual->map_entries; a++)
- {
- if (redbottom < 256)
- redtop = redbottom + redstep;
- if (greenbottom < 256)
- greentop = greenbottom + greenstep;
- if (bluebottom < 256)
- bluetop = bluebottom + bluestep;
-
- xcolor.red = (redtop - 1) << 8;
- xcolor.green = (greentop - 1) << 8;
- xcolor.blue = (bluetop - 1) << 8;
- if (!XAllocColor(disp, ximageinfo->cmap, &xcolor))
- {
- /* if an allocation fails for a DirectColor default visual then
- * we should create a private colormap and try again.
- */
-
- if ((visual->class == DirectColor) &&
- (visual == DefaultVisual(disp, scrn)))
- {
- global_cmap = XCopyColormapAndFree(disp, global_cmap);
- ximageinfo->cmap = global_cmap;
- private_cmap = TRUE;
-
- goto retry_direct;
- }
-
- /* something completely unexpected happened
- */
-
- fprintf(stderr, "imageToXImage: XAllocColor failed on a TrueColor/Directcolor visual\n");
- free((byte *)redvalue);
- free((byte *)greenvalue);
- free((byte *)bluevalue);
- free((byte *)ximageinfo);
- return(NULL);
- }
-
- /* fill in pixel values for each band at this intensity
- */
-
- while ((redbottom < 256) && (redbottom < redtop))
- redvalue[redbottom++] = xcolor.pixel & visual->red_mask;
- while ((greenbottom < 256) && (greenbottom < greentop))
- greenvalue[greenbottom++] = xcolor.pixel & visual->green_mask;
- while ((bluebottom < 256) && (bluebottom < bluetop))
- bluevalue[bluebottom++] = xcolor.pixel & visual->blue_mask;
- }
- break;
- }
-
- case PseudoColor:
-
- ximageinfo->cmap = global_cmap;
- ximageinfo->index = (Pixel *)lmalloc(sizeof(Pixel) * image->rgb.used);
-
- for (a=0; a<image->rgb.used; a++)
- {
- XColor xcolor2;
- unsigned short mask;
- int color_found;
- int i;
-
- xcolor.red = *(image->rgb.red + a);
- xcolor.green = *(image->rgb.green + a);
- xcolor.blue = *(image->rgb.blue + a);
-
- /* look if this color already exists in our colormap */
- if (!XAllocColor(disp, ximageinfo->cmap, &xcolor))
- {
- if (!private_cmap)
- {
- /*
- printf("switching to private colormap...\n");
- */
-
- /* we just filled up the default colormap -- get a private one
- which contains all already allocated colors */
-
- global_cmap = XCopyColormapAndFree(disp, global_cmap);
- ximageinfo->cmap = global_cmap;
- private_cmap = TRUE;
-
- /* allocate the rest of the color cells read/write */
- global_cmap_index =
- (Pixel *)lmalloc(sizeof(Pixel) * NOFLASH_COLORS);
- for (i=0; i<NOFLASH_COLORS; i++)
- if (!XAllocColorCells(disp, global_cmap, FALSE, NULL, 0,
- global_cmap_index + i, 1))
- break;
- num_cmap_entries = free_cmap_entries = i;
-
- /*
- printf("We've got %d free colormap entries.\n", free_cmap_entries);
- */
-
- /* to minimize colormap flashing, copy default colors and try
- to keep them as near as possible to the old values */
-
- for(i=0; i<num_cmap_entries; i++)
- {
- xcolor2.pixel = *(global_cmap_index + i);
- XQueryColor(disp, DefaultColormap(disp, scrn), &xcolor2);
- XStoreColor(disp, global_cmap, &xcolor2);
- xcolor_private[xcolor2.pixel] = xcolor2;
- colorcell_used[xcolor2.pixel] = FALSE;
- }
-
- /* now we have the default colormap private: all colors we
- successfully allocated so far are read-only, which is okay,
- because we don't want to change them anymore -- if we need
- an existing color again, we get it by XAllocColor; all other
- colors are read/write and we can set them by XStoreColor,
- but we will try to overwrite those color cells with our new
- color which are as close as possible to our new color */
- }
-
- /* look for an existing default color close the one we want */
-
- mask = 0xf000;
- color_found = FALSE;
-
- while (!color_found)
- {
- for (i=num_cmap_entries-1; i>=0; i--)
- {
- xcolor2.pixel = *(global_cmap_index + i);
- xcolor2 = xcolor_private[xcolor2.pixel];
-
- if (colorcell_used[xcolor2.pixel])
- continue;
-
- if ((xcolor.red & mask) == (xcolor2.red & mask) &&
- (xcolor.green & mask) == (xcolor2.green & mask) &&
- (xcolor.blue & mask) == (xcolor2.blue & mask))
- {
- /*
- printf("replacing color cell %ld with a close color\n",
- xcolor2.pixel);
- */
- color_found = TRUE;
- break;
- }
- }
-
- if (mask == 0x0000)
- break;
-
- mask = (mask << 1) & 0xffff;
- }
-
- if (!color_found) /* no more free color cells */
- {
- printf("Sorry, cannot allocate enough colors!\n");
- exit(0);
- }
-
- xcolor.pixel = xcolor2.pixel;
- xcolor_private[xcolor.pixel] = xcolor;
- colorcell_used[xcolor.pixel] = TRUE;
- XStoreColor(disp, ximageinfo->cmap, &xcolor);
- free_cmap_entries--;
- }
-
- *(ximageinfo->index + a) = xcolor.pixel;
- }
-
- /*
- printf("still %d free colormap entries\n", free_cmap_entries);
- */
-
- ximageinfo->no = a; /* number of pixels allocated for this image */
- break;
-
- default:
- printf("Sorry, only DirectColor, TrueColor and PseudoColor supported\n");
- exit(0);
- break;
- }
-
- /* create an XImage and related colormap based on the image type
- * we have.
- */
-
- /*
- printf(" Building XImage...");
- fflush(stdout);
- */
-
- switch (image->type)
- {
- case IBITMAP:
- {
- byte *data;
-
- /* we copy the data to be more consistent
- */
-
- linelen = ((image->width + 7) / 8);
- data= lmalloc(linelen * image->height);
-
- memcpy((char *)data, (char *)image->data, linelen * image->height);
-
- gcv.function= GXcopy;
- ximageinfo->ximage= XCreateImage(disp, visual, 1, XYBitmap,
- 0, (char *)data, image->width, image->height,
- 8, linelen);
-
- /* use this if you want to use the bitmap as a mask */
- ximageinfo->depth = image->depth;
-
- if(visual->class == DirectColor || visual->class == TrueColor)
- {
- Pixel pixval;
- dbits= bitsPerPixelAtDepth(disp, scrn, ddepth);
- dpixlen= (dbits + 7) / 8;
- pixval= redvalue[image->rgb.red[0] >> 8] |
- greenvalue[image->rgb.green[0] >> 8] |
- bluevalue[image->rgb.blue[0] >> 8];
- ximageinfo->background = pixval;
- pixval= redvalue[image->rgb.red[1] >> 8] |
- greenvalue[image->rgb.green[1] >> 8] |
- bluevalue[image->rgb.blue[1] >> 8];
- ximageinfo->foreground = pixval;
- }
- else /* Not Direct or True Color */
- {
- ximageinfo->foreground = BlackPixel(disp,scrn);
- ximageinfo->background = WhitePixel(disp,scrn);
- }
- ximageinfo->ximage->bitmap_bit_order= MSBFirst;
- ximageinfo->ximage->byte_order= MSBFirst;
-
- break;
- }
-
- case IRGB:
- {
- /* modify image data to match visual and colormap
- */
-
- byte *data, *destptr, *srcptr;
-
- dbits = bitsPerPixelAtDepth(disp, scrn, ddepth); /* bits per pixel */
- dpixlen = (dbits + 7) / 8; /* bytes per pixel */
-
- ximageinfo->ximage = XCreateImage(disp, visual, ddepth, ZPixmap, 0,
- NULL, image->width, image->height,
- 8, image->width * dpixlen);
-
- data = (byte *)lmalloc(image->width * image->height * dpixlen);
- ximageinfo->depth = ddepth;
- ximageinfo->ximage->data = (char *)data;
- ximageinfo->ximage->byte_order = MSBFirst;
- srcptr = image->data;
- destptr = data;
-
- switch (visual->class)
- {
- case DirectColor:
- case TrueColor:
- {
- Pixel pixval;
-
- for (y=0; y<image->height; y++)
- {
- for (x=0; x<image->width; x++)
- {
- pixval = memToVal(srcptr, 1);
- pixval = redvalue[image->rgb.red[pixval] >> 8] |
- greenvalue[image->rgb.green[pixval] >> 8] |
- bluevalue[image->rgb.blue[pixval] >> 8];
- valToMem(pixval, destptr, dpixlen);
- srcptr += 1;
- destptr += dpixlen;
- }
- }
- break;
- }
-
- default:
- {
- if (dpixlen == 1) /* most common */
- {
- for (y=0; y<image->height; y++)
- {
- for (x=0; x<image->width; x++)
- {
- *destptr = ximageinfo->index[c + *srcptr];
- srcptr++;
- destptr++;
- }
- }
- }
- else /* less common */
- {
- for (y=0; y<image->height; y++)
- {
- for (x=0; x<image->width; x++)
- {
- register unsigned long temp;
- temp = memToVal(srcptr, 1);
- valToMem(ximageinfo->index[c + temp], destptr, dpixlen);
- srcptr += 1;
- destptr += dpixlen;
- }
- }
- }
- }
- break;
- }
- }
- }
-
- /*
- printf("done\n");
- */
-
- if (redvalue)
- {
- free((byte *)redvalue);
- free((byte *)greenvalue);
- free((byte *)bluevalue);
- }
-
- return(ximageinfo);
-}
-
-/* Given an XImage and a drawable, move a rectangle from the Ximage
- * to the drawable.
- */
-
-void sendXImage(XImageInfo *ximageinfo,
- int src_x, int src_y, int dst_x, int dst_y,
- unsigned int w, unsigned int h)
-{
- XGCValues gcv;
-
- /* build and cache the GC
- */
-
- if (!ximageinfo->gc)
- {
- gcv.function = GXcopy;
- if (ximageinfo->ximage->depth == 1)
- {
- gcv.foreground = ximageinfo->foreground;
- gcv.background = ximageinfo->background;
- ximageinfo->gc = XCreateGC(ximageinfo->disp, ximageinfo->drawable,
- GCFunction | GCForeground | GCBackground,
- &gcv);
- }
- else
- ximageinfo->gc = XCreateGC(ximageinfo->disp, ximageinfo->drawable,
- GCFunction, &gcv);
- }
-
- XPutImage(ximageinfo->disp, ximageinfo->drawable, ximageinfo->gc,
- ximageinfo->ximage, src_x, src_y, dst_x, dst_y, w, h);
-}
-
-/* free up anything cached in the local Ximage structure.
- */
-
-void freeXImage(Image *image, XImageInfo *ximageinfo)
-{
- if (ximageinfo->index != NULL) /* if we allocated colors */
- {
- if (ximageinfo->no > 0 && !ximageinfo->rootimage) /* don't free root colors */
- XFreeColors(ximageinfo->disp, ximageinfo->cmap, ximageinfo->index, ximageinfo->no, 0);
- free(ximageinfo->index);
- }
- if (ximageinfo->gc)
- XFreeGC(ximageinfo->disp, ximageinfo->gc);
- free((byte *)ximageinfo->ximage->data);
- ximageinfo->ximage->data= NULL;
- XDestroyImage(ximageinfo->ximage);
- free((byte *)ximageinfo);
- /* should we free private color map to ??? */
-}
+++ /dev/null
-
-/* xli.h:
- *
- * jim frost 06.21.89
- *
- * Copyright 1989 Jim Frost. See included file "copyright.h" for complete
- * copyright information.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include <malloc.h>
-
-#include <X11/X.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#include <X11/cursorfont.h>
-
-typedef unsigned long Pixel; /* what X thinks a pixel is */
-typedef unsigned short Intensity; /* what X thinks an RGB intensity is */
-typedef unsigned char byte; /* unsigned byte type */
-
-#define FALSE 0
-#define TRUE (!FALSE)
-
-/* Display device dependent Information structure */
-typedef struct
-{
- int width; /* Display width and height */
- int height;
-
- Display *disp;
- int scrn;
- Colormap colormap;
-} DisplayInfo;
-
-/* This struct holds the X-client side bits for a rendered image. */
-typedef struct
-{
- Display *disp; /* destination display */
- int scrn; /* destination screen */
- int depth; /* depth of drawable we want/have */
- Drawable drawable; /* drawable to send image to */
- Pixel *index; /* array of pixel values allocated */
- int no; /* number of pixels in the array */
- int rootimage; /* True if is a root image - eg, retain colors */
- Pixel foreground; /* foreground and background pixels for mono images */
- Pixel background;
- Colormap cmap; /* colormap used for image */
- GC gc; /* cached gc for sending image */
- XImage *ximage; /* ximage structure */
-} XImageInfo;
-
-/* Function declarations */
-void sendXImage(); /* send.c */
-XImageInfo *imageToXImage();
-Pixmap ximageToPixmap();
-void freeXImage();
-
-
-typedef struct rgbmap {
- unsigned int size; /* size of RGB map */
- unsigned int used; /* number of colors used in RGB map */
- int compressed; /* image uses colormap fully */
- Intensity *red; /* color values in X style */
- Intensity *green;
- Intensity *blue;
-} RGBMap;
-
-/* image structure
- */
-
-typedef struct {
- char *title; /* name of image */
- unsigned int type; /* type of image */
- RGBMap rgb; /* RGB map of image if IRGB type */
- unsigned int width; /* width of image in pixels */
- unsigned int height; /* height of image in pixels */
- unsigned int depth; /* depth of image in bits if IRGB type */
- unsigned int pixlen; /* length of pixel if IRGB type */
- byte *data; /* data rounded to full byte for each row */
- float gamma; /* gamma of display the image is adjusted for */
-} Image;
-
-#define IBITMAP 0 /* image is a bitmap */
-#define IRGB 1 /* image is RGB */
-
-#define BITMAPP(IMAGE) ((IMAGE)->type == IBITMAP)
-#define RGBP(IMAGE) ((IMAGE)->type == IRGB)
-
-#define depthToColors(n) DepthToColorsTable[((n) < 24 ? (n) : 24)]
-
-/*
- * Architecture independent memory to value conversions.
- * Note the "Normal" internal format is big endian.
- */
-
-#define memToVal(PTR,LEN) ( \
-(LEN) == 1 ? (unsigned long)( *( (byte *)(PTR)) ) : \
-(LEN) == 2 ? (unsigned long)(((unsigned long)(*( (byte *)(PTR)) ))<< 8) \
- + ( *(((byte *)(PTR))+1) ) : \
-(LEN) == 3 ? (unsigned long)(((unsigned long)(*( (byte *)(PTR)) ))<<16) \
- + (((unsigned long)(*(((byte *)(PTR))+1)))<< 8) \
- + ( *(((byte *)(PTR))+2) ) : \
- (unsigned long)(((unsigned long)(*( (byte *)(PTR)) ))<<24) \
- + (((unsigned long)(*(((byte *)(PTR))+1)))<<16) \
- + (((unsigned long)(*(((byte *)(PTR))+2)))<< 8) \
- + ( *(((byte *)(PTR))+3) ) )
-
-#define valToMem(VAL,PTR,LEN) ( \
-(LEN) == 1 ? (*( (byte *)(PTR) ) = ( VAL ) ) : \
-(LEN) == 2 ? (*( (byte *)(PTR) ) = (((unsigned long)(VAL))>> 8), \
- *(((byte *)(PTR))+1) = ( VAL ) ) : \
-(LEN) == 3 ? (*( (byte *)(PTR) ) = (((unsigned long)(VAL))>>16), \
- *(((byte *)(PTR))+1) = (((unsigned long)(VAL))>> 8), \
- *(((byte *)(PTR))+2) = ( VAL ) ) : \
- (*( (byte *)(PTR) ) = (((unsigned long)(VAL))>>24), \
- *(((byte *)(PTR))+1) = (((unsigned long)(VAL))>>16), \
- *(((byte *)(PTR))+2) = (((unsigned long)(VAL))>> 8), \
- *(((byte *)(PTR))+3) = ( VAL ) ))
-
-
-/* functions */
-
-void cleanUpWindow(); /* window.c */
-char imageInWindow();
-
-int visualClassFromName();
-char *nameOfVisualClass();
-
-extern unsigned long DepthToColorsTable[]; /* new.c */
-char *dupString();
-Image *newBitImage();
-Image *newRGBImage();
-void freeImage();
-void freeImageData();
-void newRGBMapData();
-void freeRGBMapData();
-byte *lcalloc();
-byte *lmalloc();
-
-Image *gifLoad();
-Image *monochrome();
-Image *zoom();
-
-void compress(); /* compress.c */
-
-int xliOpenDisplay();
-void tellAboutDisplay(DisplayInfo *);
-void xliCloseDisplay(DisplayInfo *);