Added Enigma game

This commit is contained in:
pelya
2010-10-13 17:30:44 +03:00
parent 8bd2d39dfe
commit bf7d3f22c6
308 changed files with 92986 additions and 39 deletions

View File

@@ -89,7 +89,7 @@ if [ -n "$var" ] ; then
AppNeedsArrowKeys="$var"
fi
echo -n "\nApplication uses joystick (y) or (n), the accelerometer (2-axis) or orientation sensor (3-axis)\nwill be used as joystick 0 if not used as arrow keys ($AppUsesJoystick): "
echo -n "\nApplication uses joystick (y) or (n), the accelerometer (2-axis) or orientation sensor (3-axis)\nwill be used as joystick 0, also on-screen DPAD will be used as joystick ($AppUsesJoystick): "
read var
if [ -n "$var" ] ; then
AppUsesJoystick="$var"
@@ -147,15 +147,6 @@ if [ -n "$var" ] ; then
AppVersionName="$var"
fi
echo -n "\nOptional shared libraries to compile - removing some of them will save space\nMP3 support by libMAD is encumbered by patents and libMAD is GPL-ed\n"
grep 'Available libraries:' project/jni/Application.mk
grep 'depends on' project/jni/Application.mk
echo -n "Current: $CompiledLibraries\n\n: "
read var
if [ -n "$var" ] ; then
CompiledLibraries="$var"
fi
echo -n "\nApplication uses custom build script AndroidBuild.sh instead of Android.mk (y) or (n) ($CustomBuildScript): "
read var
if [ -n "$var" ] ; then
@@ -168,13 +159,22 @@ if [ -n "$var" ] ; then
AppCflags="$var"
fi
echo -n "\nOptional shared libraries to compile - removing some of them will save space\nMP3 support by libMAD is encumbered by patents and libMAD is GPL-ed\n"
grep 'Available' project/jni/Application.mk
grep 'depends on' project/jni/Application.mk
echo -n "Current: $CompiledLibraries\n\n: "
read var
if [ -n "$var" ] ; then
CompiledLibraries="$var"
fi
echo -n "\nAditional LDFLAGS for application ($AppLdflags): "
read var
if [ -n "$var" ] ; then
AppLdflags="$var"
fi
echo -n "\nBuild only following subdirs (empty will build all dirs) ($AppSubdirsBuild): "
echo -n "\nBuild only following subdirs (empty will build all dirs, ignored with custom script) ($AppSubdirsBuild): "
read var
if [ -n "$var" ] ; then
AppSubdirsBuild="$var"
@@ -369,7 +369,7 @@ fi
echo Patching project/jni/Application.mk
cat project/jni/Application.mk | \
sed "s/APP_MODULES := .*/APP_MODULES := application sdl-$LibSdlVersion sdl_main stlport tremor png jpeg freetype $CompiledLibraries/" | \
sed "s/APP_MODULES := .*/APP_MODULES := application sdl-$LibSdlVersion sdl_main stlport tremor png jpeg freetype xerces $CompiledLibraries/" | \
sed "s/APP_ABI := .*/APP_ABI := $MultiABI/" > \
project/jni/Application.mk.1
if [ -n "`diff -w project/jni/Application.mk.1 project/jni/Application.mk`" ] ; then
@@ -392,6 +392,14 @@ rm -rf project/$OUT/local/*/libsdl-*.so
rm -rf project/$OUT/local/*/objs/sdl-*/src/*/android
rm -rf project/$OUT/local/*/objs/sdl-*/src/video/SDL_video.o
rm -rf project/$OUT/local/*/objs/sdl-*/SDL_renderer_gles.o
# Do not rebuild several huge libraries that do not depend on SDL version
for LIB in freetype intl jpeg png lua mad stlport tremor xerces xml2; do
for ARCH in armeabi armeabi-v7a; do
if [ -e "project/$OUT/local/$ARCH/objs/$LIB" ] ; then
find project/$OUT/local/$ARCH/objs/$LIB -name "*.o" | xargs touch -c
fi
done
done
done
echo Done

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.schwardtnet.alienblaster"
android:versionCode="110011"
android:versionName="1.1.0.11 - fixed keys stuck sometimes for on-screen keyboard, fixed restoring app from background"
package="org.enigmagame.enigma"
android:versionCode="1"
android:versionName="0.1"
android:installLocation="preferExternal"
>
<application android:label="@string/app_name"

View File

@@ -1,6 +1,6 @@
# The namespace in Java file, with dots replaced with underscores
SDL_JAVA_PACKAGE_PATH := de_schwardtnet_alienblaster
SDL_JAVA_PACKAGE_PATH := org_enigmagame_enigma
# Path to shared libraries - Android 1.6 cannot load them properly, thus we have to specify absolute path here
# SDL_SHARED_LIBRARIES_PATH := /data/data/de.schwardtnet.alienblaster/lib
@@ -10,7 +10,7 @@ SDL_JAVA_PACKAGE_PATH := de_schwardtnet_alienblaster
# Typically /sdcard/alienblaster
# Or /data/data/de.schwardtnet.alienblaster/files if you're planning to unpack data in application private folder
# Your application will just set current directory there
SDL_CURDIR_PATH := de.schwardtnet.alienblaster
SDL_CURDIR_PATH := org.enigmagame.enigma
# Android Dev Phone G1 has trackball instead of cursor keys, and
# sends trackball movement events as rapid KeyDown/KeyUp events,
@@ -23,11 +23,11 @@ SDL_TRACKBALL_KEYUP_DELAY := 1
# resized in HW-accelerated way, however it eats a tiny bit of CPU
SDL_VIDEO_RENDER_RESIZE := 1
COMPILED_LIBRARIES := sdl_mixer sdl_image
COMPILED_LIBRARIES := sdl_mixer sdl_image sdl_ttf intl lua
APPLICATION_ADDITIONAL_CFLAGS := -finline-functions -O2
APPLICATION_ADDITIONAL_LDFLAGS :=
APPLICATION_ADDITIONAL_LDFLAGS := -lpng -lxerces
APPLICATION_SUBDIRS_BUILD :=
@@ -35,7 +35,7 @@ APPLICATION_CUSTOM_BUILD_SCRIPT :=
SDL_ADDITIONAL_CFLAGS := -DSDL_ANDROID_KEYCODE_MOUSE=UNKNOWN -DSDL_ANDROID_KEYCODE_0=RETURN -DSDL_ANDROID_KEYCODE_1=LCTRL -DSDL_ANDROID_KEYCODE_2=PAGEUP -DSDL_ANDROID_KEYCODE_3=PAGEDOWN -DSDL_ANDROID_KEYCODE_4=LCTRL
SDL_VERSION := 1.3
SDL_VERSION := 1.2
# If SDL_Mixer should link to libMAD
SDL_MIXER_USE_LIBMAD :=

View File

@@ -32,6 +32,8 @@ LOCAL_CFLAGS += \
-I$(LOCAL_PATH)/../intl \
-I$(LOCAL_PATH)/../freetype/include \
-I$(LOCAL_PATH)/../xml2/include \
-I$(LOCAL_PATH)/../xerces/src \
-I$(LOCAL_PATH)/../lua/src \
-I$(LOCAL_PATH)/..
LOCAL_CFLAGS += $(APPLICATION_ADDITIONAL_CFLAGS)

View File

@@ -0,0 +1,190 @@
----------------------------------------------------------------------
* Deja Vu fonts (dejavu.sourceforge.net)
Fonts are (c) Bitstream (see below). DejaVu changes are in public
domain. Glyphs imported from Arev fonts are (c) Tavmjung Bah (see
below)
Bitstream Vera Fonts Copyright
------------------------------
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
a trademark of Bitstream, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of the fonts accompanying this license ("Fonts") and associated
documentation files (the "Font Software"), to reproduce and distribute the
Font Software, including without limitation the rights to use, copy, merge,
publish, distribute, and/or sell copies of the Font Software, and to permit
persons to whom the Font Software is furnished to do so, subject to the
following conditions:
The above copyright and trademark notices and this permission notice shall
be included in all copies of one or more of the Font Software typefaces.
The Font Software may be modified, altered, or added to, and in particular
the designs of glyphs or characters in the Fonts may be modified and
additional glyphs or characters may be added to the Fonts, only if the fonts
are renamed to names not containing either the words "Bitstream" or the word
"Vera".
This License becomes null and void to the extent applicable to Fonts or Font
Software that has been modified and is distributed under the "Bitstream
Vera" names.
The Font Software may be sold as part of a larger software package but no
copy of one or more of the Font Software typefaces may be sold by itself.
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
FONT SOFTWARE.
Except as contained in this notice, the names of Gnome, the Gnome
Foundation, and Bitstream Inc., shall not be used in advertising or
otherwise to promote the sale, use or other dealings in this Font Software
without prior written authorization from the Gnome Foundation or Bitstream
Inc., respectively. For further information, contact: fonts at gnome dot
org.
Arev Fonts Copyright
------------------------------
Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of the fonts accompanying this license ("Fonts") and
associated documentation files (the "Font Software"), to reproduce
and distribute the modifications to the Bitstream Vera Font Software,
including without limitation the rights to use, copy, merge, publish,
distribute, and/or sell copies of the Font Software, and to permit
persons to whom the Font Software is furnished to do so, subject to
the following conditions:
The above copyright and trademark notices and this permission notice
shall be included in all copies of one or more of the Font Software
typefaces.
The Font Software may be modified, altered, or added to, and in
particular the designs of glyphs or characters in the Fonts may be
modified and additional glyphs or characters may be added to the
Fonts, only if the fonts are renamed to names not containing either
the words "Tavmjong Bah" or the word "Arev".
This License becomes null and void to the extent applicable to Fonts
or Font Software that has been modified and is distributed under the
"Tavmjong Bah Arev" names.
The Font Software may be sold as part of a larger software package but
no copy of one or more of the Font Software typefaces may be sold by
itself.
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
Except as contained in this notice, the name of Tavmjong Bah shall not
be used in advertising or otherwise to promote the sale, use or other
dealings in this Font Software without prior written authorization
from Tavmjong Bah. For further information, contact: tavmjong @ free
. fr
----------------------------------------------------------------------
* Zipios (http://zipios.sourceforge.net)
See doc/lpgl.txt
----------------------------------------------------------------------
* Oxydlib (http://www.sawicki.us/oxyd/)
See doc/gpl.txt
OxydLib is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
OxydLib is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OxydLib; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
----------------------------------------------------------------------
* Enet (http://enet.bespin.org)
Copyright (c) 2002 Lee Salzman
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------
* Lua (http://www.lua.org)
Copyright (c) 1994-2006 Lua.org, PUC-Rio.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------
* tolua (http://www.tecgraf.puc-rio.br/~celes/tolua/)
tolua is freely available; you can redistribute it and/or modify it.
The software provided hereunder is on an "as is" basis, and
the author has no obligation to provide maintenance, support,
updates, enhancements, or modifications.
----------------------------------------------------------------------

View File

@@ -0,0 +1 @@
Please refer to the documentation for a complete list of contributors.

View File

@@ -0,0 +1,27 @@
# The application settings for Android libSDL port
AppSettingVersion=10
LibSdlVersion=1.2
AppName="enigma"
AppFullName=org.enigmagame.enigma
ScreenOrientation=h
AppDataDownloadUrl="Enigma Game Data (16 MiB)|https://sites.google.com/site/xpelyax/Home/enigma-data.zip?attredirects=0&d=1"
SdlVideoResize=y
NeedDepthBuffer=n
AppUsesMouse=y
AppNeedsArrowKeys=n
AppUsesJoystick=y
AppUsesMultitouch=n
NonBlockingSwapBuffers=n
RedefinedKeys="RETURN LCTRL PAGEUP PAGEDOWN LCTRL"
AppTouchscreenKeyboardKeysAmount=0
AppTouchscreenKeyboardKeysAmountAutoFire=0
MultiABI=n
AppVersionCode=1
AppVersionName="0.1"
CompiledLibraries="sdl_mixer sdl_image sdl_ttf intl lua"
CustomBuildScript=n
AppCflags='-finline-functions -O2'
AppLdflags='-lpng -lxerces'
AppSubdirsBuild=''
AppUseCrystaXToolchain=y
ReadmeText='^You can press "Home" now - the data will be downloaded in background^Have fun playing enigma!^'

View File

@@ -0,0 +1,379 @@
Changes in Version 1.01
=======================
User-Visible changes
--------------------
- 60++ new level
- added easy mode to some existing levels
- fixes of all levels with known shortcuts
- Finnish translation
- French and Russian 1.0 manuals
- support of updatable cross internet level packs
- return to last played level via F6
- sound damping for noisy levels
- level developer inspector with developer attributes
- mouse wheel enabled for many buttons like user ratings, volume,...
- logo cleaned
- moved backup of score and state to backup subdirectory
- level menu string display optimization of level title, wr-holders,...
- visualize inherited user rating in level inspector
- vista compatible marble icon
- windows installer reengineering to modern NSI
Internal changes
----------------
- fix of various engine bugs that did not yet show up with bundled levels
- fixed properties of various glass stones
- sound handling reengineering
- support of user sound sets
- autorecovery from state / score mismatches
- re-Id of Windows users
Changes in Version 1.00
=======================
User-Visible changes
--------------------
- 200++ new levels, fixes to all broken levels
- new levelpack sorting
- grouping of levelpacks
- level inspector for viewing ratings and statistic information about levels
- screenshot viewer
- personal annotations and rating of levels
- score registration and download of world records and statistic information
- PAR and handicap as messures for a player
- drop & play of new levels and new levelpacks
- history and search of levels
- composer for own levelpacks and levelpack groups
- instant language change
- Translations of level titles and documents
- Swedish, Russian, Hungarian, Portuguese translation
- German and French manuals
- 100++ pages Reference manual
Internal changes
----------------
- XMLification of all data files
- reengineering of level and levelpack
- catch many errors intenally, display messages, continue or clean shutdown
- portability issues - Unix, Windows, MacOS as unified platform
- switch from Lua 4.* to Lua 5.1.1, from tolua to tolua++
- switch return value of messages from void/nil to Value
- added sender object as second argument to callback function
- common floor attributes (gradient, mouseforce, friction)
- border stones are swappable
- improved fire system: eternal, secure fire, heat transformation, ...
- new stones: st-chess, st-lightpassenger, st-polarswitch, st-redrock,
st-firebreak[_move], st-bigbluesand-<nesw>, st-camouflage
- new floors: fl-thief, fl-nomouse, fl-woven_orange
- new items: it-rubberband, it-booze-broken, it-death, it-drop
- removed: fl-ice_001
- it-pencil -> it-cross, it-crack
- it-brush -> it-cross, it-squashed
- st-scissor actions
- bigbricks unswappable and unpullable
- st-flash/actorimpulse*/spitter : distorted forces
- small whiteballs can jump
- new libraries: andreas_itemfreeze, andreas_ghosts, libpuzzle, libterrain
- icons polish
- sound additions, volume reduction on stone hit
for details on the subjects read the reference manual, for a complete list
of changes see svn commit messages at berlios.de:
http://svn.berlios.de/wsvn/enigma-game/tags/1.00/?op=log&rev=0&sc=0&isdir=1)
Changes in Version 0.92
=======================
Internal changes
----------------
- fl-ice_001 is back, but by all means, use fl-ice if you can
User-Visible changes
--------------------
- Ice is working again
- Cannonballs are working again
- Spanish translation (thanks to Samuel Elías Martínez <20>?lvarez)
- New application icon on Windows (thanks to Tobias Schmidbauer)
Changes in Version 0.91
=======================
Internal changes
----------------
- removed fl-ice_001
- new game variable enigma.IceFriction
Changes in Version 0.90
=======================
User-Visible Changes
--------------------
* Support for internationalized text
* Support for 800x600 and 1024x768 video modes
* Many new levels
* Tutorial levels for new players
* Much improved support for loading Oxyd levels
* New game mode: Time hunt
* Can reorder inventory with TAB key
* Support for gamma correction on some systems
* New command line options: --dumpinfo, --lang, --data
* Removed --8bpp command line option
* Removed support for 8bit graphics
Internal changes
----------------
* New item types
- it-bag
- it-banana
- it-blackbomb-burning
- it-booze
- it-changefloor
- it-drop (not 100% finished)
- it-easykeepstone
- it-easykillstone
- it-magnet-off
- it-magnet-on
- it-squashed
- it-surprise
* Other item changes
- Renamed it-soother to it-ring
* New stone types
- st-spitter
- st-flash
- st-surprise
- st-coffee
- st-blackballs
- st-whiteballs
- st-bug
- st-breaking
- st-fakeoxyda
- st-plain_cracked
- st-plain_hole
- st-plain_breaking
- st-plain_break
- st-plain_falling
- st-plain_move
- st-laserbreak
- st-break_gray
- st-yinyang3
* New floor types
fl-ice (fl-ice_001 still available)
* Other changes
- Two new scrolling modes: FOLLOW_SCREENSCROLLING (yes, ugly name,
sorry) and FOLLOW_SMOOTH.
- Elastic bands also have a minimum length, see daniel6.lua.
- An XML-based level format. Please refer to the reference manual
for details.
Changes in Version 0.81
=======================
User-Visible Changes
--------------------
* Fixed bug which caused all levels to be restarted when the
marble died.
Internal Changes
----------------
* Changed a few object names
it-seed_vulcano -> it-seed_volcano
st-vulcano -> st-volcano
st-vulcano-growing -> st-volcano-growing
Changes in Version 0.80
=======================
User-Visible Changes
--------------------
* Time game
* Easy / difficult game mode
* Sokoban mode
* Game manual
* More than 300 new levels (now more than 550 in total)
* (partially working) Oxyd level importer
* Better soft scrolling
* Countless new game elements: turnstiles, volcanos, warp tunnels,
land-mines, jump pads, rotors, ...
* Reduced memory footprint
Internal Changes
----------------
* New Lua Variables
enigma.AllowTogglePlayer = TRUE | FALSE
enigma.ShowMoves = TRUE | FALSE
enigma.Brittleness = 0 .. 1
enigma.SlopeForce
enigma.SlopeForce2
enigma.FrictionFactor
enigma.ElectricForce
enigma.BumperForce
* New Actor Types
ac-bug
ac-killerball
ac-rotator
ac-top
* New Stone Types
st-actorimpulse_invisible
st-beads
st-block
st-blocker
st-blue-sand
st-bolder-[nesw]
st-brake
st-break_bolder
st-break_invisible
st-chargeminus
st-chargeplus
st-chargezero
st-death_invisible
st-disco-dark
st-disco-light
st-disco-medium
st-door-h
st-door-h-open
st-door-v
st-door-v-open
st-easymode
st-fourswitch
st-glass_hole
st-glass_move
st-knight
st-laserswitch
st-likeoxyd[abcd]
st-mail
st-oneway-[nesw]
st-oneway_black-[nesw]
st-oneway_white-[nesw]
st-plain
st-pull
st-puzzle-[nesw]
st-puzzle-{ne, ns, nw, es, ew, sw}
st-puzzle-{nes, new, nsw, esw, nesw}
st-puzzle2-[nesw]
st-puzzle2-{ne, ns, nw, es, ew, sw}
st-puzzle2-{nes, new, nsw, esw, nesw}
st-rock3_movebreak
st-rotator-left
st-rotator-right
st-rotator_move-left
st-rotator_move-right
st-shogun-{s, m, l, sm, sl, ml, sml}
st-stoneimpulse_movable
st-switch_black
st-switch_white
st-timeswitch
st-turnstile
st-turnstile-[nesw]
st-turnstile-green
st-volcano
st-volcano_active
st-volcano_inactive
st-window
st-wood1
st-wood2
st-yellow
* New Item Types
it-abyss
it-blocker
it-brake
it-burnable
it-burnable-ash
it-burnable-fireproof
it-burnable-ignited
it-cherry
it-coffee
it-easymode
it-extinguisher
it-extinguisher-empty
it-extinguisher-full
it-flagblack
it-flagwhite
it-glasses
it-glasses-broken
it-hstrip
it-inversesensor
it-landmine
it-odometer
it-pin
it-puller-[nesw]
it-seed
it-seed_nowood
it-seed_volcano
it-seed_wood
it-sensor
it-soother
it-springboard
it-vortex-closed
it-vortex-open
it-vstrip
it-weight
it-whitebomb
it-wrench
* New Floor Types
fl-abyss_fake
fl-acwhite
fl-acblack
fl-black
fl-bumps
fl-concrete
fl-gravel
fl-light
fl-mortar
fl-red
fl-rock
fl-rough-blue
fl-rough-red
fl-rough_medium
fl-rough_slow
fl-springboard
fl-stwood
fl-stwood1
fl-stwood1
fl-stwood2
fl-stwood2
fl-white

View File

@@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@@ -0,0 +1,182 @@
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
The file `configure.in' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment. Using
a Bourne-compatible shell, you can do that on the command line like
this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
Or on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
==================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`configure' also accepts some other, not widely useful, options.

View File

@@ -0,0 +1,102 @@
About Enigma
============
Enigma is a unique puzzle game, with influences from almost every game
genre. Your objective is easily explained: you control a small black
marble with your mouse and have to find and uncover all pairs of
identical Oxyd stones in each landscape. Simple? Yes. Easy? It would
be, if it weren't for hidden traps, vast mazes, insurmountable
obstacles and innumerable puzzles blocking your direct way to the Oxyd
stones... If you like puzzle games and have a steady hand, Enigma's
more than 500 levels will probably keep you busy for hours on end.
Enigma is developed by a small group of volunteers, and help is always
appreciated. If you like Enigma and want to contribute to its future,
you are welcome to join us on our development mailing list at
http://mail.nongnu.org/mailman/listinfo/enigma-devel
or simply send email to
enigma-devel@nongnu.org
Every kind of contribution is welcome, whether it is programming,
documentation, graphics, sound effects, or simply good advice.
The official Enigma homepage can be found at
http://www.nongnu.org/enigma/
If you have any questions, suggestions, or contributions, feel free to
send email to the mailing list. Have fun!
The Enigma Team
Playing Enigma
==============
Please refer to the user manual for instructions on how to play Enigma,
or simply start with the tutorial levels included with the game.
Installation
============
Installation on Windows and Mac OS X is straightforward: Simply download
the appropriate .exe or .dmg file and start it with a double click.
Things get a little more complicated for other operating systems,
please refer to Enigma's download page
http://www.nongnu.org/enigma/download.html
for up-to-date information. If you are running some kind of Unix system,
you have always the option of compiling Enigma yourself; this is
explained in the next section.
There may or may not be binaries for the Linux distribution of your choice,
and they may or may not work on your computer. This is not our fault:
packaging a Linux version that works everywhere is almost impossible,
thanks to countless subtle and not-so-subtle differences between each
and every Linux distribution. Please complain to your vendor if this
bugs you.
Compiling Enigma
================
This section briefly describes how to compile Enigma on a Unix
machine. If you want to build Enigma on Windows or Mac OS X, please
see the documentation in `doc/README.mingw32' and `doc/README.macosx',
respectively.
For a list of libraries and programs that must be installed to compile
Enigma, please refer to `doc/REQUIREMENTS' for a complete list.
Once you have everything installed, building Enigma is as easy as typing
./configure && make && make install
in the enigma directory.
Copying
=======
Enigma is free software. You may copy and modify it under the terms
of the GNU General Public License, Version 2 or, at your option, any
later version. For details, please refer to the accompanying
COPYING file.
Please refer to the ACKNOWLEDGEMENTS file that comes with Enigma for
copyright information and licensing terms of external dependencies and
contributions to this project.
To my best of our knowledge the included sound effects are either in the
public domain or freely distributable. We weren't able to pin down the
exact origin of each sound file -- the copyrights of which we are aware
are collected in soundsets/enigma/README. Please refer to this list
before using the samples in your productions.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -0,0 +1,14 @@
Please visit the ENet homepage at http://enet.bespin.org for installation
and usage instructions.
If you obtained this package from CVS, the quick description on how to build
is:
# Generate the build system.
aclocal && automake -a -c --foreign && autoconf
# Compile and install the library.
./configure && make && make install

View File

@@ -0,0 +1,53 @@
/**
@file callbacks.c
@brief ENet callback functions
*/
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
static ENetCallbacks callbacks = { malloc, free, rand };
int
enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits)
{
if (version != ENET_VERSION)
return -1;
if (inits -> malloc != NULL || inits -> free != NULL)
{
if (inits -> malloc == NULL || inits -> free == NULL)
return -1;
callbacks.malloc = inits -> malloc;
callbacks.free = inits -> free;
}
if (inits -> rand != NULL)
callbacks.rand = inits -> rand;
return enet_initialize ();
}
void *
enet_malloc (size_t size)
{
void * memory = callbacks.malloc (size);
if (memory == NULL)
abort ();
return memory;
}
void
enet_free (void * memory)
{
callbacks.free (memory);
}
int
enet_rand (void)
{
return callbacks.rand ();
}

View File

@@ -0,0 +1,391 @@
/**
@file host.c
@brief ENet host management functions
*/
#define ENET_BUILDING_LIB 1
#include <string.h>
#include "enet/enet.h"
/** @defgroup host ENet host functions
@{
*/
/** Creates a host for communicating to peers.
@param address the address at which other peers may connect to this host. If NULL, then no peers may connect to the host.
@param peerCount the maximum number of peers that should be allocated for the host.
@param incomingBandwidth downstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
@param outgoingBandwidth upstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
@returns the host on success and NULL on failure
@remarks ENet will strategically drop packets on specific sides of a connection between hosts
to ensure the host's bandwidth is not overwhelmed. The bandwidth parameters also determine
the window size of a connection which limits the amount of reliable packets that may be in transit
at any given time.
*/
ENetHost *
enet_host_create (const ENetAddress * address, size_t peerCount, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
{
ENetHost * host = (ENetHost *) enet_malloc (sizeof (ENetHost));
ENetPeer * currentPeer;
host -> peers = (ENetPeer *) enet_malloc (peerCount * sizeof (ENetPeer));
memset (host -> peers, 0, peerCount * sizeof (ENetPeer));
host -> socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM, address);
if (host -> socket == ENET_SOCKET_NULL)
{
enet_free (host -> peers);
enet_free (host);
return NULL;
}
if (address != NULL)
host -> address = * address;
host -> incomingBandwidth = incomingBandwidth;
host -> outgoingBandwidth = outgoingBandwidth;
host -> bandwidthThrottleEpoch = 0;
host -> recalculateBandwidthLimits = 0;
host -> mtu = ENET_HOST_DEFAULT_MTU;
host -> peerCount = peerCount;
host -> lastServicedPeer = host -> peers;
host -> commandCount = 0;
host -> bufferCount = 0;
host -> receivedAddress.host = ENET_HOST_ANY;
host -> receivedAddress.port = 0;
host -> receivedDataLength = 0;
for (currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
currentPeer -> host = host;
currentPeer -> incomingPeerID = currentPeer - host -> peers;
currentPeer -> data = NULL;
enet_list_clear (& currentPeer -> acknowledgements);
enet_list_clear (& currentPeer -> sentReliableCommands);
enet_list_clear (& currentPeer -> sentUnreliableCommands);
enet_list_clear (& currentPeer -> outgoingReliableCommands);
enet_list_clear (& currentPeer -> outgoingUnreliableCommands);
enet_peer_reset (currentPeer);
}
return host;
}
/** Destroys the host and all resources associated with it.
@param host pointer to the host to destroy
*/
void
enet_host_destroy (ENetHost * host)
{
ENetPeer * currentPeer;
enet_socket_destroy (host -> socket);
for (currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
enet_peer_reset (currentPeer);
}
enet_free (host -> peers);
enet_free (host);
}
/** Initiates a connection to a foreign host.
@param host host seeking the connection
@param address destination for the connection
@param channelCount number of channels to allocate
@returns a peer representing the foreign host on success, NULL on failure
@remarks The peer returned will have not completed the connection until enet_host_service()
notifies of an ENET_EVENT_TYPE_CONNECT event for the peer.
*/
ENetPeer *
enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelCount)
{
ENetPeer * currentPeer;
ENetChannel * channel;
ENetProtocol command;
if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
channelCount = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
else
if (channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
channelCount = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
for (currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED)
break;
}
if (currentPeer >= & host -> peers [host -> peerCount])
return NULL;
currentPeer -> state = ENET_PEER_STATE_CONNECTING;
currentPeer -> address = * address;
currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel));
currentPeer -> channelCount = channelCount;
currentPeer -> challenge = (enet_uint32) enet_rand ();
if (host -> outgoingBandwidth == 0)
currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
else
currentPeer -> windowSize = (host -> outgoingBandwidth /
ENET_PEER_WINDOW_SIZE_SCALE) *
ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
else
if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
for (channel = currentPeer -> channels;
channel < & currentPeer -> channels [channelCount];
++ channel)
{
channel -> outgoingReliableSequenceNumber = 0;
channel -> outgoingUnreliableSequenceNumber = 0;
channel -> incomingReliableSequenceNumber = 0;
channel -> incomingUnreliableSequenceNumber = 0;
enet_list_clear (& channel -> incomingReliableCommands);
enet_list_clear (& channel -> incomingUnreliableCommands);
}
command.header.command = ENET_PROTOCOL_COMMAND_CONNECT;
command.header.channelID = 0xFF;
command.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE;
command.header.commandLength = sizeof (ENetProtocolConnect);
command.connect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID);
command.connect.mtu = ENET_HOST_TO_NET_16 (currentPeer -> mtu);
command.connect.windowSize = ENET_HOST_TO_NET_32 (currentPeer -> windowSize);
command.connect.channelCount = ENET_HOST_TO_NET_32 (channelCount);
command.connect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth);
command.connect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
command.connect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval);
command.connect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration);
command.connect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration);
enet_peer_queue_outgoing_command (currentPeer, & command, NULL, 0, 0);
return currentPeer;
}
/** Queues a packet to be sent to all peers associated with the host.
@param host host on which to broadcast the packet
@param channelID channel on which to broadcast
@param packet packet to broadcast
*/
void
enet_host_broadcast (ENetHost * host, enet_uint8 channelID, ENetPacket * packet)
{
ENetPeer * currentPeer;
for (currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
if (currentPeer -> state != ENET_PEER_STATE_CONNECTED)
continue;
enet_peer_send (currentPeer, channelID, packet);
}
if (packet -> referenceCount == 0)
enet_packet_destroy (packet);
}
/** Adjusts the bandwidth limits of a host.
@param host host to adjust
@param incomingBandwidth new incoming bandwidth
@param outgoingBandwidth new outgoing bandwidth
@remarks the incoming and outgoing bandwidth parameters are identical in function to those
specified in enet_host_create().
*/
void
enet_host_bandwidth_limit (ENetHost * host, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
{
host -> incomingBandwidth = incomingBandwidth;
host -> outgoingBandwidth = outgoingBandwidth;
host -> recalculateBandwidthLimits = 1;
}
void
enet_host_bandwidth_throttle (ENetHost * host)
{
enet_uint32 timeCurrent = enet_time_get (),
elapsedTime = timeCurrent - host -> bandwidthThrottleEpoch,
peersTotal = 0,
dataTotal = 0,
peersRemaining,
bandwidth,
throttle = 0,
bandwidthLimit = 0;
int needsAdjustment;
ENetPeer * peer;
ENetProtocol command;
if (elapsedTime < ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
return;
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
if (peer -> state != ENET_PEER_STATE_CONNECTED)
continue;
++ peersTotal;
dataTotal += peer -> outgoingDataTotal;
}
if (peersTotal == 0)
return;
peersRemaining = peersTotal;
needsAdjustment = 1;
if (host -> outgoingBandwidth == 0)
bandwidth = ~0;
else
bandwidth = (host -> outgoingBandwidth * elapsedTime) / 1000;
while (peersRemaining > 0 && needsAdjustment != 0)
{
needsAdjustment = 0;
if (dataTotal < bandwidth)
throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
else
throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
enet_uint32 peerBandwidth;
if (peer -> state != ENET_PEER_STATE_CONNECTED ||
peer -> incomingBandwidth == 0 ||
peer -> outgoingBandwidthThrottleEpoch == timeCurrent)
continue;
peerBandwidth = (peer -> incomingBandwidth * elapsedTime) / 1000;
if ((throttle * peer -> outgoingDataTotal) / ENET_PEER_PACKET_THROTTLE_SCALE <= peerBandwidth)
continue;
peer -> packetThrottleLimit = (peerBandwidth *
ENET_PEER_PACKET_THROTTLE_SCALE) / peer -> outgoingDataTotal;
if (peer -> packetThrottleLimit == 0)
peer -> packetThrottleLimit = 1;
if (peer -> packetThrottle > peer -> packetThrottleLimit)
peer -> packetThrottle = peer -> packetThrottleLimit;
peer -> outgoingBandwidthThrottleEpoch = timeCurrent;
needsAdjustment = 1;
-- peersRemaining;
bandwidth -= peerBandwidth;
dataTotal -= peerBandwidth;
}
}
if (peersRemaining > 0)
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
if (peer -> state != ENET_PEER_STATE_CONNECTED ||
peer -> outgoingBandwidthThrottleEpoch == timeCurrent)
continue;
peer -> packetThrottleLimit = throttle;
if (peer -> packetThrottle > peer -> packetThrottleLimit)
peer -> packetThrottle = peer -> packetThrottleLimit;
}
if (host -> recalculateBandwidthLimits)
{
host -> recalculateBandwidthLimits = 0;
peersRemaining = peersTotal;
bandwidth = host -> incomingBandwidth;
needsAdjustment = 1;
if (bandwidth == 0)
bandwidthLimit = 0;
else
while (peersRemaining > 0 && needsAdjustment != 0)
{
needsAdjustment = 0;
bandwidthLimit = bandwidth / peersRemaining;
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
if (peer -> state != ENET_PEER_STATE_CONNECTED ||
peer -> incomingBandwidthThrottleEpoch == timeCurrent)
continue;
if (peer -> outgoingBandwidth > 0 &&
bandwidthLimit > peer -> outgoingBandwidth)
continue;
peer -> incomingBandwidthThrottleEpoch = timeCurrent;
needsAdjustment = 1;
-- peersRemaining;
bandwidth -= peer -> outgoingBandwidth;
}
}
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
if (peer -> state != ENET_PEER_STATE_CONNECTED)
continue;
command.header.command = ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT;
command.header.channelID = 0xFF;
command.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE;
command.header.commandLength = sizeof (ENetProtocolBandwidthLimit);
command.bandwidthLimit.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
if (peer -> incomingBandwidthThrottleEpoch == timeCurrent)
command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32 (peer -> outgoingBandwidth);
else
command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32 (bandwidthLimit);
enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
}
}
host -> bandwidthThrottleEpoch = timeCurrent;
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
peer -> incomingDataTotal = 0;
peer -> outgoingDataTotal = 0;
}
}
/** @} */

View File

@@ -0,0 +1,28 @@
/**
@file callbacks.h
@brief ENet callbacks
*/
#ifndef __ENET_CALLBACKS_H__
#define __ENET_CALLBACKS_H__
#include <stdlib.h>
typedef struct
{
void * (ENET_CALLBACK * malloc) (size_t size);
void (ENET_CALLBACK * free) (void * memory);
int (ENET_CALLBACK * rand) (void);
} ENetCallbacks;
/** @defgroup callbacks ENet internal callbacks
@{
@ingroup private
*/
extern void * enet_malloc (size_t);
extern void enet_free (void *);
extern int enet_rand (void);
/** @} */
#endif /* __ENET_CALLBACKS_H__ */

View File

@@ -0,0 +1,432 @@
/**
@file enet.h
@brief ENet public header file
*/
#ifndef __ENET_ENET_H__
#define __ENET_ENET_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdlib.h>
#ifdef WIN32
#include "enet/win32.h"
#else
#include "enet/unix.h"
#endif
#include "enet/types.h"
#include "enet/protocol.h"
#include "enet/list.h"
#include "enet/callbacks.h"
typedef enum
{
ENET_VERSION = 1
} ENetVersion;
typedef enum
{
ENET_SOCKET_TYPE_STREAM = 1,
ENET_SOCKET_TYPE_DATAGRAM = 2
} ENetSocketType;
typedef enum
{
ENET_SOCKET_WAIT_NONE = 0,
ENET_SOCKET_WAIT_SEND = (1 << 0),
ENET_SOCKET_WAIT_RECEIVE = (1 << 1)
} ENetSocketWait;
enum
{
ENET_HOST_ANY = 0, /**< specifies the default server host */
ENET_HOST_BROADCAST = 0xFFFFFFFF /**< specifies a subnet-wide broadcast */
};
/**
* Portable internet address structure.
*
* The host must be specified in network byte-order, and the port must be in host
* byte-order. The constant ENET_HOST_ANY may be used to specify the default
* server host. The constant ENET_HOST_BROADCAST may be used to specify the
* broadcast address (255.255.255.255). This makes sense for enet_host_connect,
* but not for enet_host_create. Once a server responds to a broadcast, the
* address is updated from ENET_HOST_BROADCAST to the server's actual IP address.
*/
typedef struct _ENetAddress
{
enet_uint32 host;
enet_uint16 port;
} ENetAddress;
/**
* Packet flag bit constants.
*
* The host must be specified in network byte-order, and the port must be in
* host byte-order. The constant ENET_HOST_ANY may be used to specify the
* default server host.
@sa ENetPacket
*/
typedef enum
{
/** packet must be received by the target peer and resend attempts should be
* made until the packet is delivered */
ENET_PACKET_FLAG_RELIABLE = (1 << 0),
/** packet will not be sequenced with other packets
* not supported for reliable packets
*/
ENET_PACKET_FLAG_UNSEQUENCED = (1 << 1)
} ENetPacketFlag;
/**
* ENet packet structure.
*
* An ENet data packet that may be sent to or received from a peer. The shown
* fields should only be read and never modified. The data field contains the
* allocated data for the packet. The dataLength fields specifies the length
* of the allocated data. The flags field is either 0 (specifying no flags),
* or a bitwise-or of any combination of the following flags:
*
* ENET_PACKET_FLAG_RELIABLE - packet must be received by the target peer
* and resend attempts should be made until the packet is delivered
@sa ENetPacketFlag
*/
typedef struct _ENetPacket
{
size_t referenceCount; /**< internal use only */
enet_uint32 flags; /**< bitwise or of ENetPacketFlag constants */
enet_uint8 * data; /**< allocated data for packet */
size_t dataLength; /**< length of data */
} ENetPacket;
typedef struct _ENetAcknowledgement
{
ENetListNode acknowledgementList;
enet_uint32 sentTime;
ENetProtocol command;
} ENetAcknowledgement;
typedef struct _ENetOutgoingCommand
{
ENetListNode outgoingCommandList;
enet_uint32 reliableSequenceNumber;
enet_uint32 unreliableSequenceNumber;
enet_uint32 sentTime;
enet_uint32 roundTripTimeout;
enet_uint32 roundTripTimeoutLimit;
enet_uint32 fragmentOffset;
enet_uint16 fragmentLength;
ENetProtocol command;
ENetPacket * packet;
} ENetOutgoingCommand;
typedef struct _ENetIncomingCommand
{
ENetListNode incomingCommandList;
enet_uint32 reliableSequenceNumber;
enet_uint32 unreliableSequenceNumber;
ENetProtocol command;
enet_uint32 fragmentCount;
enet_uint32 fragmentsRemaining;
enet_uint32 * fragments;
ENetPacket * packet;
} ENetIncomingCommand;
typedef enum
{
ENET_PEER_STATE_DISCONNECTED = 0,
ENET_PEER_STATE_CONNECTING = 1,
ENET_PEER_STATE_ACKNOWLEDGING_CONNECT = 2,
ENET_PEER_STATE_CONNECTION_PENDING = 3,
ENET_PEER_STATE_CONNECTED = 4,
ENET_PEER_STATE_DISCONNECTING = 5,
ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT = 6,
ENET_PEER_STATE_ZOMBIE = 7
} ENetPeerState;
#ifndef ENET_BUFFER_MAXIMUM
#define ENET_BUFFER_MAXIMUM (1 + 2 * ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS)
#endif
enum
{
ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024,
ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000,
ENET_HOST_DEFAULT_MTU = 1400,
ENET_PEER_DEFAULT_ROUND_TRIP_TIME = 500,
ENET_PEER_DEFAULT_PACKET_THROTTLE = 32,
ENET_PEER_PACKET_THROTTLE_SCALE = 32,
ENET_PEER_PACKET_THROTTLE_COUNTER = 7,
ENET_PEER_PACKET_THROTTLE_ACCELERATION = 2,
ENET_PEER_PACKET_THROTTLE_DECELERATION = 2,
ENET_PEER_PACKET_THROTTLE_INTERVAL = 5000,
ENET_PEER_PACKET_LOSS_SCALE = (1 << 16),
ENET_PEER_PACKET_LOSS_INTERVAL = 10000,
ENET_PEER_WINDOW_SIZE_SCALE = 64 * 1024,
ENET_PEER_TIMEOUT_LIMIT = 32,
ENET_PEER_TIMEOUT_MINIMUM = 5000,
ENET_PEER_TIMEOUT_MAXIMUM = 30000,
ENET_PEER_PING_INTERVAL = 500,
ENET_PEER_UNSEQUENCED_WINDOW_SIZE = 4 * 32,
};
typedef struct _ENetChannel
{
enet_uint32 outgoingReliableSequenceNumber;
enet_uint32 outgoingUnreliableSequenceNumber;
enet_uint32 incomingReliableSequenceNumber;
enet_uint32 incomingUnreliableSequenceNumber;
ENetList incomingReliableCommands;
ENetList incomingUnreliableCommands;
} ENetChannel;
/**
* An ENet peer which data packets may be sent or received from.
*
* No fields should be modified unless otherwise specified.
*/
typedef struct _ENetPeer
{
struct _ENetHost * host;
enet_uint16 outgoingPeerID;
enet_uint16 incomingPeerID;
enet_uint32 challenge;
ENetAddress address; /**< Internet address of the peer */
void * data; /**< Application private data, may be freely modified */
ENetPeerState state;
ENetChannel * channels;
size_t channelCount; /**< Number of channels allocated for communication with peer */
enet_uint32 incomingBandwidth; /**< Downstream bandwidth of the client in bytes/second */
enet_uint32 outgoingBandwidth; /**< Upstream bandwidth of the client in bytes/second */
enet_uint32 incomingBandwidthThrottleEpoch;
enet_uint32 outgoingBandwidthThrottleEpoch;
enet_uint32 incomingDataTotal;
enet_uint32 outgoingDataTotal;
enet_uint32 lastSendTime;
enet_uint32 lastReceiveTime;
enet_uint32 nextTimeout;
enet_uint32 earliestTimeout;
enet_uint32 packetLossEpoch;
enet_uint32 packetsSent;
enet_uint32 packetsLost;
enet_uint32 packetLoss; /**< mean packet loss of reliable packets as a ratio with respect to the constant ENET_PEER_PACKET_LOSS_SCALE */
enet_uint32 packetLossVariance;
enet_uint32 packetThrottle;
enet_uint32 packetThrottleLimit;
enet_uint32 packetThrottleCounter;
enet_uint32 packetThrottleEpoch;
enet_uint32 packetThrottleAcceleration;
enet_uint32 packetThrottleDeceleration;
enet_uint32 packetThrottleInterval;
enet_uint32 lastRoundTripTime;
enet_uint32 lowestRoundTripTime;
enet_uint32 lastRoundTripTimeVariance;
enet_uint32 highestRoundTripTimeVariance;
enet_uint32 roundTripTime; /**< mean round trip time (RTT), in milliseconds, between sending a reliable packet and receiving its acknowledgement */
enet_uint32 roundTripTimeVariance;
enet_uint16 mtu;
enet_uint32 windowSize;
enet_uint32 reliableDataInTransit;
enet_uint32 outgoingReliableSequenceNumber;
ENetList acknowledgements;
ENetList sentReliableCommands;
ENetList sentUnreliableCommands;
ENetList outgoingReliableCommands;
ENetList outgoingUnreliableCommands;
enet_uint32 incomingUnsequencedGroup;
enet_uint32 outgoingUnsequencedGroup;
enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32];
enet_uint32 disconnectData;
} ENetPeer;
/** An ENet host for communicating with peers.
*
* No fields should be modified.
@sa enet_host_create()
@sa enet_host_destroy()
@sa enet_host_connect()
@sa enet_host_service()
@sa enet_host_flush()
@sa enet_host_broadcast()
@sa enet_host_bandwidth_limit()
@sa enet_host_bandwidth_throttle()
*/
typedef struct _ENetHost
{
ENetSocket socket;
ENetAddress address; /**< Internet address of the host */
enet_uint32 incomingBandwidth; /**< downstream bandwidth of the host */
enet_uint32 outgoingBandwidth; /**< upstream bandwidth of the host */
enet_uint32 bandwidthThrottleEpoch;
enet_uint32 mtu;
int recalculateBandwidthLimits;
ENetPeer * peers; /**< array of peers allocated for this host */
size_t peerCount; /**< number of peers allocated for this host */
ENetPeer * lastServicedPeer;
size_t packetSize;
ENetProtocol commands [ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS];
size_t commandCount;
ENetBuffer buffers [ENET_BUFFER_MAXIMUM];
size_t bufferCount;
ENetAddress receivedAddress;
enet_uint8 receivedData [ENET_PROTOCOL_MAXIMUM_MTU];
size_t receivedDataLength;
} ENetHost;
/**
* An ENet event type, as specified in @ref ENetEvent.
*/
typedef enum
{
/** no event occurred within the specified time limit */
ENET_EVENT_TYPE_NONE = 0,
/** a connection request initiated by enet_host_connect has completed.
* The peer field contains the peer which successfully connected.
*/
ENET_EVENT_TYPE_CONNECT = 1,
/** a peer has disconnected. This event is generated on a successful
* completion of a disconnect initiated by enet_pper_disconnect, if
* a peer has timed out, or if a connection request intialized by
* enet_host_connect has timed out. The peer field contains the peer
* which disconnected. The data field contains user supplied data
* describing the disconnection, or 0, if none is available.
*/
ENET_EVENT_TYPE_DISCONNECT = 2,
/** a packet has been received from a peer. The peer field specifies the
* peer which sent the packet. The channelID field specifies the channel
* number upon which the packet was received. The packet field contains
* the packet that was received; this packet must be destroyed with
* enet_packet_destroy after use.
*/
ENET_EVENT_TYPE_RECEIVE = 3
} ENetEventType;
/**
* An ENet event as returned by enet_host_service().
@sa enet_host_service
*/
typedef struct _ENetEvent
{
ENetEventType type; /**< type of the event */
ENetPeer * peer; /**< peer that generated a connect, disconnect or receive event */
enet_uint8 channelID; /**< channel on the peer that generated the event, if appropriate */
enet_uint32 data; /**< data associated with the event, if appropriate */
ENetPacket * packet; /**< packet associated with the event, if appropriate */
} ENetEvent;
/** @defgroup global ENet global functions
@{
*/
/**
Initializes ENet globally. Must be called prior to using any functions in
ENet.
@returns 0 on success, < 0 on failure
*/
ENET_API int enet_initialize (void);
ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits);
/**
Shuts down ENet globally. Should be called when a program that has
initialized ENet exits.
*/
ENET_API void enet_deinitialize (void);
/** @} */
/** @defgroup private ENet private implementation functions */
/**
Returns the wall-time in milliseconds. Its initial value is unspecified
unless otherwise set.
*/
ENET_API enet_uint32 enet_time_get (void);
/**
Sets the current wall-time in milliseconds.
*/
ENET_API void enet_time_set (enet_uint32);
/** @defgroup socket ENet socket functions
@{
@ingroup private
*/
extern ENetSocket enet_socket_create (ENetSocketType, const ENetAddress *);
extern ENetSocket enet_socket_accept (ENetSocket, ENetAddress *);
extern int enet_socket_connect (ENetSocket, const ENetAddress *);
extern int enet_socket_send (ENetSocket, const ENetAddress *, const ENetBuffer *, size_t);
extern int enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t);
extern int enet_socket_wait (ENetSocket, enet_uint32 *, enet_uint32);
extern void enet_socket_destroy (ENetSocket);
/** @} */
/** @defgroup Address ENet address functions
@{
*/
/** Attempts to resolve the host named by the parameter hostName and sets
the host field in the address parameter if successful.
@param address destination to store resolved address
@param hostName host name to lookup
@retval 0 on success
@retval < 0 on failure
@returns the address of the given hostName in address on success
*/
ENET_API int enet_address_set_host (ENetAddress *address, const char *hostName );
/** Attempts to do a reserve lookup of the host field in the address parameter.
@param address address used for reverse lookup
@param hostName destination for name, must not be NULL
@param nameLength maximum length of hostName.
@returns the null-terminated name of the host in hostName on success
@retval 0 on success
@retval < 0 on failure
*/
ENET_API int enet_address_get_host (const ENetAddress *address, char *hostName, size_t nameLength );
/** @} */
ENET_API ENetPacket * enet_packet_create (const void *dataContents, size_t dataLength, enet_uint32 flags);
ENET_API void enet_packet_destroy (ENetPacket *packet );
ENET_API int enet_packet_resize (ENetPacket *packet, size_t dataLength );
ENET_API ENetHost * enet_host_create (const ENetAddress *address, size_t peerCount, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth );
ENET_API void enet_host_destroy (ENetHost *host );
ENET_API ENetPeer * enet_host_connect (ENetHost *host, const ENetAddress *address, size_t channelCount );
ENET_API int enet_host_service (ENetHost *, ENetEvent *, enet_uint32);
ENET_API void enet_host_flush (ENetHost *);
ENET_API void enet_host_broadcast (ENetHost *, enet_uint8, ENetPacket *);
ENET_API void enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uint32);
extern void enet_host_bandwidth_throttle (ENetHost *);
ENET_API int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *);
ENET_API ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8);
ENET_API void enet_peer_ping (ENetPeer *);
ENET_API void enet_peer_reset (ENetPeer *);
ENET_API void enet_peer_disconnect (ENetPeer *, enet_uint32);
ENET_API void enet_peer_disconnect_now (ENetPeer *, enet_uint32);
ENET_API void enet_peer_throttle_configure (ENetPeer *, enet_uint32, enet_uint32, enet_uint32);
extern int enet_peer_throttle (ENetPeer *, enet_uint32);
extern void enet_peer_reset_queues (ENetPeer *);
extern ENetOutgoingCommand * enet_peer_queue_outgoing_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16);
extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32);
extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint32);
#ifdef __cplusplus
}
#endif
#endif /* __ENET_ENET_H__ */

View File

@@ -0,0 +1,42 @@
/**
@file list.h
@brief ENet list management
*/
#ifndef __ENET_LIST_H__
#define __ENET_LIST_H__
#include <stdlib.h>
typedef struct _ENetListNode
{
struct _ENetListNode * next;
struct _ENetListNode * previous;
} ENetListNode;
typedef ENetListNode * ENetListIterator;
typedef struct _ENetList
{
ENetListNode sentinel;
} ENetList;
extern void enet_list_clear (ENetList *);
extern ENetListIterator enet_list_insert (ENetListIterator, void *);
extern void * enet_list_remove (ENetListIterator);
extern size_t enet_list_size (ENetList *);
#define enet_list_begin(list) ((list) -> sentinel.next)
#define enet_list_end(list) (& (list) -> sentinel)
#define enet_list_empty(list) (enet_list_begin (list) == enet_list_end (list))
#define enet_list_next(iterator) ((iterator) -> next)
#define enet_list_previous(iterator) ((iterator) -> previous)
#define enet_list_front(list) ((void *) (list) -> sentinel.next)
#define enet_list_back(list) ((void *) (list) -> sentinel.previous)
#endif /* __ENET_LIST_H__ */

View File

@@ -0,0 +1,167 @@
/**
@file protocol.h
@brief ENet protocol
*/
#ifndef __ENET_PROTOCOL_H__
#define __ENET_PROTOCOL_H__
#include "enet/types.h"
enum
{
ENET_PROTOCOL_MINIMUM_MTU = 576,
ENET_PROTOCOL_MAXIMUM_MTU = 4096,
ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS = 32,
ENET_PROTOCOL_MINIMUM_WINDOW_SIZE = 4096,
ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 32768,
ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1,
ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255
};
typedef enum
{
ENET_PROTOCOL_COMMAND_NONE = 0,
ENET_PROTOCOL_COMMAND_ACKNOWLEDGE = 1,
ENET_PROTOCOL_COMMAND_CONNECT = 2,
ENET_PROTOCOL_COMMAND_VERIFY_CONNECT = 3,
ENET_PROTOCOL_COMMAND_DISCONNECT = 4,
ENET_PROTOCOL_COMMAND_PING = 5,
ENET_PROTOCOL_COMMAND_SEND_RELIABLE = 6,
ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE = 7,
ENET_PROTOCOL_COMMAND_SEND_FRAGMENT = 8,
ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT = 9,
ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE = 10,
ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED = 11
} ENetProtocolCommand;
typedef enum
{
ENET_PROTOCOL_FLAG_ACKNOWLEDGE = (1 << 0),
ENET_PROTOCOL_FLAG_UNSEQUENCED = (1 << 1)
} ENetProtocolFlag;
typedef struct
{
enet_uint16 peerID;
enet_uint8 flags;
enet_uint8 commandCount;
enet_uint32 sentTime;
enet_uint32 challenge;
} ENetProtocolHeader;
typedef struct
{
enet_uint8 command;
enet_uint8 channelID;
enet_uint8 flags;
enet_uint8 reserved;
enet_uint32 commandLength;
enet_uint32 reliableSequenceNumber;
} ENetProtocolCommandHeader;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint32 receivedReliableSequenceNumber;
enet_uint32 receivedSentTime;
} ENetProtocolAcknowledge;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint16 outgoingPeerID;
enet_uint16 mtu;
enet_uint32 windowSize;
enet_uint32 channelCount;
enet_uint32 incomingBandwidth;
enet_uint32 outgoingBandwidth;
enet_uint32 packetThrottleInterval;
enet_uint32 packetThrottleAcceleration;
enet_uint32 packetThrottleDeceleration;
} ENetProtocolConnect;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint16 outgoingPeerID;
enet_uint16 mtu;
enet_uint32 windowSize;
enet_uint32 channelCount;
enet_uint32 incomingBandwidth;
enet_uint32 outgoingBandwidth;
enet_uint32 packetThrottleInterval;
enet_uint32 packetThrottleAcceleration;
enet_uint32 packetThrottleDeceleration;
} ENetProtocolVerifyConnect;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint32 incomingBandwidth;
enet_uint32 outgoingBandwidth;
} ENetProtocolBandwidthLimit;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint32 packetThrottleInterval;
enet_uint32 packetThrottleAcceleration;
enet_uint32 packetThrottleDeceleration;
} ENetProtocolThrottleConfigure;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint32 data;
} ENetProtocolDisconnect;
typedef struct
{
ENetProtocolCommandHeader header;
} ENetProtocolPing;
typedef struct
{
ENetProtocolCommandHeader header;
} ENetProtocolSendReliable;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint32 unreliableSequenceNumber;
} ENetProtocolSendUnreliable;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint32 unsequencedGroup;
} ENetProtocolSendUnsequenced;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint32 startSequenceNumber;
enet_uint32 fragmentCount;
enet_uint32 fragmentNumber;
enet_uint32 totalLength;
enet_uint32 fragmentOffset;
} ENetProtocolSendFragment;
typedef union
{
ENetProtocolCommandHeader header;
ENetProtocolAcknowledge acknowledge;
ENetProtocolConnect connect;
ENetProtocolVerifyConnect verifyConnect;
ENetProtocolDisconnect disconnect;
ENetProtocolPing ping;
ENetProtocolSendReliable sendReliable;
ENetProtocolSendUnreliable sendUnreliable;
ENetProtocolSendUnsequenced sendUnsequenced;
ENetProtocolSendFragment sendFragment;
ENetProtocolBandwidthLimit bandwidthLimit;
ENetProtocolThrottleConfigure throttleConfigure;
} ENetProtocol;
#endif /* __ENET_PROTOCOL_H__ */

View File

@@ -0,0 +1,18 @@
/**
@file time.h
@brief ENet time constants and macros
*/
#ifndef __ENET_TIME_H__
#define __ENET_TIME_H__
#define ENET_TIME_OVERFLOW 86400000
#define ENET_TIME_LESS(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW)
#define ENET_TIME_GREATER(a, b) ((b) - (a) >= ENET_TIME_OVERFLOW)
#define ENET_TIME_LESS_EQUAL(a, b) (! ENET_TIME_GREATER (a, b))
#define ENET_TIME_GREATER_EQUAL(a, b) (! ENET_TIME_LESS (a, b))
#define ENET_TIME_DIFFERENCE(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW ? (b) - (a) : (a) - (b))
#endif /* __ENET_TIME_H__ */

View File

@@ -0,0 +1,13 @@
/**
@file types.h
@brief type definitions for ENet
*/
#ifndef __ENET_TYPES_H__
#define __ENET_TYPES_H__
typedef unsigned char enet_uint8; /**< unsigned 8-bit type */
typedef unsigned short enet_uint16; /**< unsigned 16-bit type */
typedef unsigned int enet_uint32; /**< unsigned 32-bit type */
#endif /* __ENET_TYPES_H__ */

View File

@@ -0,0 +1,36 @@
/**
@file unix.h
@brief ENet Unix header
*/
#ifndef __ENET_UNIX_H__
#define __ENET_UNIX_H__
#include <stdlib.h>
#include <sys/types.h>
#include <netinet/in.h>
typedef int ENetSocket;
enum
{
ENET_SOCKET_NULL = -1
};
#define ENET_HOST_TO_NET_16(value) (htons (value)) /**< macro that converts host to net byte-order of a 16-bit value */
#define ENET_HOST_TO_NET_32(value) (htonl (value)) /**< macro that converts host to net byte-order of a 32-bit value */
#define ENET_NET_TO_HOST_16(value) (ntohs (value)) /**< macro that converts net to host byte-order of a 16-bit value */
#define ENET_NET_TO_HOST_32(value) (ntohl (value)) /**< macro that converts net to host byte-order of a 32-bit value */
typedef struct
{
void * data;
size_t dataLength;
} ENetBuffer;
#define ENET_CALLBACK
#define ENET_API extern
#endif /* __ENET_UNIX_H__ */

View File

@@ -0,0 +1,12 @@
/**
@file utility.h
@brief ENet utility header
*/
#ifndef __ENET_UTILITY_H__
#define __ENET_UTILITY_H__
#define ENET_MAX(x, y) ((x) > (y) ? (x) : (y))
#define ENET_MIN(x, y) ((x) < (y) ? (x) : (y))
#endif /* __ENET_UTILITY_H__ */

View File

@@ -0,0 +1,51 @@
/**
@file win32.h
@brief ENet Win32 header
*/
#ifndef __ENET_WIN32_H__
#define __ENET_WIN32_H__
#ifdef ENET_BUILDING_LIB
#pragma warning (disable: 4996) // 'strncpy' was declared deprecated
#pragma warning (disable: 4267) // size_t to int conversion
#pragma warning (disable: 4244) // 64bit to 32bit int
#pragma warning (disable: 4018) // signed/unsigned mismatch
#endif
#include <stdlib.h>
#include <winsock2.h>
typedef SOCKET ENetSocket;
enum
{
ENET_SOCKET_NULL = INVALID_SOCKET
};
#define ENET_HOST_TO_NET_16(value) (htons (value))
#define ENET_HOST_TO_NET_32(value) (htonl (value))
#define ENET_NET_TO_HOST_16(value) (ntohs (value))
#define ENET_NET_TO_HOST_32(value) (ntohl (value))
typedef struct
{
size_t dataLength;
void * data;
} ENetBuffer;
#define ENET_CALLBACK __cdecl
#if defined ENET_DLL
#if defined ENET_BUILDING_LIB
#define ENET_API __declspec( dllexport )
#else
#define ENET_API __declspec( dllimport )
#endif /* ENET_BUILDING_LIB */
#else /* !ENET_DLL */
#define ENET_API extern
#endif /* ENET_DLL */
#endif /* __ENET_WIN32_H__ */

View File

@@ -0,0 +1,57 @@
/**
@file list.c
@brief ENet linked list functions
*/
#define ENET_BUILDING_LIB 1
#include "enet/list.h"
/**
@defgroup list ENet linked list utility functions
@ingroup private
@{
*/
void
enet_list_clear (ENetList * list)
{
list -> sentinel.next = & list -> sentinel;
list -> sentinel.previous = & list -> sentinel;
}
ENetListIterator
enet_list_insert (ENetListIterator position, void * data)
{
ENetListIterator result = (ENetListIterator) data;
result -> previous = position -> previous;
result -> next = position;
result -> previous -> next = result;
position -> previous = result;
return result;
}
void *
enet_list_remove (ENetListIterator position)
{
position -> previous -> next = position -> next;
position -> next -> previous = position -> previous;
return position;
}
size_t
enet_list_size (ENetList * list)
{
size_t size = 0;
ENetListIterator position;
for (position = enet_list_begin (list);
position != enet_list_end (list);
position = enet_list_next (position))
++ size;
return size;
}
/** @} */

View File

@@ -0,0 +1,74 @@
/**
@file packet.c
@brief ENet packet management functions
*/
#include <string.h>
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
/** @defgroup Packet ENet packet functions
@{
*/
/** Creates a packet that may be sent to a peer.
@param dataContents initial contents of the packet's data; the packet's data will remain uninitialized if dataContents is NULL.
@param dataLength size of the data allocated for this packet
@param flags flags for this packet as described for the ENetPacket structure.
@returns the packet on success, NULL on failure
*/
ENetPacket *
enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags)
{
ENetPacket * packet = (ENetPacket *) enet_malloc (sizeof (ENetPacket));
packet -> data = (enet_uint8 *) enet_malloc (dataLength);
if (data != NULL)
memcpy (packet -> data, data, dataLength);
packet -> referenceCount = 0;
packet -> flags = flags;
packet -> dataLength = dataLength;
return packet;
}
/** Destroys the packet and deallocates its data.
@param packet packet to be destroyed
*/
void
enet_packet_destroy (ENetPacket * packet)
{
enet_free (packet -> data);
enet_free (packet);
}
/** Attempts to resize the data in the packet to length specified in the
dataLength parameter
@param packet packet to resize
@param dataLength new size for the packet data
@returns 0 on success, < 0 on failure
*/
int
enet_packet_resize (ENetPacket * packet, size_t dataLength)
{
enet_uint8 * newData;
if (dataLength <= packet -> dataLength)
{
packet -> dataLength = dataLength;
return 0;
}
newData = (enet_uint8 *) enet_malloc (dataLength);
memcpy (newData, packet -> data, packet -> dataLength);
enet_free (packet -> data);
packet -> data = newData;
packet -> dataLength = dataLength;
return 0;
}
/** @} */

View File

@@ -0,0 +1,657 @@
/**
@file peer.c
@brief ENet peer management functions
*/
#include <string.h>
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
/** @defgroup peer ENet peer functions
@{
*/
/** Configures throttle parameter for a peer.
Unreliable packets are dropped by ENet in response to the varying conditions
of the Internet connection to the peer. The throttle represents a probability
that an unreliable packet should not be dropped and thus sent by ENet to the peer.
The lowest mean round trip time from the sending of a reliable packet to the
receipt of its acknowledgement is measured over an amount of time specified by
the interval parameter in milliseconds. If a measured round trip time happens to
be significantly less than the mean round trip time measured over the interval,
then the throttle probability is increased to allow more traffic by an amount
specified in the acceleration parameter, which is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE
constant. If a measured round trip time happens to be significantly greater than
the mean round trip time measured over the interval, then the throttle probability
is decreased to limit traffic by an amount specified in the deceleration parameter, which
is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE constant. When the throttle has
a value of ENET_PEER_PACKET_THROTTLE_SCALE, on unreliable packets are dropped by
ENet, and so 100% of all unreliable packets will be sent. When the throttle has a
value of 0, all unreliable packets are dropped by ENet, and so 0% of all unreliable
packets will be sent. Intermediate values for the throttle represent intermediate
probabilities between 0% and 100% of unreliable packets being sent. The bandwidth
limits of the local and foreign hosts are taken into account to determine a
sensible limit for the throttle probability above which it should not raise even in
the best of conditions.
@param peer peer to configure
@param interval interval, in milliseconds, over which to measure lowest mean RTT; the default value is ENET_PEER_PACKET_THROTTLE_INTERVAL.
@param acceleration rate at which to increase the throttle probability as mean RTT declines
@param deceleration rate at which to decrease the throttle probability as mean RTT increases
*/
void
enet_peer_throttle_configure (ENetPeer * peer, enet_uint32 interval, enet_uint32 acceleration, enet_uint32 deceleration)
{
ENetProtocol command;
peer -> packetThrottleInterval = interval;
peer -> packetThrottleAcceleration = acceleration;
peer -> packetThrottleDeceleration = deceleration;
command.header.command = ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE;
command.header.channelID = 0xFF;
command.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE;
command.header.commandLength = sizeof (ENetProtocolThrottleConfigure);
command.throttleConfigure.packetThrottleInterval = ENET_HOST_TO_NET_32 (interval);
command.throttleConfigure.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (acceleration);
command.throttleConfigure.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (deceleration);
enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
}
int
enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt)
{
if (peer -> lastRoundTripTime <= peer -> lastRoundTripTimeVariance)
{
peer -> packetThrottle = peer -> packetThrottleLimit;
}
else
if (rtt < peer -> lastRoundTripTime)
{
peer -> packetThrottle += peer -> packetThrottleAcceleration;
if (peer -> packetThrottle > peer -> packetThrottleLimit)
peer -> packetThrottle = peer -> packetThrottleLimit;
return 1;
}
else
if (rtt > peer -> lastRoundTripTime + 2 * peer -> lastRoundTripTimeVariance)
{
if (peer -> packetThrottle > peer -> packetThrottleDeceleration)
peer -> packetThrottle -= peer -> packetThrottleDeceleration;
else
peer -> packetThrottle = 0;
return -1;
}
return 0;
}
/** Queues a packet to be sent.
@param peer destination for the packet
@param channelID channel on which to send
@param packet packet to send
@retval 0 on success
@retval < 0 on failure
*/
int
enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet)
{
ENetChannel * channel = & peer -> channels [channelID];
ENetProtocol command;
size_t fragmentLength;
if (peer -> state != ENET_PEER_STATE_CONNECTED ||
channelID >= peer -> channelCount)
return -1;
fragmentLength = peer -> mtu - sizeof (ENetProtocolHeader) - sizeof (ENetProtocolSendFragment);
if (packet -> dataLength > fragmentLength)
{
enet_uint32 fragmentCount = ENET_HOST_TO_NET_32 ((packet -> dataLength + fragmentLength - 1) / fragmentLength),
startSequenceNumber = ENET_HOST_TO_NET_32 (channel -> outgoingReliableSequenceNumber + 1),
fragmentNumber,
fragmentOffset;
packet -> flags = ENET_PACKET_FLAG_RELIABLE;
for (fragmentNumber = 0,
fragmentOffset = 0;
fragmentOffset < packet -> dataLength;
++ fragmentNumber,
fragmentOffset += fragmentLength)
{
command.header.command = ENET_PROTOCOL_COMMAND_SEND_FRAGMENT;
command.header.channelID = channelID;
command.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE;
command.header.commandLength = sizeof (ENetProtocolSendFragment);
command.sendFragment.startSequenceNumber = startSequenceNumber;
command.sendFragment.fragmentCount = fragmentCount;
command.sendFragment.fragmentNumber = ENET_HOST_TO_NET_32 (fragmentNumber);
command.sendFragment.totalLength = ENET_HOST_TO_NET_32 (packet -> dataLength);
command.sendFragment.fragmentOffset = ENET_NET_TO_HOST_32 (fragmentOffset);
if (packet -> dataLength - fragmentOffset < fragmentLength)
fragmentLength = packet -> dataLength - fragmentOffset;
enet_peer_queue_outgoing_command (peer, & command, packet, fragmentOffset, fragmentLength);
}
return 0;
}
command.header.channelID = channelID;
if (packet -> flags & ENET_PACKET_FLAG_RELIABLE)
{
command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE;
command.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE;
command.header.commandLength = sizeof (ENetProtocolSendReliable);
}
else
if (packet -> flags & ENET_PACKET_FLAG_UNSEQUENCED)
{
command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED;
command.header.flags = ENET_PROTOCOL_FLAG_UNSEQUENCED;
command.header.commandLength = sizeof (ENetProtocolSendUnsequenced);
command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_32 (peer -> outgoingUnsequencedGroup + 1);
}
else
{
command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE;
command.header.flags = 0;
command.header.commandLength = sizeof (ENetProtocolSendUnreliable);
command.sendUnreliable.unreliableSequenceNumber = ENET_HOST_TO_NET_32 (channel -> outgoingUnreliableSequenceNumber + 1);
}
enet_peer_queue_outgoing_command (peer, & command, packet, 0, packet -> dataLength);
return 0;
}
/** Attempts to dequeue any incoming queued packet.
@param peer peer to dequeue packets from
@param channelID channel on which to receive
@returns a pointer to the packet, or NULL if there are no available incoming queued packets
*/
ENetPacket *
enet_peer_receive (ENetPeer * peer, enet_uint8 channelID)
{
ENetChannel * channel = & peer -> channels [channelID];
ENetIncomingCommand * incomingCommand = NULL;
ENetPacket * packet;
if (enet_list_empty (& channel -> incomingUnreliableCommands) == 0)
{
incomingCommand = (ENetIncomingCommand *) enet_list_front (& channel -> incomingUnreliableCommands);
if (incomingCommand -> unreliableSequenceNumber > 0)
{
if (incomingCommand -> reliableSequenceNumber > channel -> incomingReliableSequenceNumber)
incomingCommand = NULL;
else
channel -> incomingUnreliableSequenceNumber = incomingCommand -> unreliableSequenceNumber;
}
}
if (incomingCommand == NULL &&
enet_list_empty (& channel -> incomingReliableCommands) == 0)
{
do
{
incomingCommand = (ENetIncomingCommand *) enet_list_front (& channel -> incomingReliableCommands);
if (incomingCommand -> fragmentsRemaining > 0 ||
incomingCommand -> reliableSequenceNumber > channel -> incomingReliableSequenceNumber + 1)
return NULL;
if (incomingCommand -> reliableSequenceNumber <= channel -> incomingReliableSequenceNumber)
{
-- incomingCommand -> packet -> referenceCount;
if (incomingCommand -> packet -> referenceCount == 0)
enet_packet_destroy (incomingCommand -> packet);
if (incomingCommand -> fragments != NULL)
enet_free (incomingCommand -> fragments);
enet_list_remove (& incomingCommand -> incomingCommandList);
enet_free (incomingCommand);
incomingCommand = NULL;
}
} while (incomingCommand == NULL &&
enet_list_empty (& channel -> incomingReliableCommands) == 0);
if (incomingCommand == NULL)
return NULL;
channel -> incomingReliableSequenceNumber = incomingCommand -> reliableSequenceNumber;
if (incomingCommand -> fragmentCount > 0)
channel -> incomingReliableSequenceNumber += incomingCommand -> fragmentCount - 1;
}
if (incomingCommand == NULL)
return NULL;
enet_list_remove (& incomingCommand -> incomingCommandList);
packet = incomingCommand -> packet;
-- packet -> referenceCount;
if (incomingCommand -> fragments != NULL)
enet_free (incomingCommand -> fragments);
enet_free (incomingCommand);
return packet;
}
static void
enet_peer_reset_outgoing_commands (ENetList * queue)
{
ENetOutgoingCommand * outgoingCommand;
while (enet_list_empty (queue) == 0)
{
outgoingCommand = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (queue));
if (outgoingCommand -> packet != NULL)
{
-- outgoingCommand -> packet -> referenceCount;
if (outgoingCommand -> packet -> referenceCount == 0)
enet_packet_destroy (outgoingCommand -> packet);
}
enet_free (outgoingCommand);
}
}
static void
enet_peer_reset_incoming_commands (ENetList * queue)
{
ENetIncomingCommand * incomingCommand;
while (enet_list_empty (queue) == 0)
{
incomingCommand = (ENetIncomingCommand *) enet_list_remove (enet_list_begin (queue));
if (incomingCommand -> packet != NULL)
{
-- incomingCommand -> packet -> referenceCount;
if (incomingCommand -> packet -> referenceCount == 0)
enet_packet_destroy (incomingCommand -> packet);
}
if (incomingCommand -> fragments != NULL)
enet_free (incomingCommand -> fragments);
enet_free (incomingCommand);
}
}
void
enet_peer_reset_queues (ENetPeer * peer)
{
ENetChannel * channel;
while (enet_list_empty (& peer -> acknowledgements) == 0)
enet_free (enet_list_remove (enet_list_begin (& peer -> acknowledgements)));
enet_peer_reset_outgoing_commands (& peer -> sentReliableCommands);
enet_peer_reset_outgoing_commands (& peer -> sentUnreliableCommands);
enet_peer_reset_outgoing_commands (& peer -> outgoingReliableCommands);
enet_peer_reset_outgoing_commands (& peer -> outgoingUnreliableCommands);
if (peer -> channels != NULL && peer -> channelCount > 0)
{
for (channel = peer -> channels;
channel < & peer -> channels [peer -> channelCount];
++ channel)
{
enet_peer_reset_incoming_commands (& channel -> incomingReliableCommands);
enet_peer_reset_incoming_commands (& channel -> incomingUnreliableCommands);
}
enet_free (peer -> channels);
}
peer -> channels = NULL;
peer -> channelCount = 0;
}
/** Forcefully disconnects a peer.
@param peer peer to forcefully disconnect
@remarks The foreign host represented by the peer is not notified of the disconnection and will timeout
on its connection to the local host.
*/
void
enet_peer_reset (ENetPeer * peer)
{
peer -> outgoingPeerID = 0xFFFF;
peer -> challenge = 0;
peer -> address.host = ENET_HOST_ANY;
peer -> address.port = 0;
peer -> state = ENET_PEER_STATE_DISCONNECTED;
peer -> incomingBandwidth = 0;
peer -> outgoingBandwidth = 0;
peer -> incomingBandwidthThrottleEpoch = 0;
peer -> outgoingBandwidthThrottleEpoch = 0;
peer -> incomingDataTotal = 0;
peer -> outgoingDataTotal = 0;
peer -> lastSendTime = 0;
peer -> lastReceiveTime = 0;
peer -> nextTimeout = 0;
peer -> earliestTimeout = 0;
peer -> packetLossEpoch = 0;
peer -> packetsSent = 0;
peer -> packetsLost = 0;
peer -> packetLoss = 0;
peer -> packetLossVariance = 0;
peer -> packetThrottle = ENET_PEER_DEFAULT_PACKET_THROTTLE;
peer -> packetThrottleLimit = ENET_PEER_PACKET_THROTTLE_SCALE;
peer -> packetThrottleCounter = 0;
peer -> packetThrottleEpoch = 0;
peer -> packetThrottleAcceleration = ENET_PEER_PACKET_THROTTLE_ACCELERATION;
peer -> packetThrottleDeceleration = ENET_PEER_PACKET_THROTTLE_DECELERATION;
peer -> packetThrottleInterval = ENET_PEER_PACKET_THROTTLE_INTERVAL;
peer -> lastRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
peer -> lowestRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
peer -> lastRoundTripTimeVariance = 0;
peer -> highestRoundTripTimeVariance = 0;
peer -> roundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
peer -> roundTripTimeVariance = 0;
peer -> mtu = peer -> host -> mtu;
peer -> reliableDataInTransit = 0;
peer -> outgoingReliableSequenceNumber = 0;
peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
peer -> incomingUnsequencedGroup = 0;
peer -> outgoingUnsequencedGroup = 0;
peer -> disconnectData = 0;
memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow));
enet_peer_reset_queues (peer);
}
/** Sends a ping request to a peer.
@param peer destination for the ping request
@remarks ping requests factor into the mean round trip time as designated by the
roundTripTime field in the ENetPeer structure. Enet automatically pings all connected
peers at regular intervals, however, this function may be called to ensure more
frequent ping requests.
*/
void
enet_peer_ping (ENetPeer * peer)
{
ENetProtocol command;
if (peer -> state != ENET_PEER_STATE_CONNECTED)
return;
command.header.command = ENET_PROTOCOL_COMMAND_PING;
command.header.channelID = 0xFF;
command.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE;
command.header.commandLength = sizeof (ENetProtocolPing);
enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
}
/** Force an immediate disconnection from a peer.
@param peer peer to disconnect
@param data data describing the disconnection
@remarks No ENET_EVENT_DISCONNECT event will be generated. The foreign peer is not
guarenteed to receive the disconnect notification, and is reset immediately upon
return from this function.
*/
void
enet_peer_disconnect_now (ENetPeer * peer, enet_uint32 data)
{
ENetProtocol command;
if (peer -> state == ENET_PEER_STATE_DISCONNECTED)
return;
if (peer -> state != ENET_PEER_STATE_ZOMBIE &&
peer -> state != ENET_PEER_STATE_DISCONNECTING)
{
enet_peer_reset_queues (peer);
command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT;
command.header.channelID = 0xFF;
command.header.flags = ENET_PROTOCOL_FLAG_UNSEQUENCED;
command.header.commandLength = sizeof (ENetProtocolDisconnect);
command.disconnect.data = data;
enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
enet_host_flush (peer -> host);
}
enet_peer_reset (peer);
}
/** Request a disconnection from a peer.
@param peer peer to request a disconnection
@param data data describing the disconnection
@remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
once the disconnection is complete.
*/
void
enet_peer_disconnect (ENetPeer * peer, enet_uint32 data)
{
ENetProtocol command;
if (peer -> state == ENET_PEER_STATE_DISCONNECTING ||
peer -> state == ENET_PEER_STATE_DISCONNECTED ||
peer -> state == ENET_PEER_STATE_ZOMBIE)
return;
enet_peer_reset_queues (peer);
command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT;
command.header.channelID = 0xFF;
command.header.flags = ENET_PROTOCOL_FLAG_UNSEQUENCED;
command.header.commandLength = sizeof (ENetProtocolDisconnect);
command.disconnect.data = data;
if (peer -> state == ENET_PEER_STATE_CONNECTED)
command.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE;
enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
if (peer -> state == ENET_PEER_STATE_CONNECTED)
peer -> state = ENET_PEER_STATE_DISCONNECTING;
else
{
enet_host_flush (peer -> host);
enet_peer_reset (peer);
}
}
ENetAcknowledgement *
enet_peer_queue_acknowledgement (ENetPeer * peer, const ENetProtocol * command, enet_uint32 sentTime)
{
ENetAcknowledgement * acknowledgement;
peer -> outgoingDataTotal += sizeof (ENetProtocolAcknowledge);
acknowledgement = (ENetAcknowledgement *) enet_malloc (sizeof (ENetAcknowledgement));
acknowledgement -> sentTime = sentTime;
acknowledgement -> command = * command;
enet_list_insert (enet_list_end (& peer -> acknowledgements), acknowledgement);
return acknowledgement;
}
ENetOutgoingCommand *
enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 offset, enet_uint16 length)
{
ENetChannel * channel = & peer -> channels [command -> header.channelID];
ENetOutgoingCommand * outgoingCommand;
peer -> outgoingDataTotal += command -> header.commandLength + length;
outgoingCommand = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand));
if (command -> header.channelID == 0xFF)
{
++ peer -> outgoingReliableSequenceNumber;
outgoingCommand -> reliableSequenceNumber = peer -> outgoingReliableSequenceNumber;
outgoingCommand -> unreliableSequenceNumber = 0;
}
else
if (command -> header.flags & ENET_PROTOCOL_FLAG_ACKNOWLEDGE)
{
++ channel -> outgoingReliableSequenceNumber;
outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
outgoingCommand -> unreliableSequenceNumber = 0;
}
else
if (command -> header.flags & ENET_PROTOCOL_FLAG_UNSEQUENCED)
{
++ peer -> outgoingUnsequencedGroup;
outgoingCommand -> reliableSequenceNumber = 0;
outgoingCommand -> unreliableSequenceNumber = 0;
}
else
{
++ channel -> outgoingUnreliableSequenceNumber;
outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
outgoingCommand -> unreliableSequenceNumber = channel -> outgoingUnreliableSequenceNumber;
}
outgoingCommand -> sentTime = 0;
outgoingCommand -> roundTripTimeout = 0;
outgoingCommand -> roundTripTimeoutLimit = 0;
outgoingCommand -> fragmentOffset = offset;
outgoingCommand -> fragmentLength = length;
outgoingCommand -> packet = packet;
outgoingCommand -> command = * command;
outgoingCommand -> command.header.reliableSequenceNumber = ENET_HOST_TO_NET_32 (outgoingCommand -> reliableSequenceNumber);
if (packet != NULL)
++ packet -> referenceCount;
if (command -> header.flags & ENET_PROTOCOL_FLAG_ACKNOWLEDGE)
enet_list_insert (enet_list_end (& peer -> outgoingReliableCommands), outgoingCommand);
else
enet_list_insert (enet_list_end (& peer -> outgoingUnreliableCommands), outgoingCommand);
return outgoingCommand;
}
ENetIncomingCommand *
enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 fragmentCount)
{
ENetChannel * channel = & peer -> channels [command -> header.channelID];
enet_uint32 unreliableSequenceNumber = 0;
ENetIncomingCommand * incomingCommand;
ENetListIterator currentCommand;
switch (command -> header.command)
{
case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands));
currentCommand != enet_list_end (& channel -> incomingReliableCommands);
currentCommand = enet_list_previous (currentCommand))
{
incomingCommand = (ENetIncomingCommand *) currentCommand;
if (incomingCommand -> reliableSequenceNumber <= command -> header.reliableSequenceNumber)
{
if (incomingCommand -> reliableSequenceNumber < command -> header.reliableSequenceNumber)
break;
goto freePacket;
}
}
break;
case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
unreliableSequenceNumber = ENET_NET_TO_HOST_32 (command -> sendUnreliable.unreliableSequenceNumber);
if (command -> header.reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
goto freePacket;
if (unreliableSequenceNumber <= channel -> incomingUnreliableSequenceNumber)
goto freePacket;
for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands));
currentCommand != enet_list_end (& channel -> incomingUnreliableCommands);
currentCommand = enet_list_previous (currentCommand))
{
incomingCommand = (ENetIncomingCommand *) currentCommand;
if (incomingCommand -> unreliableSequenceNumber <= unreliableSequenceNumber)
{
if (incomingCommand -> unreliableSequenceNumber < unreliableSequenceNumber)
break;
goto freePacket;
}
}
break;
case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
currentCommand = enet_list_end (& channel -> incomingUnreliableCommands);
break;
default:
goto freePacket;
}
incomingCommand = (ENetIncomingCommand *) enet_malloc (sizeof (ENetIncomingCommand));
incomingCommand -> reliableSequenceNumber = command -> header.reliableSequenceNumber;
incomingCommand -> unreliableSequenceNumber = unreliableSequenceNumber;
incomingCommand -> command = * command;
incomingCommand -> fragmentCount = fragmentCount;
incomingCommand -> fragmentsRemaining = fragmentCount;
incomingCommand -> packet = packet;
incomingCommand -> fragments = NULL;
if (fragmentCount > 0)
{
incomingCommand -> fragments = (enet_uint32 *) enet_malloc ((fragmentCount + 31) / 32 * sizeof (enet_uint32));
memset (incomingCommand -> fragments, 0, (fragmentCount + 31) / 32 * sizeof (enet_uint32));
}
if (packet != NULL)
++ packet -> referenceCount;
enet_list_insert (enet_list_next (currentCommand), incomingCommand);
return incomingCommand;
freePacket:
if (packet != NULL)
{
if (packet -> referenceCount == 0)
enet_packet_destroy (packet);
}
return NULL;
}
/** @} */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,407 @@
/**
@file unix.c
@brief ENet Unix system specific functions
*/
#ifndef WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#ifdef ANDROID
#define HAS_SOCKLEN_T 1
#define HAS_POLL 1
#define HAS_FCNTL 1
#define HAS_INET_PTON 1
// #define HAS_GETHOSTBYNAME_R 1 // Incompatible argument list
#define HAS_INET_NTOP 1
#define HAS_MSGHDR_FLAGS 1
#endif
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
#ifdef HAS_FCNTL
#include <fcntl.h>
#endif
#ifdef __APPLE__
#undef HAS_POLL
#endif
#ifdef HAS_POLL
#include <sys/poll.h>
#endif
#ifndef HAS_SOCKLEN_T
typedef int socklen_t;
#endif
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
static enet_uint32 timeBase = 0;
int
enet_initialize (void)
{
return 0;
}
void
enet_deinitialize (void)
{
}
enet_uint32
enet_time_get (void)
{
struct timeval timeVal;
gettimeofday (& timeVal, NULL);
return timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - timeBase;
}
void
enet_time_set (enet_uint32 newTimeBase)
{
struct timeval timeVal;
gettimeofday (& timeVal, NULL);
timeBase = timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - newTimeBase;
}
int
enet_address_set_host (ENetAddress * address, const char * name)
{
struct hostent * hostEntry = NULL;
#ifdef HAS_GETHOSTBYNAME_R
struct hostent hostData;
char buffer [2048];
int errnum;
#if defined(linux) || defined(__GLIBC__) || defined(__GNU__)
gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
#else
hostEntry = gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & errnum);
#endif
#else
hostEntry = gethostbyname (name);
#endif
if (hostEntry == NULL ||
hostEntry -> h_addrtype != AF_INET)
{
#ifdef HAS_INET_PTON
if (! inet_pton (AF_INET, name, & address -> host))
#else
if (! inet_aton (name, (struct in_addr *) & address -> host))
#endif
return -1;
return 0;
}
address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
return 0;
}
int
enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
{
struct in_addr in;
struct hostent * hostEntry = NULL;
#ifdef HAS_GETHOSTBYADDR_R
struct hostent hostData;
char buffer [2048];
int errnum;
in.s_addr = address -> host;
#if defined(linux) || defined(__GLIBC__) || defined(__GNU__)
gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
#else
hostEntry = gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & errnum);
#endif
#else
in.s_addr = address -> host;
hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
#endif
if (hostEntry == NULL)
{
#ifdef HAS_INET_NTOP
if (inet_ntop (AF_INET, & address -> host, name, nameLength) == NULL)
#else
char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
if (addr != NULL)
strncpy (name, addr, nameLength);
else
#endif
return -1;
return 0;
}
strncpy (name, hostEntry -> h_name, nameLength);
return 0;
}
ENetSocket
enet_socket_create (ENetSocketType type, const ENetAddress * address)
{
ENetSocket newSocket = socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
int receiveBufferSize = ENET_HOST_RECEIVE_BUFFER_SIZE,
allowBroadcasting = 1;
#ifndef HAS_FCNTL
int nonBlocking = 1;
#endif
struct sockaddr_in sin;
if (newSocket == ENET_SOCKET_NULL)
return ENET_SOCKET_NULL;
if (type == ENET_SOCKET_TYPE_DATAGRAM)
{
#ifdef HAS_FCNTL
fcntl (newSocket, F_SETFL, O_NONBLOCK | fcntl (newSocket, F_GETFL));
#else
ioctl (newSocket, FIONBIO, & nonBlocking);
#endif
setsockopt (newSocket, SOL_SOCKET, SO_RCVBUF, (char *) & receiveBufferSize, sizeof (int));
setsockopt (newSocket, SOL_SOCKET, SO_BROADCAST, (char *) & allowBroadcasting, sizeof (int));
}
if (address == NULL)
return newSocket;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
if (bind (newSocket,
(struct sockaddr *) & sin,
sizeof (struct sockaddr_in)) == -1 ||
(type == ENET_SOCKET_TYPE_STREAM &&
listen (newSocket, SOMAXCONN) == -1))
{
close (newSocket);
return ENET_SOCKET_NULL;
}
return newSocket;
}
int
enet_socket_connect (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
return connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
}
ENetSocket
enet_socket_accept (ENetSocket socket, ENetAddress * address)
{
int result;
struct sockaddr_in sin;
socklen_t sinLength = sizeof (struct sockaddr_in);
result = accept (socket,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? & sinLength : NULL);
if (result == -1)
return ENET_SOCKET_NULL;
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
return result;
}
void
enet_socket_destroy (ENetSocket socket)
{
close (socket);
}
int
enet_socket_send (ENetSocket socket,
const ENetAddress * address,
const ENetBuffer * buffers,
size_t bufferCount)
{
struct msghdr msgHdr;
struct sockaddr_in sin;
int sentLength;
memset (& msgHdr, 0, sizeof (struct msghdr));
if (address != NULL)
{
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
msgHdr.msg_name = & sin;
msgHdr.msg_namelen = sizeof (struct sockaddr_in);
}
msgHdr.msg_iov = (struct iovec *) buffers;
msgHdr.msg_iovlen = bufferCount;
sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL);
if (sentLength == -1)
{
if (errno == EWOULDBLOCK)
return 0;
return -1;
}
return sentLength;
}
int
enet_socket_receive (ENetSocket socket,
ENetAddress * address,
ENetBuffer * buffers,
size_t bufferCount)
{
struct msghdr msgHdr;
struct sockaddr_in sin;
int recvLength;
memset (& msgHdr, 0, sizeof (struct msghdr));
if (address != NULL)
{
msgHdr.msg_name = & sin;
msgHdr.msg_namelen = sizeof (struct sockaddr_in);
}
msgHdr.msg_iov = (struct iovec *) buffers;
msgHdr.msg_iovlen = bufferCount;
recvLength = recvmsg (socket, & msgHdr, MSG_NOSIGNAL);
if (recvLength == -1)
{
if (errno == EWOULDBLOCK)
return 0;
return -1;
}
#ifdef HAS_MSGHDR_FLAGS
if (msgHdr.msg_flags & MSG_TRUNC)
return -1;
#endif
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
return recvLength;
}
int
enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout)
{
#ifdef HAS_POLL
struct pollfd pollSocket;
int pollCount;
pollSocket.fd = socket;
pollSocket.events = 0;
if (* condition & ENET_SOCKET_WAIT_SEND)
pollSocket.events |= POLLOUT;
if (* condition & ENET_SOCKET_WAIT_RECEIVE)
pollSocket.events |= POLLIN;
pollCount = poll (& pollSocket, 1, timeout);
if (pollCount < 0)
return -1;
* condition = ENET_SOCKET_WAIT_NONE;
if (pollCount == 0)
return 0;
if (pollSocket.revents & POLLOUT)
* condition |= ENET_SOCKET_WAIT_SEND;
if (pollSocket.revents & POLLIN)
* condition |= ENET_SOCKET_WAIT_RECEIVE;
return 0;
#else
fd_set readSet, writeSet;
struct timeval timeVal;
int selectCount;
timeVal.tv_sec = timeout / 1000;
timeVal.tv_usec = (timeout % 1000) * 1000;
FD_ZERO (& readSet);
FD_ZERO (& writeSet);
if (* condition & ENET_SOCKET_WAIT_SEND)
FD_SET (socket, & writeSet);
if (* condition & ENET_SOCKET_WAIT_RECEIVE)
FD_SET (socket, & readSet);
selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal);
if (selectCount < 0)
return -1;
* condition = ENET_SOCKET_WAIT_NONE;
if (selectCount == 0)
return 0;
if (FD_ISSET (socket, & writeSet))
* condition |= ENET_SOCKET_WAIT_SEND;
if (FD_ISSET (socket, & readSet))
* condition |= ENET_SOCKET_WAIT_RECEIVE;
return 0;
#endif
}
#endif

View File

@@ -0,0 +1,309 @@
/**
@file win32.c
@brief ENet Win32 system specific functions
*/
#ifdef WIN32
#include <time.h>
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
static enet_uint32 timeBase = 0;
int
enet_initialize (void)
{
WORD versionRequested = MAKEWORD (1, 1);
WSADATA wsaData;
if (WSAStartup (versionRequested, & wsaData))
return -1;
if (LOBYTE (wsaData.wVersion) != 1||
HIBYTE (wsaData.wVersion) != 1)
{
WSACleanup ();
return -1;
}
timeBeginPeriod (1);
return 0;
}
void
enet_deinitialize (void)
{
timeEndPeriod (1);
WSACleanup ();
}
enet_uint32
enet_time_get (void)
{
return (enet_uint32) timeGetTime () - timeBase;
}
void
enet_time_set (enet_uint32 newTimeBase)
{
timeBase = (enet_uint32) timeGetTime () - newTimeBase;
}
int
enet_address_set_host (ENetAddress * address, const char * name)
{
struct hostent * hostEntry;
hostEntry = gethostbyname (name);
if (hostEntry == NULL ||
hostEntry -> h_addrtype != AF_INET)
{
unsigned long host = inet_addr (name);
if (host == INADDR_NONE)
return -1;
address -> host = host;
return 0;
}
address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
return 0;
}
int
enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
{
struct in_addr in;
struct hostent * hostEntry;
in.s_addr = address -> host;
hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
if (hostEntry == NULL)
{
char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
if (addr == NULL)
return -1;
strncpy (name, addr, nameLength);
return 0;
}
strncpy (name, hostEntry -> h_name, nameLength);
return 0;
}
ENetSocket
enet_socket_create (ENetSocketType type, const ENetAddress * address)
{
ENetSocket newSocket = socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
u_long nonBlocking = 1;
int receiveBufferSize = ENET_HOST_RECEIVE_BUFFER_SIZE,
allowBroadcasting = 1;
struct sockaddr_in sin;
if (newSocket == ENET_SOCKET_NULL)
return ENET_SOCKET_NULL;
if (type == ENET_SOCKET_TYPE_DATAGRAM)
{
ioctlsocket (newSocket, FIONBIO, & nonBlocking);
setsockopt (newSocket, SOL_SOCKET, SO_RCVBUF, (char *) & receiveBufferSize, sizeof (int));
setsockopt (newSocket, SOL_SOCKET, SO_BROADCAST, (char *) & allowBroadcasting, sizeof (int));
}
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
if (address != NULL)
{
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
}
else
{
sin.sin_port = 0;
sin.sin_addr.s_addr = INADDR_ANY;
}
if (bind (newSocket,
(struct sockaddr *) & sin,
sizeof (struct sockaddr_in)) == SOCKET_ERROR ||
(type == ENET_SOCKET_TYPE_STREAM &&
address != NULL &&
listen (newSocket, SOMAXCONN) == SOCKET_ERROR))
{
closesocket (newSocket);
return ENET_SOCKET_NULL;
}
return newSocket;
}
int
enet_socket_connect (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
return connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
}
ENetSocket
enet_socket_accept (ENetSocket socket, ENetAddress * address)
{
SOCKET result;
struct sockaddr_in sin;
int sinLength = sizeof (struct sockaddr_in);
result = accept (socket,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? & sinLength : NULL);
if (result == INVALID_SOCKET)
return ENET_SOCKET_NULL;
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
return result;
}
void
enet_socket_destroy (ENetSocket socket)
{
closesocket (socket);
}
int
enet_socket_send (ENetSocket socket,
const ENetAddress * address,
const ENetBuffer * buffers,
size_t bufferCount)
{
struct sockaddr_in sin;
DWORD sentLength;
if (address != NULL)
{
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
}
if (WSASendTo (socket,
(LPWSABUF) buffers,
(DWORD) bufferCount,
& sentLength,
0,
address != NULL ? (struct sockaddr *) & sin : 0,
address != NULL ? sizeof (struct sockaddr_in) : 0,
NULL,
NULL) == SOCKET_ERROR)
{
if (WSAGetLastError () == WSAEWOULDBLOCK)
return 0;
return -1;
}
return (int) sentLength;
}
int
enet_socket_receive (ENetSocket socket,
ENetAddress * address,
ENetBuffer * buffers,
size_t bufferCount)
{
INT sinLength = sizeof (struct sockaddr_in);
DWORD flags = 0,
recvLength;
struct sockaddr_in sin;
if (WSARecvFrom (socket,
(LPWSABUF) buffers,
(DWORD) bufferCount,
& recvLength,
& flags,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? & sinLength : NULL,
NULL,
NULL) == SOCKET_ERROR)
{
switch (WSAGetLastError ())
{
case WSAEWOULDBLOCK:
case WSAECONNRESET:
return 0;
}
return -1;
}
if (flags & MSG_PARTIAL)
return -1;
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
return (int) recvLength;
}
int
enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout)
{
fd_set readSet, writeSet;
struct timeval timeVal;
int selectCount;
timeVal.tv_sec = timeout / 1000;
timeVal.tv_usec = (timeout % 1000) * 1000;
FD_ZERO (& readSet);
FD_ZERO (& writeSet);
if (* condition & ENET_SOCKET_WAIT_SEND)
FD_SET (socket, & writeSet);
if (* condition & ENET_SOCKET_WAIT_RECEIVE)
FD_SET (socket, & readSet);
selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal);
if (selectCount < 0)
return -1;
* condition = ENET_SOCKET_WAIT_NONE;
if (selectCount == 0)
return 0;
if (FD_ISSET (socket, & writeSet))
* condition |= ENET_SOCKET_WAIT_SEND;
if (FD_ISSET (socket, & readSet))
* condition |= ENET_SOCKET_WAIT_RECEIVE;
return 0;
}
#endif

View File

@@ -0,0 +1,151 @@
#include "SDL.h"
#include "IMG_SavePNG.h"
#include "png.h"
#include <stdlib.h>
#include <setjmp.h>
#define IMG_SetError(a) SDL_SetError(a)
/* Save a PNG type image to an SDL datasource */
static void png_write_data(png_structp ctx, png_bytep area, png_size_t size)
{
SDL_RWops *src;
src = (SDL_RWops *)png_get_io_ptr(ctx);
SDL_RWwrite(src, area, size, 1);
}
static void png_io_flush(png_structp ctx)
{
SDL_RWops *src;
src = (SDL_RWops *)png_get_io_ptr(ctx);
/* how do I flush src? */
}
static int png_colortype_from_surface(SDL_Surface *surface)
{
int colortype = PNG_COLOR_MASK_COLOR; /* grayscale not supported */
if (surface->format->palette)
colortype |= PNG_COLOR_MASK_PALETTE;
else if (surface->format->Amask)
colortype |= PNG_COLOR_MASK_ALPHA;
return colortype;
}
static void png_user_warn(png_structp ctx, png_const_charp str)
{
fprintf(stderr, "libpng: warning: %s\n", str);
}
static void png_user_error(png_structp ctx, png_const_charp str)
{
fprintf(stderr, "libpng: error: %s\n", str);
}
int IMG_SavePNG_RW(SDL_Surface *face, SDL_RWops *src) {
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
const int rmask = 0x00ff0000;
const int gmask = 0x0000ff00;
const int bmask = 0x000000ff;
const int amask = 0x00000000;
#else
const int rmask = 0x000000ff;
const int gmask = 0x0000ff00;
const int bmask = 0x00ff0000;
const int amask = 0x00000000;
#endif
int result = -1;
SDL_Surface *surface = SDL_CreateRGBSurface(SDL_SWSURFACE, face->w, face->h, 24,
rmask, gmask, bmask, amask);
if (surface) {
png_structp png_ptr;
SDL_BlitSurface(face, NULL, surface, NULL);
SDL_LockSurface(surface);
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, png_user_error, png_user_warn);
if (!png_ptr) {
IMG_SetError("Couldn't allocate memory for PNG file");
}
else {
/* Allocate/initialize the image information data. REQUIRED */
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
IMG_SetError("Couldn't create image information for PNG file");
}
else {
png_bytep *row_pointers = 0;
/* Set error handling. */
if (setjmp(png_ptr->jmpbuf)) {
IMG_SetError("Error writing the PNG file");
}
else {
int colortype;
png_set_write_fn(png_ptr, src, png_write_data, png_io_flush);
/* Set the image information here. Width and height are up to 2^31,
* bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
* the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
* PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
* or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
* PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
* currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
*/
colortype = png_colortype_from_surface(surface);
png_set_IHDR(png_ptr, info_ptr, surface->w, surface->h, 8,
colortype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
/* Write the file header information. REQUIRED */
png_write_info(png_ptr, info_ptr);
/* pack pixels into bytes */
png_set_packing(png_ptr);
/* Create the array of pointers to image data */
row_pointers = (png_bytep*) malloc(sizeof(png_bytep)*surface->h);
if (!row_pointers) {
IMG_SetError("Couldn't allocate PNG row pointers");
}
else {
int i;
for (i = 0; i < surface->h; i++)
row_pointers[i] = (png_bytep)(Uint8 *)surface->pixels + i*surface->pitch;
/* write out the entire image data in one call */
png_write_image(png_ptr, row_pointers);
png_write_end(png_ptr, info_ptr);
result = 0; /* success! */
}
}
if (row_pointers)
free(row_pointers);
png_destroy_info_struct(png_ptr, &info_ptr);
}
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
}
SDL_UnlockSurface(surface);
SDL_FreeSurface(surface);
}
return result;
}
int IMG_SavePNG(SDL_Surface *surface, const char *file)
{
SDL_RWops *out = SDL_RWFromFile(file, "wb");
int ret;
if(!out)
return -1;
ret = IMG_SavePNG_RW(surface, out);
SDL_RWclose(out);
return ret;
}

View File

@@ -0,0 +1,28 @@
/*
IMG_SavePNG.h
Originally a patch to SDL_image, LGPL
(c) 2001 Darren Grant
Endian fixes by J. Fortmann
*/
#ifndef _IMG_SavePNG_h
#define _IMG_SavePNG_h
#include "SDL.h"
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
extern "C" {
#endif
int IMG_SavePNG_RW(SDL_Surface *face, SDL_RWops *src);
int IMG_SavePNG(SDL_Surface *surface, const char *file);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
};
#endif
#endif // _IMG_SavePNG_h

View File

@@ -0,0 +1,47 @@
This directory contains the reusable parts of Enigma, i.e., all the
code that I had the time and leisure to write more or less properly.
Some of the classes and functions are rather complete and useful but
others are only useful for certain applications and would need further
features or refinements to make genuinely reusable. Anyway, if you
find any of it useful, feel free to use it in your game or
application.
Here is a short rundown of the files and the services they provide:
File Description
--------------------------------------------------------------------
alist.hh Associative lists
argp.hh Parser for command line (POSIX and GNU-style options)
buffer.hh Stream-like buffer for binary data, takes care of
endianness
cache.hh Simple facility for resource caching
callback.hh Generic callbacks, turned out not to be that useful
dict.hh std::map alike hash table; useful but a bit incomplete
font.hh Bitmap fonts, to be used in connection with the stuff
in video.hh
geom.hh Rectangles and rectangle lists and some geometric
operations like intersection, bounding box, etc;
fairly complete
math.hh Generic vectors in 2 and 3 dimensions
sdl.hh Some utilities and bindings for SDL
tools.hh General utilities like delete_sequence() and delete_map()
video.hh Class wrappers and some higher level operations SDL's
video operations; useful, but incomplete and in need of
a better design.
windows.hh Attempt at a reusable window manager that keeps track
of the stacking order, dirty rectangles, etc. Needs a
little more work to make it really useful.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,143 @@
/*
SDL_gfxPrimitives: graphics primitives for SDL
LGPL (c) A. Schiffler
*/
#ifndef _SDL_gfxPrimitives_h
#define _SDL_gfxPrimitives_h
#include <math.h>
#ifndef M_PI
#define M_PI 3.141592654
#endif
#include "SDL.h"
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
extern "C" {
#endif
/* ----- Versioning */
#define SDL_GFXPRIMITIVES_MAJOR 1
#define SDL_GFXPRIMITIVES_MINOR 5
/* ----- Prototypes */
/* Note: all ___Color routines expect the color to be in format 0xRRGGBBAA */
/* Pixel */
int pixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color);
int pixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/* Horizontal line */
int hlineColor(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color);
int hlineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/* Vertical line */
int vlineColor(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color);
int vlineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/* Rectangle */
int rectangleColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color);
int rectangleRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1,
Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/* Filled rectangle (Box) */
int boxColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color);
int boxRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2,
Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/* Line */
int lineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color);
int lineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1,
Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/* AA Line */
int aalineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color);
int aalineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1,
Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/* Circle */
int circleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color);
int circleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/* AA Circle */
int aacircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color);
int aacircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y,
Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/* Filled Circle */
int filledCircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color);
int filledCircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y,
Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/* Ellipse */
int ellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color);
int ellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y,
Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/* AA Ellipse */
int aaellipseColor(SDL_Surface * dst, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 ry, Uint32 color);
int aaellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y,
Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/* Filled Ellipse */
int filledEllipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color);
int filledEllipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y,
Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/* Filled Pie */
int filledpieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
Sint16 start, Sint16 end, Uint32 color);
int filledpieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/* Polygon */
int polygonColor(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, Uint32 color);
int polygonRGBA(SDL_Surface * dst, Sint16 * vx, Sint16 * vy,
int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/* AA-Polygon */
int aapolygonColor(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, Uint32 color);
int aapolygonRGBA(SDL_Surface * dst, Sint16 * vx, Sint16 * vy,
int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/* Filled Polygon */
int filledPolygonColor(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, int color);
int filledPolygonRGBA(SDL_Surface * dst, Sint16 * vx,
Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/* 8x8 Characters/Strings */
int characterColor(SDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint32 color);
int characterRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
int stringColor(SDL_Surface * dst, Sint16 x, Sint16 y, char *c, Uint32 color);
int stringRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, char *c, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
};
#endif
#endif /* _SDL_gfxPrimitives_h */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,88 @@
/*
SDL_rotozoom - rotozoomer
LGPL (c) A. Schiffler
*/
#ifndef _SDL_rotozoom_h
#define _SDL_rotozoom_h
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
extern "C" {
#endif
#include <math.h>
#ifndef M_PI
#define M_PI 3.141592654
#endif
#include "SDL.h"
/* ---- Defines */
#define SMOOTHING_OFF 0
#define SMOOTHING_ON 1
/* ---- Structures */
typedef struct tColorRGBA {
Uint8 r;
Uint8 g;
Uint8 b;
Uint8 a;
} tColorRGBA;
typedef struct tColorY {
Uint8 y;
} tColorY;
/* ---- Prototypes */
/*
rotozoomSurface()
Rotates and zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
'angle' is the rotation in degrees. 'zoom' a scaling factor. If 'smooth' is 1
then the destination 32bit surface is anti-aliased. If the surface is not 8bit
or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
*/
SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth);
/* Returns the size of the target surface for a rotozoomSurface() call */
void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth,
int *dstheight);
/*
zoomSurface()
Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
'zoomx' and 'zoomy' are scaling factors for width and height. If 'smooth' is 1
then the destination 32bit surface is anti-aliased. If the surface is not 8bit
or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
*/
SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth);
/* Returns the size of the target surface for a zoomSurface() call */
void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
};
#endif
#endif /* _SDL_rotozoom_h */

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2002,2003,2004,2005 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef ECL_HH
#define ECL_HH
#include "ecl_array2.hh"
#include "ecl_buffer.hh"
#include "ecl_cache.hh"
#include "ecl_callback.hh"
#include "ecl_font.hh"
#include "ecl_math.hh"
#include "ecl_system.hh"
#include "ecl_video.hh"
#include "ecl_util.hh"
#endif

View File

@@ -0,0 +1,70 @@
/*
* Copyright (C) 2002 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef ECL_ALIST_HH
#define ECL_ALIST_HH
/*
* This file defines STL-like associative lists (similar to the ones
* found in Lisp dialects, but with a C++-ish look and feel. They can
* be used as a std::map replacement when linear searches aren't
* expensive.
*/
#include <string>
#include <list>
#include <utility>
namespace ecl
{
template <class KEY, class VAL>
class AssocList : public std::list<std::pair<KEY, VAL> > {
public:
typedef KEY key_type;
typedef std::pair<KEY,VAL> value_type;
typedef typename std::list<value_type>::iterator iterator;
typedef typename std::list<value_type>::const_iterator const_iterator;
//
// Lookup of keys
//
iterator find (const key_type &key) {
iterator i=this->begin(), e=this->end();
for (; i!=e; ++i)
if (i->first == key)
break;
return i;
}
const_iterator find (const key_type &key) const {
const_iterator i=this->begin(), e=this->end();
for (; i!=e; ++i)
if (i->first == key)
break;
return i;
}
VAL &operator[] (const key_type &key) {
iterator i=find(key);
if (i==this->end())
i=insert(this->end(), make_pair(key, VAL()));
return i->second;
}
};
}
#endif

View File

@@ -0,0 +1,167 @@
/*
* Copyright (C) 2000,2003 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "ecl_argp.hh"
#include <iostream>
using namespace std;
using ecl::ArgParser;
ArgParser::ArgParser() {
}
ArgParser::~ArgParser(){
}
void ArgParser::on_error (ErrorType t, const std::string &arg) {
cerr << "Error: " << errormsg(t, arg) << endl;
}
void ArgParser::on_argument (const std::string &/*arg*/) {
}
void ArgParser::on_option (int /*id*/, const std::string &/*param*/)
{
}
void ArgParser::def (int id, const std::string &name,
char abbr, bool takesparam)
{
m_opts.push_back (Option(id, abbr, string("--") + name, takesparam));
}
void ArgParser::def (bool *boolvar, const std::string &name,
char abbr)
{
Option opt(-1, abbr, string("--") + name, false);
opt.boolvar = boolvar;
m_opts.push_back(opt);
}
string ArgParser::errormsg(ErrorType t, const std::string &arg) const {
string errmsg;
switch (t) {
case InvalidParam: errmsg = "Invalid parameter for option `"; break;
case AmbiguousOpt: errmsg = "Ambiguous command line option `"; break;
case UnknownOpt: errmsg = "Unknown command line option `"; break;
case MissingParam: errmsg = "Missing parameter for option `"; break;
default:
return string();
}
errmsg += arg;
errmsg += "'.";
return errmsg;
}
void ArgParser::process_option(Option &opt, const std::string &param) {
if (opt.boolvar)
*opt.boolvar = true;
else
on_option(opt.id, param);
}
void ArgParser::getlongopt (const std::string &arg) {
string::const_iterator eqpos = find(arg.begin(), arg.end(), '=');
string optname(arg.begin(), eqpos);
option_iterator i, j;
j = i = find_prefix (m_opts.begin(), m_opts.end(), optname);
if (i == m_opts.end()) {
on_error (UnknownOpt, optname);
}
else if (find_prefix(++j, m_opts.end(), optname) != m_opts.end()) {
on_error (AmbiguousOpt, optname);
}
else if (i->takesparam) {
if (eqpos != arg.end()) {
process_option (*i, string(eqpos+1, arg.end()));
}
else if (!m_arglist.empty()) {
process_option (*i, m_arglist.front());
m_arglist.pop_front();
}
else
on_error (MissingParam, optname);
}
else if (eqpos != arg.end()) {
on_error (InvalidParam, optname);
}
else
process_option(*i, "");
}
void ArgParser::getshortopt (const std::string &arg) {
option_iterator i = m_opts.begin();
for (; i != m_opts.end(); ++i)
if (i->shortopt == arg[1])
break;
string option = arg.substr(0, 2);
if (i == m_opts.end()) {
on_error (UnknownOpt, option);
}
else if (i->takesparam) {
string param = arg.substr(2);
if (param.empty()) {
if (!m_arglist.empty()) {
param = m_arglist.front();
m_arglist.pop_front();
process_option (*i, param);
}
else
on_error (MissingParam, option);
} else
process_option (*i, param);
}
else {
process_option (*i, "");
// The following characters can be options in their own right
// (single-character options can be grouped, as in -hvx), so
// put them back into the argument list.
std::string newarg("-");
newarg.append(arg.begin()+2, arg.end());
if (newarg != "-")
m_arglist.push_front(newarg);
}
}
void ArgParser::parse () {
bool no_more_opts = false;
while (!m_arglist.empty()) {
std::string arg = m_arglist.front();
m_arglist.pop_front();
if (!no_more_opts && arg.size() >= 2 && arg[0] == '-') {
// Note: "-" is treated as an ordinary argument
if (arg[1] == '-') {
if (arg.size() == 2) // "--" terminates the option list
no_more_opts = true;
else
getlongopt (arg);
}
else
getshortopt (arg);
}
else
on_argument (arg);
}
}

View File

@@ -0,0 +1,120 @@
/*
* Copyright (C) 2000,2003 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef ECL_ARGP_HH
#define ECL_ARGP_HH
#include "ecl_util.hh"
#include <list>
#include <algorithm>
namespace ecl
{
class ArgParser : public ecl::Nocopy {
public:
// Constructors.
ArgParser ();
template <class Iter>
ArgParser(Iter beg, Iter end) {
feed (beg, end);
}
// Destructor.
virtual ~ArgParser();
// Types.
enum ErrorType {
UnknownOpt, // Unkown option found
AmbiguousOpt, // Abbreviation matches two options
MissingParam, // Expected parameter is missing
InvalidParam // Option does not take parameter
};
//
// Public interface.
//
virtual void on_error (ErrorType t, const std::string &arg);
virtual void on_argument (const std::string &arg);
virtual void on_option (int id, const std::string &param);
//
// Functions.
//
/* Feed new arguments into the parser. */
template <class ForwardIterator>
void feed (ForwardIterator begin, ForwardIterator end) {
std::copy(begin, end, std::back_inserter(m_arglist));
}
/* Define a new option. */
void def (int id, const std::string &name, char abbr = 0, bool param = false);
void def (bool *boolvar, const std::string &name, char abbr = 0);
/* Parse all command line arguments, calling the appropriate
handlers at the right time. */
void parse();
std::string errormsg(ErrorType t, const std::string &arg) const;
private:
struct Option {
Option (int id_, char s='\0', const std::string& l="", bool param=false)
: id(id_), shortopt(s), longopt(l), takesparam(param), boolvar(0)
{}
int id;
char shortopt;
std::string longopt;
bool takesparam;
bool *boolvar;
};
// Private Variables.
typedef std::list<Option>::iterator option_iterator;
std::list<Option> m_opts;
std::list<std::string> m_arglist;
std::string m_lastopt; // Last option seen
// Private functions.
void process_option(Option &opt, const std::string &param);
void getlongopt (const std::string& arg);
void getshortopt (const std::string& arg);
template <class Iter>
static Iter
find_prefix(Iter beg, Iter end, const std::string& val) {
typename std::string::size_type s = val.size();
for (; beg != end; ++beg) {
// This is the way the comparison should be done,
// but gcc doesn't like it yet...
// if ((beg->longopt).compare(0, s, val) == 0)
if ((beg->longopt).substr(0, s) == val)
break;
}
return beg;
}
};
}
#endif

View File

@@ -0,0 +1,172 @@
/*
* Copyright (C) 2002,2003 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef ECL_ARRAY2_HH
#define ECL_ARRAY2_HH
/*
** This file implements templated two-dimensional arrays.
*/
#include <memory>
namespace ecl
{
template <class T, class A = std::allocator<T> >
struct Array2Base {
A alloc; // allocator
T *first, *last; // start/end of allocated space
Array2Base(const A &a, typename A::size_type n)
: alloc(a), first(alloc.allocate(n)), last(first+n)
{}
~Array2Base() {
// allocate(0) returns 0 on GCC 2.95 -- standard?
if (first)
alloc.deallocate(first, last-first);
}
void resize (typename A::size_type n)
{
if (first)
alloc.deallocate(first, last-first);
first = alloc.allocate(n);
last = first+n;
}
};
template <class T, class A=std::allocator<T> >
class Array2 : private Array2Base<T,A> {
A alloc;
public:
typedef T value_type;
typedef T* iterator;
typedef const T * const_iterator;
typedef T & reference;
typedef const T & const_reference;
typedef typename A::size_type size_type;
// Construction / Copying
explicit Array2(int ww=0, int hh=0, const T& val=T(), const A& a=A());
Array2(const Array2<T,A> &a);
Array2<T,A> &operator=(Array2<T,A> a2); // call by value!
// Destructor
~Array2() { destroy_elements(); }
iterator begin() { return this->first; }
iterator end() { return this->last; }
const_iterator begin() const { return this->first; }
const_iterator end() const { return this->last; }
iterator row_begin(size_type y) { return this->first + y*w; }
iterator row_end(size_type y) { return this->first + y*w + w; }
const_iterator row_begin(size_type y) const { return this->first + y*w; }
const_iterator row_end(size_type y) const { return this->first + y*w + w; }
void swap(Array2<T,A> &a2);
size_type width() const { return w; }
size_type height()const { return h; }
T& get(size_type x, size_type y) { return this->first[y*w+x]; }
const T& get(size_type x, size_type y) const { return this->first[y*w+x]; }
T& operator()(size_type x, size_type y) { return get(x,y); }
const T& operator()(size_type x, size_type y) const { return get(x,y); }
void set(size_type x, size_type y, const T& val) {
this->first[y*w+x] = val;
}
/*! Fill the array with some value or the default value. */
void fill (const T& val=T());
/*! Resize the array in place, but discard any old array
entries */
void resize (int w, int h, const T& val=T());
private:
void destroy_elements();
size_type w, h;
};
template <class T, class A>
Array2<T,A>::Array2(int ww, int hh, const T& val, const A& a)
: Array2Base<T,A>(a, ww*hh), w(ww), h(hh)
{
std::uninitialized_fill(this->first, this->last, val);
}
template <class T, class A>
Array2<T,A>::Array2(const Array2<T,A> &a)
: Array2Base<T,A>(a.alloc, a.last-a.first)
{
std::uninitialized_copy(a.begin(), a.end(), this->first);
}
template <class T, class A>
void Array2<T,A>::destroy_elements() {
for (T* p=this->first; p!=this->last; ++p)
p->~T();
}
template <class T, class A>
void Array2<T,A>::fill (const T& val)
{
destroy_elements();
std::uninitialized_fill(this->first, this->last, val);
}
/*! Resize the array in place, but discard any old array
entries */
template <class T, class A>
void Array2<T,A>::resize (int w_, int h_, const T& val)
{
destroy_elements();
Array2Base<T,A>::resize(w_*h_);
std::uninitialized_fill(this->first, this->last, val);
w = w_;
h = h_;
}
template <class T, class A>
void Array2<T,A>::swap(Array2<T,A> &a2)
{
std::swap(this->first, a2.first);
std::swap(this->last, a2.last);
std::swap(w, a2.w);
std::swap(h, a2.h);
}
template <class T, class A>
void swap (Array2<T,A> &a, Array2<T,A> &b)
{
a.swap(b);
}
template <class T, class A> Array2<T,A>&
Array2<T,A>::operator= (Array2<T,A> a2)
{
ecl::swap(*this, a2);
return *this;
}
}
#endif

View File

@@ -0,0 +1,392 @@
/*
* Copyright (C) 2002,2005 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "ecl_buffer.hh"
#include <iostream>
using namespace ecl;
using namespace std;
Buffer::Buffer(size_t startlen)
: buf(new char[startlen])
, rpos(buf), wpos(buf)
, sz(0)
, capacity(startlen)
, iostate(GOODBIT)
{}
void Buffer::assign (char *data, size_t size)
{
clear();
write (data, size);
}
char* Buffer::get_wspace(size_t len)
{
size_t newcap = capacity;
while (wpos + len > buf + newcap)
newcap *= 2;
if (newcap != capacity)
{
char* newbuf = new char[newcap];
memcpy(newbuf, buf, sz);
capacity = newcap;
wpos = (wpos - buf) + newbuf;
rpos = (rpos - buf) + newbuf;
delete[] buf;
buf = newbuf;
}
char* ret = wpos;
wpos += len;
sz += len;
return ret;
}
char* Buffer::get_rspace(size_t len)
{
if (!good() || rpos + len > buf + sz)
{
iostate = State(iostate | FAILBIT | EOFBIT);
return 0;
}
char* ret = rpos;
rpos += len;
return ret;
}
int Buffer::read()
{
if (good() && rpos < buf+sz)
return *rpos++;
else
return -1;
}
Buffer& Buffer::write(char c)
{
char* ptr = get_wspace(1);
*ptr = c;
return *this;
}
Buffer& Buffer::read(void* dest, size_t len)
{
if (!good() || (rpos + len > buf + sz))
{
iostate = State(iostate | EOFBIT | FAILBIT);
}
else
{
memcpy(dest, rpos, len);
rpos += len;
}
return *this;
}
Buffer& Buffer::write(const void* src, size_t len)
{
if (char* dest = get_wspace(len)) {
memcpy(dest, src, len);
}
return *this;
}
int Buffer::seekr(long pos, SeekMode whence)
{
size_t offs = 0;
switch (whence) {
case SET: offs = pos; break;
case CUR: offs = (rpos - buf) + pos; break;
case END: offs = sz + pos; break;
}
if ( /* offs < 0 || */ /* always false */
offs > sz)
return -1;
rpos = buf + offs;
return 0;
}
int Buffer::seekw(long pos, SeekMode whence)
{
size_t offs = 0;
switch (whence) {
case SET: offs = pos; break;
case CUR: offs = (wpos - buf) + pos; break;
case END: offs = sz + pos; break;
}
if (/* offs < 0 || */ /* always false */
offs > sz)
return -1;
wpos = buf + offs;
return 0;
}
Buffer::operator void*() const
{
return (iostate & FAILBIT) ? 0 : reinterpret_cast<void*>(1);
}
bool Buffer::operator!() const
{
return (iostate & FAILBIT) ? true : false;
}
//----------------------------------------
// Buffer helper routines.
//----------------------------------------
/*
** === Read and write bytes ===
*/
Buffer& ecl::read(Buffer& buf, Uint8& byte)
{
int a = buf.read();
if (a != -1)
byte = a;
return buf;
}
Buffer& ecl::write(Buffer& buf, Uint8 byte)
{
buf.write(byte);
return buf;
}
/*
** === Read and write words ===
*/
Buffer& ecl::read(Buffer& buf, Uint16& word)
{
Uint8* ptr = (Uint8*) buf.get_rspace(2);
if (ptr != 0)
word = ptr[0] + (ptr[1] << 8);
return buf;
}
Buffer& ecl::write(Buffer& buf, Uint16 word)
{
Uint8* ptr = (Uint8*) buf.get_wspace(2);
ptr[0] = word & 0xff;
ptr[1] = (word >> 8) & 0xff;
return buf;
}
/*
** === Read and write dwords ===
*/
Buffer& ecl::read(Buffer& buf, Uint32& dword)
{
Uint8* ptr = (Uint8*) buf.get_rspace(4);
if (ptr != 0)
{
dword = ptr[0];
dword |= (ptr[1] << 8);
dword |= (ptr[2] << 16);
dword |= (ptr[3] << 24);
}
return buf;
}
Buffer& ecl::write(Buffer& buf, Uint32 dword)
{
Uint8* ptr = (Uint8*) buf.get_wspace(4);
ptr[0] = dword & 0xff;
ptr[1] = (dword >> 8) & 0xff;
ptr[2] = (dword >> 16) & 0xff;
ptr[3] = (dword >> 24) & 0xff;
return buf;
}
/*
** === Read and write long longs ===
*/
Buffer& ecl::read(Buffer& buf, Uint64& lvar)
{
Uint8* ptr = (Uint8*) buf.get_rspace(8);
if (ptr != 0)
{
lvar = ptr[0];
lvar |= (Uint64(ptr[1]) << 8);
lvar |= (Uint64(ptr[2]) << 16);
lvar |= (Uint64(ptr[3]) << 24);
lvar |= (Uint64(ptr[4]) << 32);
lvar |= (Uint64(ptr[5]) << 40);
lvar |= (Uint64(ptr[6]) << 48);
lvar |= (Uint64(ptr[7]) << 56);
}
return buf;
}
Buffer& ecl::write(Buffer& buf, Uint64 lvar)
{
Uint8* ptr = (Uint8*) buf.get_wspace(8);
ptr[0] = Uint8(lvar & 0xff);
ptr[1] = Uint8((lvar >> 8) & 0xff);
ptr[2] = Uint8((lvar >> 16) & 0xff);
ptr[3] = Uint8((lvar >> 24) & 0xff);
ptr[4] = Uint8((lvar >> 32) & 0xff);
ptr[5] = Uint8((lvar >> 40) & 0xff);
ptr[6] = Uint8((lvar >> 48) & 0xff);
ptr[7] = Uint8((lvar >> 56) & 0xff);
return buf;
}
/*
** === Read and write floats ===
*/
/* NOTE: we reinterpret floats and doubles as Uint32/Uint64,
** and byte-swap them like integers.
** This is how quake does it, too (except they only use floats).
** I couldn't believe that this worked, so I checked it out
** (PPC <-> x86), and it does. The upside (over multiplying
** with 2048 and converting to int, as it was before) is that
** we have the same rep on both machines, possibly leading to
** less desynchronisation in network games.
*/
Buffer& ecl::read(Buffer& buf, float& dvar)
{
union
{
float f;
Uint32 a;
} t;
if (buf >> t.a)
dvar = t.f;
return buf;
}
Buffer& ecl::write(Buffer& buf, float dvar)
{
union
{
float f;
Uint32 a;
} t;
t.f = dvar;
write(buf, t.a);
return buf;
}
/*
** === Read and write doubles ===
*/
Buffer& ecl::read(Buffer& buf, double& dvar)
{
union
{
double d;
Uint64 a;
} t;
if (buf >> t.a)
dvar = t.d;
return buf;
}
Buffer& ecl::write(Buffer& buf, double dvar)
{
union
{
double d;
Uint64 a;
} t;
t.d=dvar;
write(buf, t.a);
return buf;
}
/*
** === Read and write another buffer ===
*/
Buffer& ecl::read(Buffer& srcbuf, Buffer& destbuf, int len)
{
if (&srcbuf != &destbuf)
{
char* dest = destbuf.get_wspace(len);
char* src = srcbuf.get_rspace(len);
if (src != 0)
memcpy(dest, src, len);
}
return srcbuf;
}
Buffer& ecl::write(Buffer& buf, const Buffer& databuf)
{
if (&buf != &databuf)
{
buf.write(databuf.data(), databuf.size());
}
return buf;
}
/*
** === Read and write strings ===
*/
Buffer& ecl::read(Buffer& buf, string& str)
{
Uint16 size;
if (buf >> size)
{
char* ptr = buf.get_rspace(size);
if (ptr != 0)
str.assign(ptr, ptr+size);
}
return buf;
}
Buffer& ecl::write(Buffer& buf, const string& str)
{
Uint16 size = str.size();
buf << size;
buf.write(str.c_str(), size);
return buf;
}
/*
** Read and write from and to streams
*/
ostream& ecl::operator<<(ostream& os, const Buffer& buf)
{
os.write(buf.data(), buf.size());
return os;
}
// istream& ecl::operator>>(istream& is, Buffer& buf)
// {
// buf.clear();
// char tmp[2048];
// while (is.read(tmp, sizeof tmp))
// {
// buf.write(tmp, sizeof tmp);
// }
// buf.write(tmp, is.gcount());
// return is;
// }

View File

@@ -0,0 +1,109 @@
//======================================================================
// Copyright (C) 2002 Daniel Heck
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//======================================================================
#ifndef ECL_BUFFER_HH
#define ECL_BUFFER_HH
#include "SDL_types.h"
#include <iosfwd>
#include <cstddef>
#include <string>
namespace ecl
{
class Buffer {
public:
typedef std::size_t size_t;
explicit Buffer(size_t startlen=128);
~Buffer() { delete[] buf; }
void clear() { sz=0; rpos=wpos=buf; }
void assign (char *data, size_t size);
int read(); // return the next byte or -1 on EOF
Buffer& write(char c); // write one byte at the current position
Buffer& read(void* dest, size_t maxlen);
Buffer& write(const void* src, size_t len);
// Change the read/write position. Returns <0 on error.
enum SeekMode {SET, CUR, END};
int seekr(long pos, SeekMode whence);
int seekw(long pos, SeekMode whence);
ptrdiff_t get_rpos() const { return rpos-buf; }
ptrdiff_t get_wpos() const { return wpos-buf; }
size_t size() const { return sz; }
const char* data() const { return buf; };
char* get_wspace(size_t len); // get space to write into
char* get_rspace(size_t len); // get space to read from
enum State { GOODBIT=0, FAILBIT=1, EOFBIT=2 };
operator void*() const; // == 0 iff fail()
bool operator!() const; // true iff fail()
bool good() const { return iostate==0; }
bool fail() const { return iostate & FAILBIT; }
bool eof() const { return (iostate & EOFBIT) != 0; }
void clear_state(State st=GOODBIT) { iostate = st; }
State state() const { return iostate; }
private:
char *buf, *rpos, *wpos;
size_t sz, capacity;
State iostate;
Buffer(const Buffer&);
const Buffer& operator=(const Buffer&);
};
Buffer& read(Buffer& buf, Uint8& byte);
Buffer& write(Buffer& buf, Uint8 byte);
Buffer& read(Buffer& buf, Uint16& word);
Buffer& write(Buffer& buf, Uint16 word);
Buffer& read(Buffer& buf, Uint32& dword);
Buffer& write(Buffer& buf, Uint32 dword);
Buffer& read(Buffer& buf, Uint64& lvar);
Buffer& write(Buffer& buf, Uint64 lvar);
Buffer& read(Buffer& buf, float& dvar);
Buffer& write(Buffer& buf, float dvar);
Buffer& read(Buffer& buf, double& dvar);
Buffer& write(Buffer& buf, double dvar);
Buffer& read(Buffer& buf, std::string& str);
Buffer& write(Buffer& buf, const std::string& str);
Buffer& write(Buffer& buf, const Buffer& dest);
Buffer& read(Buffer& buf, Buffer& dest, int len);
template <typename T>
inline Buffer& operator>>(Buffer& buf, T& val)
{
read(buf, val);
return buf;
}
template <typename T>
inline Buffer& operator<<(Buffer& buf, const T& val)
{
write(buf, val);
return buf;
}
std::ostream& operator <<(std::ostream& os, const Buffer& buf);
// std::istream& operator >>(std::istream& is, Buffer& buf);
}
#endif

View File

@@ -0,0 +1,128 @@
/*
* Copyright (C) 2002,2003 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef ECL_CACHE_HH
#define ECL_CACHE_HH
/* -------------------- Cache -------------------- */
/*
A generic class for caching external data. Stored data is owned by
the cache and is automatically `release'd on destruction. Missing
values are automatically retrieved using the `acquire' method.
*/
#include "ecl_dict.hh"
namespace ecl
{
template <class T>
class DeleteDisposer {
public:
static void dispose (T p)
{ delete p; }
};
template <class T, class Disposer>
class Cache {
public:
Cache();
virtual ~Cache() {}
// ---------- Methods ----------
void clear();
T get (const std::string &key);
void remove (const std::string &key);
unsigned size() const;
bool has_key(const std::string &key) const;
protected:
T store (const std::string &key, T value);
private:
Cache (const Cache &other);
Cache &operator= (const Cache &other);
void release (T value) {
Disposer::dispose (value);
}
// ---------- Interface ----------
virtual T acquire (const std::string &name) = 0;
// ---------- Variables ----------
typedef ecl::Dict<T> Map;
typedef typename Map::iterator iterator;
Map cache;
};
template <class T, class D>
Cache<T,D>::Cache() : cache(1223) {
}
template <class T, class D>
void Cache<T, D>::clear() {
for (iterator i=cache.begin(); i!=cache.end(); ++i)
release(i->second);
cache.clear();
}
template <class T, class D>
void Cache<T, D>::remove (const std::string &key)
{
cache.remove (key);
}
template <class T, class D>
T Cache<T,D>::store (const std::string &key, T value) {
cache.insert(key, value);
return value;
}
template <class T, class D>
T Cache<T,D>::get(const std::string &key) {
iterator i=cache.find(key);
if (i!=cache.end())
return i->second;
else
return store (key, acquire(key));
}
template <class T, class D>
unsigned Cache<T,D>::size() const {
return cache.size();
}
template <class T, class D>
bool Cache<T, D>::has_key(const std::string &key) const {
return cache.has_key(key);
}
/* -------------------- PtrCache -------------------- */
template <class T>
class PtrCache : public Cache<T*, DeleteDisposer<T*> > {
public:
~PtrCache() { this->clear(); }
// void release (T *value) { delete value; }
};
}
#endif

View File

@@ -0,0 +1,65 @@
//======================================================================
// Copyright (C) 2002 Daniel Heck
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//======================================================================
#ifndef ECL_CALLBACK_HH
#define ECL_CALLBACK_HH
namespace ecl
{
class Callback {
public:
virtual ~Callback() {}
virtual void operator() () = 0;
};
template <class T>
class MethodCallback : public Callback {
public:
typedef void (T::* Func)();
MethodCallback(T* o, Func f) : obj(o), func(f) {}
void operator() () { (obj->*func)(); }
private:
T *obj;
Func func;
};
class FunctionCallback : public Callback {
public:
typedef void (*Func)();
FunctionCallback(Func f) : func(f) {}
void operator() () { func(); }
private:
Func func;
};
}
namespace ecl
{
inline FunctionCallback *
make_cb(void (*func)())
{
return new FunctionCallback(func);
}
template <class T> Callback *
make_cb(T *o, void (T::* f)())
{
return new MethodCallback<T>(o, f);
}
}
#endif

View File

@@ -0,0 +1,17 @@
#include "ecl_dict.hh"
unsigned
ecl::hash(const std::string &key)
{
unsigned h=0, g;
for (const char *p=key.c_str(); *p; ++p)
{
h = (h<<4) + *p;
g = h & 0xf0000000;
if (g != 0) {
h = h ^ (g>>24);
h = h ^ g;
}
}
return h;
}

View File

@@ -0,0 +1,274 @@
/*
* Copyright (C) 2002,2003 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef ECL_DICT_HH
#define ECL_DICT_HH
#include "ecl_error.hh"
#include <utility>
namespace ecl
{
extern unsigned hash(const std::string &key);
class XInvalidKey : XGeneric {
XInvalidKey () : XGeneric("invalid dictionary key")
{}
};
template <class T>
class Dict {
public:
typedef std::string key_type;
typedef std::pair<key_type, T> value_type;
typedef size_t size_type;
private:
struct Entry {
Entry(const key_type &k, const T &v) : pair(k,v) {}
value_type pair;
Entry *next;
};
// ---------- Iterator ----------
template <class U>
class Iter {
public:
typedef U value_type;
typedef ptrdiff_t difference_type;
typedef std::forward_iterator_tag iterator_category;
typedef value_type &reference;
typedef value_type *pointer;
Iter() : dict(0), idx(0), cur(0) {}
Iter(const Dict<T> *d, size_type i, Entry *c)
: dict(d),idx(i),cur(c)
{}
Iter(const Dict<T> *d) :dict(d)
{
for (idx=0; idx<dict->nbuckets; ++idx)
if ((cur=dict->hashtab[idx]) != 0)
return;
dict = 0; // End
idx=0;
}
bool operator==(const Iter &i) {
return dict==i.dict && idx==i.idx && cur==i.cur;
}
bool operator!=(const Iter &i) {
return !this->operator==(i);
}
reference operator*() {return cur->pair;}
pointer operator->() {return &cur->pair;}
Iter &operator++() {
if ((cur=cur->next) == 0) {
for (++idx; idx<dict->nbuckets; ++idx)
if ((cur=dict->hashtab[idx]) != 0)
return *this;
dict = 0;
cur=0;
idx=0;
}
return *this;
}
Iter &operator++(int)
{
Iter tmp=*this;
++*this;
return tmp;
}
private:
friend class Dict<T>;
const Dict<T> *dict;
size_type idx;
Entry *cur;
};
public:
typedef Iter<value_type> iterator;
typedef Iter<const value_type> const_iterator;
friend class Iter<value_type>;
friend class Iter<const value_type>;
Dict(size_type table_size = 257);
~Dict();
size_type size() const { return nentries; }
iterator begin() { return iterator(this); }
iterator end() { return iterator(); }
const_iterator begin() const { return const_iterator(this); }
const_iterator end() const { return const_iterator(); }
iterator find (const key_type &key);
const_iterator find (const key_type &key) const;
T &lookup(const key_type &key) {
Entry *e = find_entry(key);
// if (!e) throw XInvalidKey();
return e->pair.second;
}
T &operator[] (const key_type &key) { return lookup(key); }
const T& lookup(const key_type &key) const {
Entry *e = find_entry(key);
if (!e) throw XInvalidKey();
return e->pair.second;
}
const T& operator[] (const key_type &key) const
{ return lookup(key); }
bool has_key(const key_type &key) const;
/*! Insert a new element into the table. */
void insert(const key_type &key, const T &val);
/*! Remove all entries from the hash table. */
void clear();
/*! Remove the entry with key \var key from the table. */
void remove(const key_type &key);
/*! Remove the element pointed to by an iterator. */
void remove (iterator i);
private:
Entry *find_entry(const key_type &key) const;
// ---------- Variables ----------
size_type nentries; // Number of entries
size_type nbuckets; // Number of buckets in `hashtab'
Entry **hashtab;
private:
// Copying not implemented yet
Dict (const Dict<T> &d)
: nentries(d.nentries),
nbuckets(d.nbuckets),
hashtab(new Entry*[nbuckets])
{
for (size_type i=0; i<nbuckets; ++i) {
Entry *e = d.hashtab[i];
hashtab[i] = 0; // XXX Fix
}
}
Dict &operator=(const Dict<T> &d);
};
/* -------------------- Dict implementation -------------------- */
template <class T>
Dict<T>::Dict(size_type table_size)
: nentries(0), nbuckets (table_size), hashtab (new Entry*[nbuckets])
{
for (size_type i=0; i<nbuckets; ++i)
hashtab[i] = 0;
}
template <class T>
Dict<T>::~Dict() {
clear();
delete [] hashtab;
}
template <class T>
typename Dict<T>::iterator
Dict<T>::find (const key_type &key)
{
unsigned h = hash(key) % nbuckets;
for (Entry *e = hashtab[h]; e != 0; e=e->next)
if (e->pair.first == key)
return iterator(this, h, e);
return end();
}
template <class T>
typename Dict<T>::const_iterator
Dict<T>::find (const key_type &key) const
{
unsigned h = hash(key) % nbuckets;
for (Entry *e = hashtab[h]; e != 0; e=e->next)
if (e->pair.first == key)
return const_iterator(this, h, e);
return end();
}
template <class T>
void Dict<T>::clear()
{
for (size_type i=0; i<nbuckets; ++i) {
Entry *cur, *next;
for (cur = hashtab[i]; cur != 0; cur=next) {
next = cur->next;
delete cur;
}
hashtab[i] = 0;
}
nentries = 0;
}
template <class T>
void Dict<T>::insert (const key_type &key, const T &val)
{
unsigned h = hash(key) % nbuckets;
Entry *e = new Entry(key, val);
e->next = hashtab[h];
hashtab[h] = e;
nentries += 1;
}
template <class T>
void Dict<T>::remove (const key_type &key)
{
unsigned h = hash(key) % nbuckets;
Entry *e = hashtab[h];
Entry **eptr = &hashtab[h];
while (e != 0) {
if (e->pair.first == key) {
*eptr = e->next; // Modify pointer referring to e
delete e;
nentries -= 1;
break;
}
eptr = &e->next;
e = e->next;
}
}
template <class T>
bool Dict<T>::has_key (const key_type &key) const
{
return find_entry(key) != 0;
}
template <class T>
typename Dict<T>::Entry *
Dict<T>::find_entry (const key_type &key) const
{
unsigned h = hash(key) % nbuckets;
for (Entry *e = hashtab[h]; e != 0; e=e->next)
if (e->pair.first == key)
return e;
return 0;
}
}
#endif

View File

@@ -0,0 +1,80 @@
/*
* Copyright (C) 2002,2004,2005,2006 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef ECL_ERROR_HH
#define ECL_ERROR_HH
#include "ecl_util.hh"
#include <string>
#include <exception>
#ifdef ENABLE_ASSERT
#define ASSERT(p, t, m) ((p) ? (void) 0 : ecl::Assert<t>(false, ecl::strf("Assert(%s) at %s:%d: %s() failed - %s",#p,__FILE__,__LINE__,__func__,m)))
#else
#define ASSERT(p, t, m) ((void)0)
#endif
namespace ecl
{
using std::string;
class XGeneric : public std::exception {
public:
// Constructor.
XGeneric (const std::string& str = "")
: m_string (str)
{}
virtual ~XGeneric() throw()
{}
// Accessors
const string& get_string() const { return m_string; }
const char *what() const throw() { return m_string.c_str(); }
private:
std::string m_string;
};
#define ECL_DEF_EXCEPTION(name, parent, message) \
class name : public parent { \
public: \
name(const std::string &str = message) : parent(str) {} \
}
ECL_DEF_EXCEPTION( XInputOutput, XGeneric, "InputOutput" );
ECL_DEF_EXCEPTION( XFileNotFound, XInputOutput, "File not found" );
ECL_DEF_EXCEPTION( XEndOfFile, XInputOutput, "End of file" );
ECL_DEF_EXCEPTION( XFileFormat, XInputOutput, "File format" );
ECL_DEF_EXCEPTION( XVideo, XGeneric, "Video");
template <class EXC>
void Assert (bool expr, const std::string &msg)
{
if (!expr)
throw EXC(msg);
}
template <class EXC>
void Assert (bool expr)
{
if (!expr)
throw EXC();
}
}
#endif

View File

@@ -0,0 +1,303 @@
/*
* Copyright (C) 2002,2003,2004 Daniel Heck
* Copyright (C) 2006,2007 Ronald Lamprecht
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "ecl_font.hh"
#include "ecl_geom.hh"
#include "ecl_utf.hh"
#include "ecl_video.hh"
#include <vector>
#include <string>
#include <memory> // for auto_ptr
#include <stdio.h>
#include <cstdlib>
#include <ostream>
#include <iostream>
#include <config.h>
using namespace ecl;
using namespace std;
void Font::render(const GC &gc, int x, int y, std::string text,
Font * altFont, int maxwidth) {
render(gc, x, y, text.c_str());
}
std::string::size_type
ecl::breakString (Font *font,
const std::string &str,
const std::string &breakChars,
int targetWidth)
{
if (font->get_width (str.c_str()) <= targetWidth)
return str.size(); // the complete string fits into a line
bool breakFound = false;
std::string::size_type pos = 0;
while (true) {
std::string::size_type nextpos = str.find_first_of (breakChars, pos);
if (nextpos == std::string::npos)
// no more line breaks
return breakFound ? pos : str.size();
if (font->get_width (str.substr(0, nextpos+1).c_str()) > targetWidth)
// now the string is too long
return breakFound ? pos : nextpos + 1;
pos = nextpos+1;
breakFound = true;
}
}
//
// Bitmap fonts
//
namespace
{
class InvalidFont {};
class BitmapFont : public Font {
vector<Rect> char_rects;
vector<int> advance;
Surface *surface;
public:
BitmapFont(Surface *s, const char *descr);
~BitmapFont() { delete surface; }
int get_lineskip() { return surface->height() + 3; }
int get_width(char c);
virtual int get_width(const char *str, Font * altFont = NULL);
int get_height();
virtual Surface *render(const char *str);
virtual void render(const GC &gc, int x, int y, const char *str);
virtual void render(const GC &gc, int x, int y, std::string text,
Font * altFont = NULL, int maxwidth = -1);
};
}
BitmapFont::BitmapFont(Surface *s, const char *descr)
: char_rects(256), advance(256), surface(s)
{
// Read and interpret the font description file.
// expected line format:
// charno xpos width xadvance
FILE *fp=fopen(descr, "rt");
if (!fp) return ; //throw InvalidFont();
int c;
int x=0, w=0, adv=0;
while (fscanf(fp, "%d %d %d %d\n", &c, &x, &w, &adv) != EOF) {
char_rects[c].x = x;
char_rects[c].w = w;
char_rects[c].y = 0;
char_rects[c].h = s->height();
advance[c] = adv;
if (adv = 0)
std::cout << "BitFont 0\n";
}
}
int BitmapFont::get_width(char c) {
return advance[int(c)];
}
int BitmapFont::get_width(const char *str, Font * altFont) {
int width = 0;
for (const char *p=str; *p; ++p) {
// utf-8 char handling
int len = utf8NextCharSize(p); // num of bytes that represents one real character
if (len == 0) {
// a spurious follow up byte
continue;
}
if (len > 1 || advance[int(*p)] == 0) {
if (altFont != NULL) {
std::string utf8char(p, len);
width += altFont->get_width(utf8char.c_str());
}
p += len - 1;
} else {
width += get_width(*p);
}
}
return width;
}
int BitmapFont::get_height() {
return surface->height();
}
Surface * BitmapFont::render(const char *str) {
Surface *s = MakeSurface(get_width(str), get_height(), 16);
s->set_color_key(0,0,0);
render (GC(s), 0, 0, str);
return s;
}
void BitmapFont::render(const GC &gc, int x, int y, const char *str) {
render(gc, x, y, std::string(str));
}
void BitmapFont::render(const GC &gc, int x, int y, std::string text,
Font * altFont, int maxwidth) {
int width = 0;
for (const char *p=text.c_str(); *p; ++p) {
// utf-8 char handling
int len = utf8NextCharSize(p); // num of bytes that represents one real character
if (len == 0) {
// a spurious follow up byte
continue;
}
if (len > 1 || advance[int(*p)] == 0) {
if (altFont != NULL) {
std::string utf8char(p, len);
int charWidth = altFont->get_width(utf8char.c_str());
width += charWidth;
if (maxwidth <= 0 || width < maxwidth) {
altFont->render(gc, x, y, utf8char.c_str());
x += altFont->get_width(utf8char.c_str());
}
}
p += len - 1;
} else {
int charWidth = get_width(*p);
width += charWidth;
if (maxwidth <= 0 || width < maxwidth) {
blit(gc, x, y, surface, char_rects[int(*p)]);
x += charWidth;
}
}
}
}
Font *
ecl::LoadBitmapFont(const char * imgname, const char * descrname)
{
if (Surface *s = LoadImage(imgname))
return new BitmapFont(s, descrname);
return 0;
}
//
// TrueType fonts
//
#include "SDL_ttf.h"
namespace
{
class TrueTypeFont : public Font {
// Variables
TTF_Font *font;
SDL_Color fgcolor;
// Inhibit copying
TrueTypeFont (const TrueTypeFont &);
TrueTypeFont &operator= (const TrueTypeFont &);
public:
TrueTypeFont (TTF_Font *font_, int r, int g, int b);
~TrueTypeFont();
// Font interface
int get_lineskip();
int get_height();
int get_width (char c);
virtual int get_width(const char *str, Font * altFont = NULL);
Surface *render (const char *str);
void render (const GC &gc, int x, int y, const char *str);
};
}
TrueTypeFont::TrueTypeFont (TTF_Font *font_, int r, int g, int b)
: font (font_)
{
fgcolor.r = r;
fgcolor.g = g;
fgcolor.b = b;
}
TrueTypeFont::~TrueTypeFont()
{
TTF_CloseFont (font);
}
int TrueTypeFont::get_lineskip() {
return TTF_FontLineSkip (font);
}
int TrueTypeFont::get_height() {
return TTF_FontHeight(font);
}
int TrueTypeFont::get_width(char c) {
int minx, maxx, miny, maxy, advance;
TTF_GlyphMetrics(font, c, &minx, &maxx, &miny, &maxy, &advance);
return advance;
}
Surface *TrueTypeFont::render (const char *str)
{
SDL_Surface *s = 0;
SDL_Color bgcolor = { 0, 0, 0, 0 };
s = TTF_RenderUTF8_Shaded (font, str, fgcolor, bgcolor);
if (s) {
SDL_SetColorKey (s, SDL_SRCCOLORKEY,0);
return Surface::make_surface (s);
}
return MakeSurface(0, get_height(), 16);
}
void TrueTypeFont::render (const GC &gc, int x, int y, const char *str)
{
std::auto_ptr<Surface> s (render (str));
if (s.get())
blit (gc, x, y, s.get());
}
int TrueTypeFont::get_width(const char *str, Font * altFont)
{
int w,h;
TTF_SizeUTF8 (font, str, &w, &h);
return w;
}
Font *ecl::LoadTTF (const char *filename, int ptsize, int r, int g, int b)
{
if (!TTF_WasInit() && TTF_Init()==-1) {
fprintf(stderr, "Couldn't initialize SDL_ttf: %s\n", SDL_GetError());
exit(1);
}
TTF_Font *font = TTF_OpenFont (filename, ptsize);
return (font) ? new TrueTypeFont (font, r, g, b) : 0;
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2002,2004 Daniel Heck
* Copyright (C) 2006,2007 Ronald Lamprecht
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef ECL_FONT_HH
#define ECL_FONT_HH
#include <string>
namespace ecl
{
class GC;
class Surface;
class Font {
public:
virtual ~Font() {}
virtual int get_lineskip() =0;
virtual int get_height() = 0;
virtual int get_width(char c) = 0; // depreceated ! not utf-8 compatible!
virtual int get_width(const char *str, Font * altFont = NULL) = 0;
virtual Surface *render(const char *str) = 0;
virtual void render(const GC &gc, int x, int y, const char *str) = 0;
virtual void render(const GC &gc, int x, int y, std::string text,
Font * altFont = NULL, int maxwidth = -1);
};
std::string::size_type breakString(Font *font,
const std::string &theString,
const std::string &breakChars,
int targetWidth);
/** Load a bitmap font with image FILENAME and font metric
DESCRNAME. */
Font *LoadBitmapFont(const char * filename,
const char * descrname);
/** Load a TrueType font from FILENAME with size PTSIZE. */
Font *LoadTTF (const char *filename, int ptsize, int r=0xff, int g=0xff, int b=0xff);
}
#endif

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2002,2003,2005 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef ECLFWD_HH_INCLUDED
#define ECLFWD_HH_INCLUDED
/*
* This file contains forward declarations for various types provided
* by the Enigma core library.
*/
namespace ecl
{
class Buffer;
// math.hh
template <class T, int N> class Vector;
class V3;
class V2;
// font.hh
class Font;
// video.hh
class Drawable;
class GC;
class Screen;
class Surface;
// geom.hh
class RectList;
}
#endif

View File

@@ -0,0 +1,101 @@
/*
* Copyright (C) 2002,2005 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "ecl_geom.hh"
#include <iostream>
#include <list>
using namespace std;
using namespace ecl;
/* -------------------- Rect -------------------- */
std::ostream& ecl::operator<<(std::ostream& os, const Rect& r) {
return os << "Rect(" << r.x << " " << r.y << " " << r.w << " " << r.h << ")";
}
/* -------------------- RectList -------------------- */
RectList::RectList(const RectList& rl)
: m_rectangles(rl.m_rectangles)
{}
void RectList::swap(RectList &rl) {
std::swap(m_rectangles, rl.m_rectangles);
}
RectList& RectList::operator=(const RectList& rl) {
m_rectangles = rl.m_rectangles;
return *this;
}
void RectList::push_back(const Rect& r) {
if (r.w > 0 && r.h > 0)
m_rectangles.push_back(r);
}
void RectList::pop_back() {
return m_rectangles.pop_back();
}
void RectList::merge(const RectList& rl) {
for (const_iterator i = rl.begin(); i != rl.end(); ++i)
add(*i);
}
void RectList::intersect(const Rect& rect) {
RectList rl;
for (iterator i=begin(); i != end(); ++i) {
int a = max(i->x, rect.x);
int b = min(i->x + i->w, rect.x + rect.w);
int c = max(i->y, rect.y);
int d = min(i->y + i->h, rect.y + rect.h);
rl.push_back(Rect(a, c, b-a, d-c));
}
swap(rl);
}
void RectList::add(const Rect& r) {
RectList rl;
rl.push_back(r);
for (iterator i=begin(); i != end(); ++i)
rl.sub(*i);
copy(rl.begin(), rl.end(), back_inserter(*this));
}
/* Cut a region out of the rectangle list, i.e., remove all points
that are _not_ covered by `rect'. */
void RectList::sub(const Rect& rect) {
RectList rl;
for (iterator i=begin(); i != end(); ++i) {
int lft = max(i->x, rect.x);
int top = max(i->y, rect.y);
int rgt = min(i->x + i->w, rect.x + rect.w);
int bot = min(i->y + i->h, rect.y + rect.h);
if (rgt > lft && bot > top) {
// the coordinates of the intersection rectangle
rl.push_back(Rect(i->x, i->y, i->w, top - i->y));
rl.push_back(Rect(i->x, top, lft - i->x, bot - top));
rl.push_back(Rect(rgt, top, i->x + i->w - rgt, bot - top));
rl.push_back(Rect(i->x, bot, i->w, i->y + i->h - bot));
}
else
rl.push_back(*i);
}
swap(rl);
}

View File

@@ -0,0 +1,160 @@
/*
* Copyright (C) 2002,2003 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef ECL_GEOM_HH
#define ECL_GEOM_HH
#include "ecl_util.hh"
#include <iosfwd>
#include <vector>
namespace ecl
{
/* -------------------- Generic rectangles -------------------- */
template <class T>
class TRect {
public:
T x, y, w, h;
TRect() { x=y=w=h=0; }
TRect (T xx, T yy, T ww, T hh) { x=xx; y=yy; w=ww; h=hh; }
void move(T xx, T yy) { x = xx; y = yy; }
void resize (T ww, T hh) { w = ww; h = hh; }
void assign (T xx, T yy, T ww, T hh) {
x = xx; y = yy;
w = ww; h = hh;
}
void intersect(const TRect<T> & r)
{
T x1 = Max(x, r.x);
T y1 = Max(y, r.y);
T x2 = Min(x+w, r.x+r.w);
T y2 = Min(y+h, r.y+r.h);
assign(x1, y1, Max(x2-x1, 0), Max(y2-y1,0));
}
bool contains(T xx, T yy) const {
return (xx >= x && xx < x+w && yy >= y && yy<y+h);
}
bool overlaps(const TRect<T>& r) const {
T x1 = Max(x, r.x);
T y1 = Max(y, r.y);
T x2 = Min(x+w, r.x+r.w);
T y2 = Min(y+h, r.y+r.h);
return !(x2 <= x1 || y2 <= y1);
}
bool empty() const { return !(w > 0 && h > 0); }
bool operator==(const TRect<T> &r) {
return (x==r.x && y==r.y && w==r.w && h==r.h);
}
};
/* -------------------- Helper routines -------------------- */
/*! Center one rectangle inside another. */
template <class T>
TRect<T> center(const TRect<T> &outer, const TRect<T> &inner)
{
return TRect<T>(outer.x + (outer.w-inner.w)/2,
outer.y + (outer.h-inner.h)/2,
inner.w, inner.h);
}
/*! Construct the bounding box for two rectangles */
template <class T>
TRect<T> boundingbox(const TRect<T> & r1, const TRect<T>& r2)
{
T x1 = Min(r1.x, r2.x);
T y1 = Min(r1.y, r2.y);
T x2 = Max(r1.x+r1.w, r2.x+r2.w);
T y2 = Max(r1.y+r1.h, r2.y+r2.h);
return TRect<T> (x1,y1, x2-x1, y2-y1);
}
/*! Intersect two rectangles */
template <class T>
TRect<T> intersect(const TRect<T> & r1, const TRect<T>& r2)
{
TRect<T> retval(r1);
retval.intersect(r2);
return retval;
}
template <class T>
TRect<T> larger(const TRect<T> &r, T amount) {
return TRect<T>(r.x-amount, r.y-amount, r.w+2*amount, r.h+2*amount);
}
template <class T>
TRect<T> smaller(const TRect<T> &r, T amount) {
return larger(r, -amount);
}
/* -------------------- Integer rectangles -------------------- */
typedef TRect<int> Rect;
std::ostream& operator<<(std::ostream& os, const Rect& r);
/* -------------------- Rectangle list -------------------- */
class RectList {
public:
typedef Rect value_type;
typedef value_type &reference;
typedef const value_type &const_reference;
typedef std::vector<Rect>::iterator iterator;
typedef std::vector<Rect>::const_iterator const_iterator;
RectList() {}
RectList(const RectList&);
RectList& operator= (const RectList&);
iterator begin() { return m_rectangles.begin(); }
const_iterator begin() const { return m_rectangles.begin(); }
iterator end() { return m_rectangles.end(); }
const_iterator end() const { return m_rectangles.end(); }
void clear() { m_rectangles.clear(); }
size_t size() const { return m_rectangles.size(); }
bool empty() const { return m_rectangles.empty(); }
void push_back(const Rect& r);
void pop_back();
void intersect(const Rect& r2);
void add(const Rect& r);
void sub(const Rect& r2);
void merge(const RectList& rl);
void swap(RectList &rl);
private:
std::vector<Rect> m_rectangles;
};
}
#endif

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2002,2005 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "ecl_math.hh"
#include <iostream>
namespace ecl
{
std::ostream& operator<<(std::ostream& os, const V3 & v)
{
return os << "(" << v[0] << "," << v[1] << "," << v[2] << ")";
}
std::ostream& operator<<(std::ostream& os, const V2 & v)
{
return os << "(" << v[0] << "," << v[1] << ")";
}
}

View File

@@ -0,0 +1,286 @@
/*
* Copyright (C) 2002,2003,2004 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef ECL_MATH_HH_INCLUDED
#define ECL_MATH_HH_INCLUDED
#include <cmath>
#include <iosfwd>
namespace ecl
{
/* -------------------- Functions -------------------- */
template <class T, class V>
inline T round_nearest (V v)
{
if (v > 0)
return static_cast<T>(floor(v + 0.5));
else
return static_cast<T>(ceil(v - 0.5));
}
template <class T, class V>
inline T round_down (V v)
{
return static_cast<T>(floor(v));
}
/* -------------------- Vector class -------------------- */
template <typename T, int N>
class Vector
{
T v[N];
typedef Vector<T, N> vector_type;
protected:
class noinit {};
Vector(noinit) {}
public:
// Constructors.
Vector() {
for (int i=N-1; i>=0; --i)
v[i] = 0;
}
explicit Vector(T* w) {
for (int i=N-1; i>=0; --i)
v[i] = w[i];
}
// Copy constructor & assignment
Vector(const vector_type & x) {
for (int i=N-1; i>=0; --i)
v[i] = x.v[i];
}
vector_type& operator=(const vector_type & x) {
if (&x != this)
for (int i=N-1; i>=0; --i)
v[i] = x.v[i];
return *this;
}
// Normalization
T normalize() {
T l = std::sqrt( (*this) * (*this) );
if (l != 0)
(*this) /= l;
return l;
}
// Addition and subtraction
vector_type & operator+= (const vector_type & x) {
for (int i=N-1; i>=0; --i)
v[i] += x.v[i];
return *this;
}
vector_type & operator-= (const vector_type & x) {
for (int i=N-1; i>=0; --i)
v[i] -= x.v[i];
return *this;
}
// scalar multiplication
vector_type & operator*= (T a) {
for (int i=N-1; i>=0; --i)
v[i] *= a;
return *this;
}
// scalar division
vector_type & operator/= (T a) {
for (int i=N-1; i>=0; --i)
v[i] /= a;
return *this;
}
// scalar product
T operator*(const vector_type & x) const {
double sp = 0;
for (int i=N-1; i>=0; --i)
sp += v[i]*x.v[i];
return sp;
}
T& operator[](int idx) { return v[idx]; }
const T& operator[](int idx) const { return v[idx]; }
};
// negation
template <typename T, int N>
inline Vector<T,N>
operator- (const Vector<T,N> &a)
{
Vector<T,N> res(a);
for (int i=N-1; i>=0; --i)
res[i]= -res[i];
return res;
}
template <typename T, int N>
inline double
length(const Vector<T,N> &a)
{
return std::sqrt(a*a);
}
template <typename T, int N>
inline double
square (const Vector<T,N> &a)
{
return a*a;
}
template <typename T, int N>
inline Vector<T,N>
normalize(const Vector<T,N> &a)
{
if (T aa=length(a))
return a/aa;
else
return a;
}
template <typename T, int N>
inline Vector<T,N>
operator+ (const Vector<T,N> & a,
const Vector<T,N> & b)
{
Vector<T,N> res (a);
res += b;
return res;
}
template <typename T, int N>
inline Vector<T,N>
operator- (const Vector<T,N> & a,
const Vector<T,N> & b)
{
Vector<T,N> res (a);
res -= b;
return res;
}
// scalar multiplication in different operand orders
template <typename T, int N>
inline Vector<T,N>
operator*(const Vector<T,N> & v, double a)
{
Vector<T,N> res (v);
res *= a;
return res;
}
template <typename T, int N>
inline Vector<T,N>
operator*(double a, const Vector<T,N> & v)
{
Vector<T,N> res (v);
res *= a;
return res;
}
// scalar division in different operand orders
template <typename T, int N>
inline Vector<T,N>
operator/(const Vector<T,N> & v, double a)
{
Vector<T,N> res (v);
res /= a;
return res;
}
template <typename T, int N>
inline Vector<T,N>
operator/(double a, const Vector<T,N> & v)
{
Vector<T,N> res (v);
res /= a;
return res;
}
template <typename T, int N>
inline bool
operator==(const Vector<T,N> & v,const Vector<T,N> & w)
{
for (int i=N-1; i>=0; --i)
if (v[i] != w[i])
return false;
return true;
}
template <typename T, int N>
inline bool
operator!=(const Vector<T,N> & v,const Vector<T,N> & w)
{
return !(v == w);
}
class V3 : public Vector<double, 3> {
public:
V3() {}
V3(double x, double y, double z) :
Vector<double, 3>(noinit())
{
(*this)[0] = x;
(*this)[1] = y;
(*this)[2] = z;
}
V3(const Vector<double,3> &v_) : Vector<double,3>(v_) {}
V3 &operator=(const Vector<double,3> &v_) {
Vector<double,3>::operator=(v_);
return *this;
}
};
//typedef Vector<double, 3> V3;
inline V3
crossprod(const V3 & a, const V3 & b)
{
V3 r;
r[0] = a[1]*b[2] - a[2]*b[1];
r[1] = a[2]*b[0] - a[0]*b[2];
r[2] = a[0]*b[1] - a[1]*b[0];
return r;
}
std::ostream& operator<<(std::ostream& os, const V3 & v);
class V2 : public Vector<double, 2> {
public:
typedef double T;
V2() {}
V2(T x, T y) :
Vector<T,2>(noinit())
{
(*this)[0] = x;
(*this)[1] = y;
}
V2 (const Vector<T,2> &v_) : Vector<T,2>(v_) {}
V2 &operator=(const Vector<T,2> &v_) {
Vector<T,2>::operator=(v_);
return *this;
}
};
std::ostream& operator<<(std::ostream& os, const V2 & v);
}
#endif

View File

@@ -0,0 +1,40 @@
#include "ecl_sdl.hh"
using namespace sdl;
// Dispatch an event to the suitable virtual function. Returns
// true if event was handled.
bool
EventHandler::dispatch_event(SDL_Event &e)
{
bool handled = false;
switch (e.type) {
case SDL_KEYDOWN:
handled=on_keydown(e); break;
case SDL_KEYUP:
handled=on_keyup(e); break;
case SDL_MOUSEMOTION:
handled=on_mousemotion(e); break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
handled=on_mousebutton(e);
break;
case SDL_ACTIVEEVENT:
// TODO
break;
case SDL_QUIT:
handled=on_quit(e); break;
}
return handled || on_event(e);
}
void
sdl::FlushEvents()
{
SDL_Event e;
while (SDL_PollEvent(&e))
;
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2002,2003,2005 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
** SDL wrappers & helper classes
*/
#ifndef ECL_SDL_HH
#define ECL_SDL_HH
#include "ecl_geom.hh"
#include "SDL.h"
namespace sdl
{
class EventHandler {
public:
virtual ~EventHandler() {}
/* Dispatch an event to the suitable virtual function. Returns
true if event was handled. */
bool dispatch_event (SDL_Event &e);
/*
** The following function can be overriden to receive
** particular events. They should return true if the event
** was handled.
*/
virtual bool on_mousemotion (SDL_Event &/*e*/) { return false; }
virtual bool on_mousebutton (SDL_Event &/*e*/) { return false; }
virtual bool on_keydown (SDL_Event &/*e*/) { return false; }
virtual bool on_keyup (SDL_Event &/*e*/) { return false; }
virtual bool on_quit (SDL_Event &/*e*/) { return false; }
/* The generic event handler; this method is called for events
that none of the specialized methods above decided to handle. */
virtual bool on_event (SDL_Event &/*e*/) { return false; }
};
class TempInputGrab {
public:
TempInputGrab(SDL_GrabMode m)
: grabmode(SDL_WM_GrabInput(SDL_GRAB_QUERY))
{
SDL_WM_GrabInput(m);
}
~TempInputGrab() { SDL_WM_GrabInput(grabmode); }
private:
SDL_GrabMode grabmode;
};
inline void copy_rect (SDL_Rect &s, const ecl::Rect &from) {
s.x = from.x; s.y = from.y;
s.w = from.w; s.h = from.h;
}
void FlushEvents();
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2002,2003,2004 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef SYSTEM_HH
#define SYSTEM_HH
#include <string>
#include <ctime>
#include <set>
namespace ecl
{
extern const char *PathSeparator;
extern const char *PathSeparators;
extern const char *PathsSeparator;
std::string ExpandPath (const std::string &path);
bool FileExists (const std::string &fname);
std::time_t FileModTime (const std::string &fname);
bool FolderExists (const std::string &fname);
bool FolderCreate (const std::string &fname);
#ifdef __MINGW32__
std::string ApplicationDataPath();
void ToLowerCase(std::string &filename);
std::set<std::string> UniqueFilenameSet(std::set<std::string> inSet);
#endif
/* -------------------- Locales -------------------- */
std::string SysMessageLocaleName ();
std::string GetLanguageCode (const std::string &localename);
}
#endif

View File

@@ -0,0 +1,178 @@
/*
* Copyright (C) 2002,2003,2004 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "ecl_system.hh"
#include "ecl_util.hh"
#include <cstdlib>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <locale.h>
#include <unistd.h>
#include <cassert>
#include <config.h>
#ifdef __MINGW32__
#include <windows.h>
#endif
using namespace ecl;
using std::string;
#ifdef __MINGW32__
const char *ecl::PathSeparator = "\\"; // for path assembly
const char *ecl::PathsSeparator = ";"; // for listing paths in a string
#else
const char *ecl::PathSeparator = "/"; // for path assembly
const char *ecl::PathsSeparator = ":"; // for listing paths in a string
#endif
const char *ecl::PathSeparators = "/\\"; // for path splits
string ecl::ExpandPath (const string &pth)
{
string path = pth;
string::size_type p=path.find("~");
if (p != string::npos) {
string home;
if (char *h = getenv("HOME"))
home = h;
path.replace(p, 1, home);
}
return path;
}
bool ecl::FileExists (const std::string &fname)
{
struct stat s;
return (stat(fname.c_str(), &s)==0 && S_ISREG(s.st_mode));
}
time_t ecl::FileModTime (const std::string &fname)
{
struct stat s;
if (stat(fname.c_str(), &s) == 0) {
return s.st_mtime;
}
return 0; // beginning of time
}
bool ecl::FolderExists (const std::string &fname)
{
struct stat s;
return (stat(fname.c_str(), &s)==0 && S_ISDIR(s.st_mode));
}
bool ecl::FolderCreate (const std::string &fname)
{
string parent_folder;
string sub_folder;
bool ok = true;
assert(!FolderExists(fname));
if (split_path(fname, &parent_folder, &sub_folder)) {
if (!FolderExists(parent_folder)) {
ok = FolderCreate(parent_folder);
}
}
if (ok) {
#ifdef __MINGW32__
ok = mkdir(fname.c_str()) == 0;
#else
ok = mkdir(fname.c_str(), 0777) == 0;
#endif
}
return ok;
}
#ifdef __MINGW32__
// should be ecl_system_windows.cc ?
std::string ecl::ApplicationDataPath()
{
typedef HRESULT (WINAPI *SHGETFOLDERPATH)( HWND, int, HANDLE, DWORD, LPTSTR );
# define CSIDL_FLAG_CREATE 0x8000
# define CSIDL_APPDATA 0x1A
# define SHGFP_TYPE_CURRENT 0
HINSTANCE shfolder_dll;
SHGETFOLDERPATH SHGetFolderPath ;
static bool didRun = false;
static std::string result = ""; // remember exec results
if (!didRun) {
didRun = true;
/* load the shfolder.dll to retreive SHGetFolderPath */
if( ( shfolder_dll = LoadLibrary("shfolder.dll") ) != NULL )
{
SHGetFolderPath = (SHGETFOLDERPATH)GetProcAddress( shfolder_dll, "SHGetFolderPathA");
if ( SHGetFolderPath != NULL )
{
TCHAR szPath[MAX_PATH] = "";
/* get the "Application Data" folder for the current user */
if( S_OK == SHGetFolderPath( NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE,
NULL, SHGFP_TYPE_CURRENT, szPath) )
{
result = szPath;
}
}
FreeLibrary( shfolder_dll);
}
}
return result;
}
void ecl::ToLowerCase(std::string &filename) {
for (int i = 0; i < filename.length(); i++) {
char c = filename[i];
if (c >= 'A' && c <= 'Z')
filename.replace(i, 1, 1, c - 'A' + 'a');
}
}
std::set<std::string> ecl::UniqueFilenameSet(std::set<std::string> inSet) {
std::set<std::string>::iterator it = inSet.begin();
std::set<std::string> outSet;
std::set<std::string> lowerSet;
for (; it != inSet.end(); it++) {
std::string name = *it;
ecl::ToLowerCase(name);
if (lowerSet.find(name) == lowerSet.end()) {
outSet.insert(*it);
lowerSet.insert(name);
}
}
return outSet;
}
#endif
std::string ecl::GetLanguageCode (const std::string &ln)
{
if (ln == "C" || ln == "POSIX" || ln.size() < 2)
return "en";
return ln.substr (0, 2);
}

View File

@@ -0,0 +1,199 @@
/*
* This file is based on
* http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c
*
* The original parts have the following copyright
* ---------------------------------------------------------------------
* Copyright 2001-2004 Unicode, Inc.
*
* Disclaimer
*
* This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine
* applicability of information provided. If this file has been
* purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media
* within 90 days of receipt.
*
* Limitations on Rights to Redistribute This Code
*
* Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form
* for internal or external distribution as long as this notice
* remains attached.
* ---------------------------------------------------------------------
*
* The modifications and additions have the following copyright
*
* Copyright (C) 2005, 2007 Ronald Lamprecht
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "ecl_utf.hh"
#define UNI_SUR_HIGH_START (UTF32)0xD800
#define UNI_SUR_HIGH_END (UTF32)0xDBFF
#define UNI_SUR_LOW_START (UTF32)0xDC00
#define UNI_SUR_LOW_END (UTF32)0xDFFF
#define false 0
#define true 1
namespace ecl
{
static const int halfShift = 10; /* used for shifting by 10 bits */
static const UTF32 halfBase = 0x0010000UL;
static const UTF32 halfMask = 0x3FFUL;
/**
* Index into the table below with the first byte of a UTF-8 sequence to
* get the number of trailing bytes that are supposed to follow it.
* Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
* left as-is for anyone who may want to do such conversion, which was
* allowed in earlier algorithms.
*/
static const char trailingBytesForUTF8[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
};
/*
* Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
* into the first byte, depending on how many bytes follow. There are
* as many entries in this table as there are UTF-8 sequence types.
* (I.e., one byte sequence, two byte... etc.). Remember that sequencs
* for *legal* UTF-8 will be 4 or fewer bytes total.
*/
static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
/* --------------------------------------------------------------------- */
/* The interface converts a whole buffer to avoid function-call overhead.
* Constants have been gathered. Loops & conditionals have been removed as
* much as possible for efficiency, in favor of drop-through switches.
* (See "Note A" at the bottom of the file for equivalent code.)
* If your compiler supports it, the "isLegalUTF8" call can be turned
* into an inline function.
*/
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF16toUTF8 (
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF16* source = *sourceStart;
UTF8* target = *targetStart;
while (source < sourceEnd) {
UTF32 ch;
unsigned short bytesToWrite = 0;
const UTF32 byteMask = 0xBF;
const UTF32 byteMark = 0x80;
const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
ch = *source++;
/* If we have a surrogate pair, convert to UTF32 first. */
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
/* If the 16 bits following the high surrogate are in the source buffer... */
if (source < sourceEnd) {
UTF32 ch2 = *source;
/* If it's a low surrogate, convert to UTF32. */
if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ (ch2 - UNI_SUR_LOW_START) + halfBase;
++source;
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
} else { /* We don't have the 16 bits following the high surrogate. */
--source; /* return to the high surrogate */
result = sourceExhausted;
break;
}
} else if (flags == strictConversion) {
/* UTF-16 surrogate values are illegal in UTF-32 */
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
--source; /* return to the illegal value itself */
result = sourceIllegal;
break;
}
}
/* Figure out how many bytes the result will require */
if (ch < (UTF32)0x80) { bytesToWrite = 1;
} else if (ch < (UTF32)0x800) { bytesToWrite = 2;
} else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
} else if (ch < (UTF32)0x110000) { bytesToWrite = 4;
} else { bytesToWrite = 3;
ch = UNI_REPLACEMENT_CHAR;
}
target += bytesToWrite;
if (target > targetEnd) {
source = oldSource; /* Back up source pointer! */
target -= bytesToWrite; result = targetExhausted; break;
}
switch (bytesToWrite) { /* note: everything falls through. */
case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
}
target += bytesToWrite;
}
*sourceStart = source;
*targetStart = target;
return result;
}
void utf8CharSizes(const std::string &utf8String, std::vector<unsigned char> &sizes)
{
int length = utf8String.size();
for (int i = 0; i < length; ) {
unsigned char c = utf8String[i];
int charSize = trailingBytesForUTF8[c] + 1;
sizes.push_back(charSize);
i += charSize;
}
}
int utf8NextCharSize(const std::string &utf8String) {
unsigned char c = utf8String[0];
int len = 1; // num of bytes that represents one real character
if ((c & 0xC0) == 0x80) {
// a spurious follow up byte
len = 0;
} else if ((c & 0xE0) == 0xC0) {
len = 2;
} else if ((c & 0xF0) == 0xE0) {
len = 3;
} else if ((c & 0xF8) == 0xF0) {
len = 4;
}
return len;
}
} //namespace ecl

View File

@@ -0,0 +1,86 @@
/*
* This file is based on
* http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.h
*
* The original parts have the following copyright
* ---------------------------------------------------------------------
* Copyright 2001-2004 Unicode, Inc.
*
* Disclaimer
*
* This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine
* applicability of information provided. If this file has been
* purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media
* within 90 days of receipt.
*
* Limitations on Rights to Redistribute This Code
*
* Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form
* for internal or external distribution as long as this notice
* remains attached.
* ---------------------------------------------------------------------
* The modifications and additions have the following copyright
*
* Copyright (C) 2005, 2007 Ronald Lamprecht
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* @file ecl_utf.hh Several helper classes and functions for
* utf-16 (unsigned short) and utf-8 (char)
*/
#include <vector>
#include <string>
typedef unsigned long UTF32; /* at least 32 bits */
typedef unsigned short UTF16; /* at least 16 bits */
typedef unsigned char UTF8; /* typically 8 bits */
/* Some fundamental constants */
#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
#define UNI_MAX_BMP (UTF32)0x0000FFFF
#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
typedef enum {
conversionOK, /* conversion successful */
sourceExhausted, /* partial character in source, but hit end */
targetExhausted, /* insuff. room in target for conversion */
sourceIllegal /* source sequence is illegal/malformed */
} ConversionResult;
typedef enum {
strictConversion = 0,
lenientConversion
} ConversionFlags;
namespace ecl
{
ConversionResult ConvertUTF16toUTF8 (
const UTF16** sourceStart, const UTF16* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
void utf8CharSizes(const std::string &utf8String, std::vector<unsigned char> &sizes);
int utf8NextCharSize(const std::string &utf8String);
} //namespace ecl

View File

@@ -0,0 +1,94 @@
/*
* Copyright (C) 2002,2003 Ralf Westram
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "ecl_util.hh"
#include "ecl_system.hh"
#include <cstdarg>
#include <cstdio>
#include <cassert>
using namespace std;
using namespace ecl;
string ecl::concat_paths (const string& path, const string& filename)
{
// concatenate path and filename (or relative subpath)
return
path.substr(0, path.find_last_not_of (PathSeparator)+1) +
PathSeparator +
filename.substr(filename.find_first_not_of (PathSeparator));
}
bool ecl::split_path (const string& path, string* dir_part, string* filename_part)
{
size_t lslash = path.find_last_of (PathSeparators);
if (
#ifdef __MINGW32__
lslash == 2 && path[1] == ':' && (path[0] >= 'A' && path[0] <= 'Z')
#else
lslash == 0
#endif
) {
return false; // we cannot split the root directory apart
}
if (lslash == path.length()-1) // trailing slash
return split_path(path.substr(0, lslash), dir_part, filename_part);
if (lslash == string::npos)
return false;
size_t lnslash = path.find_last_not_of (PathSeparators, lslash);
if (dir_part) *dir_part = path.substr(0, lnslash+1);
if (filename_part) *filename_part = path.substr(lslash+1);
return true;
}
std::string ecl::strf(const char *format, ...) {
static size_t buf_size = 512;
static char *buffer = new char[buf_size];
va_list argPtr;
size_t length;
while (true) {
if (!buffer) {
assert(buffer); // to stop when debugging
return "<alloc problem>";
}
va_start(argPtr, format);
length = vsnprintf(buffer, buf_size, format, argPtr);
va_end(argPtr);
if (length >= 0 && length < buf_size - 1)
// string fits into current buffer
return std::string(buffer, length);
// otherwise resize buffer :
buf_size *= 2;
// fprintf(stderr, "Reallocating vstrf-buffer to size=%u\n", buf_size);
delete [] buffer;
buffer = new char[buf_size];
}
}

View File

@@ -0,0 +1,271 @@
/*
* Copyright (C) 2002,2003,2004,2005 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef ECL_UTIL_HH_INCLUDED
#define ECL_UTIL_HH_INCLUDED
#include <string>
#include <algorithm>
/* hide GNU extensions for non-gnu compilers: */
#ifndef __GNU__
# ifndef __attribute__
// # define __attribute__(x)
// # error wuah
# endif
#endif
namespace ecl
{
/*
** Base class for classes that may not be copied, neither via copy
** constructor or assignment operator.
*/
class Nocopy {
Nocopy(const Nocopy&);
Nocopy& operator=(const Nocopy&);
public:
Nocopy() {}
};
/*
** Some kind of smart pointer. Almost verbatim from tc++pl3
*/
template <class X> class Handle {
X *rep;
int *cnt;
public:
X *operator->() { return rep; }
X *get() const { return rep; }
X &operator *() { return *rep; }
explicit Handle(X *p=0) : rep(p), cnt(new int(1)) {}
Handle(const Handle<X>& a) : rep(a.rep), cnt(a.cnt) {
++(*cnt);
}
Handle<X> &operator=(const Handle<X> &a) {
if (cnt == a.cnt) return *this;
if (--(*cnt) == 0) {
delete rep;
delete cnt;
}
rep = a.rep;
cnt = a.cnt;
(*cnt)++;
return *this;
}
~Handle() {
if (--(*cnt) == 0) {
delete rep;
delete cnt;
}
}
};
/*
** More C++ magic. This class wraps around arbitrary linear
** containers (vector,list), but deletes all stored entries on
** destruction.
**
** Example:
**
** { AutoSequence <vector<Image *> > images;
** images->push_back(new Image("hello.bmp"));
** // ...
** }
**
** All images allocated and stored in `images' have by now been freed.
*/
template <class T>
class AutoSequence : public ecl::Nocopy {
public:
~AutoSequence() { delete_sequence(seq.begin(), seq.end()); }
T *operator->() { return &seq; }
T &operator*() { return seq; }
private:
T seq;
};
template <class Iter> inline
Iter next(const Iter i) {
Iter j=i;
return ++j;
}
template <class Iter> inline
Iter prev(const Iter i) {
Iter j=i;
return --j;
}
template <class For> inline
void
delete_sequence(For begin, For end)
{
while (begin != end)
delete *begin++;
}
template <class For> inline void
delete_map(For begin, For end)
{
while (begin != end)
{
delete begin->second;
++begin;
}
}
template <class T> inline const T &
Max(const T &a, const T &b)
{
return (a > b) ? a : b;
}
template <class T> inline const T &
Min(const T &a, const T &b)
{
return (a < b) ? a : b;
}
template <class T> inline const T &
Clamp (const T& a, const T& min, const T& max)
{
if (a < min)
return min;
else if (a > max)
return max;
else
return a;
}
/*
** Split a string at every occurrence of 'sep' and store the
** resulting strings using the iterator 'out'.
**
** Example:
**
** vector<string> vs;
** split_copy("/usr/bin/enigma", '/', back_inserter(vs));
*/
template <class Ch, class OutIt>
void split_copy(const std::basic_string<Ch> &str, Ch sep, OutIt out)
{
typename std::basic_string<Ch>::const_iterator i,j;
i=str.begin();
while (true) {
j = std::find(i, str.end(), sep);
*out = std::basic_string<Ch>(i,j);
++out;
if (j==str.end())
break;
i=j+1;
}
}
template <class Ch, class OutIt>
size_t split_copy_n (const std::basic_string<Ch> &str, Ch sep, OutIt out, size_t n)
{
typename std::basic_string<Ch>::const_iterator i,j;
i=str.begin();
size_t cnt=0;
for (; cnt < n; ++cnt) {
j = std::find(i, str.end(), sep);
*out = std::basic_string<Ch>(i,j);
++out;
if (j==str.end())
break;
i=j+1;
}
return cnt;
}
/*
** Remove white space at the beginning and end of a string.
*/
template <class Str>
Str trim(const Str& str)
{
if (str.size() == 0)
return str;
typename Str::size_type b = str.find_first_not_of(" \t\n\r");
typename Str::size_type e = str.find_last_not_of(" \t\n\r");
if (b == Str::npos)
return "";
return Str(str, b, e-b+1);
}
/*
** Some helper functions for dealing with bit flags.
*/
template <class E, class I> inline void
set_flags (E &val, I flags)
{
val = static_cast<E> (val | flags);
}
template <class E, class I> inline void
clear_flags (E &val, I flags)
{
val = static_cast<E> (val & ~flags);
}
template <class E, class I> inline void
toggle_flags (E &val, I flags)
{
val = static_cast<E> (val ^ flags);
}
template <class E, class I> inline bool
has_flags (E val, I flags)
{
return (static_cast<int>(val & flags) == static_cast<int>(flags));
}
/*
** Some helper functions for strings and filenames
*/
std::string strf(const char *format, ...) __attribute__((format(printf, 1, 2)));
std::string concat_paths(const std::string& path, const std::string& filename);
/**
* Split a given path into the leading directory part and the last filename
* part. The path may use unix slash separators as well as windows backlashes.
* Even mixed usage is allowed. Trailing path separators are skipped.
* @param path the path to be split
* @param dir_part ptr to a return string where the leading directory
* part without trailing separators will be stored.
* The string will not be set if the result is false.
* @param filename_part ptr to a return string where the trailing filename
* part will be stored.
* The string will not be set if the result is false.
* @return success of splitting the path into 2 parts. If no
* path separator was found just false will be returned
* without modification of the return strings.
*/
bool split_path(const std::string& path, std::string* dir_part, std::string* filename_part);
}
#endif

View File

@@ -0,0 +1,694 @@
/*
* Copyright (C) 2002,2003,2004,2005 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "ecl_video.hh"
#include "ecl_error.hh"
#include "ecl_sdl.hh"
#include "SDL_image.h"
#include "SDL_syswm.h"
#include "SDL_gfxPrimitives.h"
#include "SDL_rotozoom.h"
#include "IMG_SavePNG.h"
#include <cassert>
#include <memory>
#include <cstdio>
using namespace std;
using namespace ecl;
/* -------------------- Graphics primitives -------------------- */
void ecl::frame (const GC &gc, int x, int y, int w, int h) {
hline (gc, x, y, w);
hline (gc, x, y+h-1, w);
vline (gc, x, y, h);
vline (gc, x+w-1, y, h);
}
void ecl::line (const GC &gc, int x1, int y1, int x2, int y2) {
gc.drawable->line (gc, x1, y1, x2, y2);
}
/* -------------------- Clipping helper routines -------------------- */
namespace
{
inline bool NOCLIP(const GS &gs) {
return gs.flags & GS_NOCLIP;
}
bool clip_hline (const GS &gs, int &x, int &y, int &w) {
const Rect &cliprect = gs.cliprect;
if (y < cliprect.y || y >= cliprect.y + cliprect.h)
return false;
int d = x - cliprect.x;
if (d < 0) {
w += d;
x = cliprect.x;
}
d = (cliprect.x+cliprect.w) - (x+w);
if (d < 0)
w += d;
return w > 0;
}
bool clip_vline (const GS &gs, int &x, int &y, int &h) {
const Rect &cliprect = gs.cliprect;
if (x < cliprect.x || x >= cliprect.x + cliprect.w)
return false;
int d = y - cliprect.y;
if (d < 0) {
h += d;
y = cliprect.y;
}
d = cliprect.y+cliprect.h - (y+h);
if (d < 0)
h += d;
return h > 0;
}
bool clip_blit (Rect cliprect, int &x, int &y, Rect &r) {
cliprect.x += r.x-x;
cliprect.y += r.y-y;
cliprect.intersect (r);
if (cliprect.w > 0 && cliprect.h > 0) {
x += cliprect.x-r.x;
y += cliprect.y-r.y;
r = cliprect;
return true;
}
return false;
}
bool clip_rect (const GS &gs, Rect &r) {
r.intersect (gs.cliprect);
return r.w > 0 && r.h > 0;
}
inline bool clip_pixel (const GS &gs, int x, int y) {
return gs.cliprect.contains(x,y);
}
}
/* -------------------- Drawable implementation -------------------- */
/* `Xlib.h' also defines a type named `Drawable' so we have to specify
the namespace explicitly and cannot simply use a using-declaration. */
void ecl::Drawable::set_pixels (const GS &gs, int n, const int* x, const int* y)
{
const int *xp = x, *yp = y;
for (int i=n; i; --i)
set_pixel(gs, *xp++, *yp++);
}
void ecl::Drawable::hline (const GS &gs, int x, int y, int w)
{
for (int i=w; i; --i)
set_pixel (gs, x++, y);
}
void ecl::Drawable::vline (const GS &gs, int x, int y, int h)
{
for (int i=h; i; --i)
set_pixel (gs, x, y++);
}
void ecl::Drawable::box (const GS &gs, int x, int y, int w, int h)
{
for (int i=h; i; --i)
hline (gs, x, y--, w);
}
void ecl::Drawable::line(const GS &, int /*x1*/, int /*y1*/, int /*x2*/, int /*y2*/)
{
}
namespace
{
/* ---------- Generic Surface implementation ---------- */
template <class PIXELT>
class TSurface : virtual public Surface {
public:
TSurface (SDL_Surface *s=0) : Surface(s) {}
PIXELT *pixel_pointer(int x, int y) {
return static_cast<PIXELT*>(Surface::pixel_pointer(x,y));
}
/* ---------- Drawable interface ---------- */
PackedColor get_pixel (int x, int y) {
return *pixel_pointer(x,y);
}
void set_pixel (const GS &gs, int x, int y) {
if (NOCLIP(gs) || clip_pixel(gs, x, y)) {
*pixel_pointer(x, y) = gs.pcolor;
}
}
void set_pixels(const GS &gs, int n, const int* xlist, const int* ylist, Uint32 color) {
const int *xp = xlist, *yp = ylist;
if (NOCLIP(gs)) {
for (int i=n; i > 0; --i) {
int x = *xp++, y = *yp++;
*pixel_pointer(x,y) = gs.pcolor;
}
} else {
for (int i=n; i > 0; --i) {
int x = *xp++, y = *yp++;
if (clip_pixel (gs, x, y))
*pixel_pointer(x,y) = gs.pcolor;
}
}
}
void hline (const GS &gs, int x, int y, int w) {
if (NOCLIP(gs) || clip_hline(gs, x, y, w)) {
PIXELT* dst = pixel_pointer(x, y);
for (; w > 0; --w)
*dst++ = gs.pcolor;
}
}
void vline (const GS &gs, int x, int y, int h) {
if (NOCLIP(gs) || clip_vline(gs, x, y, h)) {
PIXELT* dst = pixel_pointer(x, y);
int offset = pitch() / bypp();
for (; h > 0; --h)
{
*dst = gs.pcolor;
dst += offset;
}
}
}
};
typedef TSurface<Uint8> Surface8;
typedef TSurface<Uint16> Surface16;
typedef TSurface<Uint32> Surface32;
/* ---------- Surface24 ---------- */
class Surface24 : virtual public Surface {
public:
Surface24 (SDL_Surface *s=0) : Surface(s) {}
void set_pixel (const GS &gs, int x, int y) {
if (NOCLIP(gs) || clip_pixel(gs, x, y)) {
Uint8* p = static_cast<Uint8*> (pixel_pointer(x, y));
SDL_GetRGB(gs.pcolor, m_surface->format, p,p+1,p+2);
}
}
Uint32 get_pixel (int x, int y) {
// if (NOCLIP(gs) || clip_pixel(gs, x, y)) {
Uint8* p = static_cast<Uint8*> (pixel_pointer(x, y));
return SDL_MapRGB(m_surface->format, p[0],p[1],p[2]);
// }
}
};
}
/* -------------------- Surface -------------------- */
Surface::Surface (SDL_Surface* sfc)
: m_surface(sfc)
{
}
Surface::~Surface() {
SDL_FreeSurface(m_surface);
}
void Surface::lock() {
if (SDL_MUSTLOCK (m_surface))
SDL_LockSurface (m_surface);
}
void Surface::unlock() {
if (SDL_MUSTLOCK (m_surface))
SDL_UnlockSurface (m_surface);
}
PackedColor
Surface::map_color(int r, int g, int b)
{
return SDL_MapRGB(m_surface->format, r, g, b);
}
PackedColor
Surface::map_color(int r, int g, int b, int a)
{
return SDL_MapRGBA(m_surface->format, r, g, b, a);
}
void Surface::box (const GS &gs, int x, int y, int w, int h) {
Rect r (x, y, w, h);
if (NOCLIP(gs) || clip_rect (gs, r)) {
SDL_Rect dr;
sdl::copy_rect (dr, r);
SDL_FillRect (m_surface, &dr, gs.pcolor);
}
}
void Surface::line (const GS &gs, int x1, int y1, int x2, int y2) {
SDL_Rect s;
sdl::copy_rect(s, gs.cliprect);
SDL_SetClipRect (m_surface, &s);
Uint8 r, g, b, a;
SDL_GetRGBA (gs.pcolor, m_surface->format, &r, &g, &b, &a);
if (has_flags(gs.flags, GS_ANTIALIAS))
aalineRGBA (m_surface, x1, y1, x2, y2, r, g, b, a);
else
lineRGBA (m_surface, x1, y1, x2, y2, r, g, b, a);
SDL_SetClipRect (m_surface, 0);
}
void Surface::blit (const GS &gs, int x, int y, const Surface* s, const Rect &r_) {
Rect r(r_);
if (NOCLIP(gs) || clip_blit (gs.cliprect, x, y, r)) {
SDL_Rect r1;
SDL_Rect r2;
sdl::copy_rect (r1, r);
r2.x = x; r2.y = y;
SDL_BlitSurface (s->m_surface, &r1, m_surface, &r2);
}
}
void Surface::blit (const GS &gs, int x, int y, const Surface* src) {
assert (src != 0);
blit (gs, x, y, src, src->size());
}
void Surface::set_color_key (int r, int g, int b) {
Uint32 color = map_color(r,g,b);
SDL_SetColorKey(get_surface(), SDL_SRCCOLORKEY | SDL_RLEACCEL, color);
}
void Surface::set_alpha(int a) {
SDL_SetAlpha(get_surface(), SDL_SRCALPHA, a);
}
Surface * Surface::zoom(int w, int h)
{
SDL_Surface *s_new;
s_new = zoomSurface( get_surface(), (double)w/width(), (double)h/height(), true);
return Surface::make_surface (s_new);
}
Surface *
Surface::make_surface (SDL_Surface *sdls)
{
if (sdls == 0) return 0;
switch (sdls->format->BitsPerPixel) {
case 8: return new Surface8 (sdls); break;
case 16: return new Surface16(sdls); break;
case 32: return new Surface32(sdls); break;
case 24: return new Surface24(sdls); break;
default:
fprintf(stderr, "Invalid bit depth in surface.\n");
return 0; // throw XVideo("Invalid bit depth in surface.");
}
}
/* -------------------- Screen -------------------- */
/* `Xlib.h' also defines a type named `Screen' so we have to specify
the namespace explicitly and cannot simply use a using-declaration. */
ecl::Screen *ecl::Screen::m_instance = 0;
ecl::Screen *
ecl::Screen::get_instance() {
return m_instance;
}
ecl::Screen::Screen (Surface *s)
: m_surface(s), m_sdlsurface(s->get_surface()), update_all_p(false)
{
assert (m_instance == 0);
m_instance = this;
}
ecl::Screen::Screen (SDL_Surface *s)
: m_surface (Surface::make_surface(s)), m_sdlsurface(s), update_all_p(false)
{
assert (m_instance == 0);
m_instance = this;
}
ecl::Screen::~Screen() {
m_instance = 0;
}
void ecl::Screen::update_all()
{
//SDL_UpdateRect(get_surface(), 0, 0, 0, 0);
update_all_p = true;
}
void ecl::Screen::update_rect(const Rect& r)
{
if (m_dirtyrects.size() < 200)
m_dirtyrects.push_back(r);
else
update_all();
}
void ecl::Screen::set_caption(const char* str)
{
SDL_WM_SetCaption(str, 0);
}
void ecl::Screen::flush_updates()
{
if (update_all_p) {
SDL_UpdateRect(m_sdlsurface, 0, 0, 0, 0); // update everything
update_all_p=false;
}
else if (!m_dirtyrects.empty()) {
m_dirtyrects.intersect (size());
vector<SDL_Rect> rects(m_dirtyrects.size());
RectList::iterator j=m_dirtyrects.begin();;
for (unsigned i=0; i<rects.size(); ++i, ++j)
sdl::copy_rect (rects[i], *j);
SDL_UpdateRects (m_sdlsurface, rects.size(), &rects[0]);
}
m_dirtyrects.clear();
}
Rect ecl::Screen::size() const {
return Rect(0, 0, width(), height());
}
int ecl::Screen::width() const {
return m_sdlsurface->w;
}
int ecl::Screen::height() const {
return m_sdlsurface->h;
}
/* -------------------- Functions -------------------- */
/* Convert the surface to the native surface format. A pointer to a
new surface is returned; the old one must be deleted by hand if it
is no longer needed. */
Surface*
ecl::DisplayFormat(Surface* s)
{
if (SDL_Surface* s2 = SDL_DisplayFormat(s->get_surface()))
return Surface::make_surface(s2);
return 0;
}
ecl::Screen *
ecl::OpenScreen(int w, int h, int bipp)
{
SDL_Surface* sfc = SDL_SetVideoMode(w, h, bipp, SDL_SWSURFACE);
return new Screen(sfc);
}
Surface *
ecl::Duplicate(const Surface *s)
{
if (s==0) return 0;
SDL_Surface *sdls = s->get_surface();
SDL_Surface *copy = SDL_ConvertSurface(sdls, sdls->format, sdls->flags);
if (sdls->format->palette != 0)
SDL_SetColors(copy, sdls->format->palette->colors, 0,
sdls->format->palette->ncolors);
return Surface::make_surface(copy);
}
void ecl::SavePNG (const ecl::Surface *s, const std::string &filename)
{
IMG_SavePNG(s->get_surface(), filename.c_str());
}
void ecl::TintRect(Surface *s, Rect rect, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
std::auto_ptr<Surface> copy(Grab(s, rect));
if (copy.get()) {
copy->set_alpha(a);
GC gc(s);
set_color(gc, r,g,b);
box(gc, rect);
blit(gc, rect.x, rect.y, copy.get());
}
}
/*
* (SDL_ConvertSurface with a few changes)
*/
static SDL_Surface *CropSurface (SDL_Surface *surface,
SDL_Rect rect,
SDL_PixelFormat *format,
Uint32 flags)
{
SDL_Surface *convert;
Uint32 colorkey = 0;
Uint8 alpha = 0;
Uint32 surface_flags;
SDL_Rect bounds;
/* Check for empty destination palette! (results in empty image) */
if ( format->palette != NULL ) {
int i;
for ( i=0; i<format->palette->ncolors; ++i ) {
if ( (format->palette->colors[i].r != 0) ||
(format->palette->colors[i].g != 0) ||
(format->palette->colors[i].b != 0) )
break;
}
if ( i == format->palette->ncolors ) {
SDL_SetError("Empty destination palette");
return(NULL);
}
}
/* Create a new surface with the desired format */
convert = SDL_CreateRGBSurface(flags,
rect.w, rect.h, format->BitsPerPixel,
format->Rmask, format->Gmask, format->Bmask, format->Amask);
if ( convert == NULL ) {
return(NULL);
}
/* Copy the palette if any */
if ( format->palette && convert->format->palette ) {
memcpy(convert->format->palette->colors,
format->palette->colors,
format->palette->ncolors*sizeof(SDL_Color));
convert->format->palette->ncolors = format->palette->ncolors;
}
/* Save the original surface color key and alpha */
surface_flags = surface->flags;
if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
/* Convert colourkeyed surfaces to RGBA if requested */
if((flags & SDL_SRCCOLORKEY) != SDL_SRCCOLORKEY
&& format->Amask) {
surface_flags &= ~SDL_SRCCOLORKEY;
} else {
colorkey = surface->format->colorkey;
SDL_SetColorKey(surface, 0, 0);
}
}
if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
alpha = surface->format->alpha;
SDL_SetAlpha(surface, 0, 0);
}
/* Copy over the image data */
bounds.x = 0;
bounds.y = 0;
bounds.w = rect.w;
bounds.h = rect.h;
SDL_LowerBlit(surface, &rect, convert, &bounds);
/* Clean up the original surface, and update converted surface */
// if ( convert != NULL ) {
// SDL_SetClipRect(convert, &surface->clip_rect);
// }
if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
Uint32 cflags = surface_flags&(SDL_SRCCOLORKEY|SDL_RLEACCELOK);
if ( convert != NULL ) {
Uint8 keyR, keyG, keyB;
SDL_GetRGB(colorkey,surface->format,&keyR,&keyG,&keyB);
SDL_SetColorKey(convert, cflags|(flags&SDL_RLEACCELOK),
SDL_MapRGB(convert->format, keyR, keyG, keyB));
}
SDL_SetColorKey(surface, cflags, colorkey);
}
if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
Uint32 aflags = surface_flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
if ( convert != NULL ) {
SDL_SetAlpha(convert, aflags|(flags&SDL_RLEACCELOK),
alpha);
}
SDL_SetAlpha(surface, aflags, alpha);
}
/* We're ready to go! */
return(convert);
}
Surface * ecl::Grab (const Surface *s, Rect &r) {
if (s==0)
return 0;
SDL_Surface *sdls = s->get_surface();
int x = 0;
int y = 0;
clip_blit (s->size(), x, y, r);
SDL_Rect rect;
sdl::copy_rect (rect, r);
SDL_Surface *copy = CropSurface (sdls, rect, sdls->format, sdls->flags);
return Surface::make_surface (copy);
}
// LoadImage is already defined as a macro in some Windows header file
#undef LoadImage
Surface* ecl::LoadImage (const char* filename)
{
return LoadImage(IMG_Load(filename));
}
Surface* ecl::LoadImage(SDL_RWops *src, int freesrc) {
return LoadImage(IMG_Load_RW(src, freesrc));
}
Surface* ecl::LoadImage(SDL_Surface *tmp) {
if (tmp != NULL)
{
SDL_Surface* img;
if (tmp->flags & SDL_SRCALPHA) {
SDL_SetAlpha(tmp, SDL_RLEACCEL, 0);
img = SDL_DisplayFormatAlpha(tmp);
}
else if (tmp->flags & SDL_SRCCOLORKEY) {
SDL_SetColorKey(tmp, SDL_SRCCOLORKEY | SDL_RLEACCEL,
tmp->format->colorkey);
img = SDL_DisplayFormat(tmp);
}
else
img = SDL_DisplayFormat(tmp);
if (img == 0)
return Surface::make_surface (tmp);
SDL_FreeSurface(tmp);
return Surface::make_surface (img);
}
return 0;
}
Surface * ecl::MakeSurface(int w, int h, int bipp, const RGBA_Mask &mask)
{
SDL_Surface* sfc;
sfc = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, bipp,
mask.r, mask.g, mask.g, mask.a);
if (sfc == 0)
return 0; //throw XVideo(string("Couldn't create surface: ") + SDL_GetError());
return Surface::make_surface (sfc);
}
/* Create a surface from image data that is already somewhere in
memory. */
Surface * ecl::MakeSurface(void *data, int w, int h, int bipp, int pitch,
const RGBA_Mask &mask)
{
SDL_Surface* sfc;
sfc = SDL_CreateRGBSurfaceFrom(data, w, h, bipp,
pitch, mask.r, mask.g, mask.b, mask.a);
if (sfc == 0)
return 0; //throw XVideo(string("Couldn't create surface:") + SDL_GetError());
return Surface::make_surface (sfc);
}
Surface *ecl::MakeSurfaceLike (int w, int h, Surface *surface)
{
if (surface == 0)
return 0;
SDL_Surface *sdls = surface->get_surface();
return MakeSurface (w, h, sdls->format->BitsPerPixel,
RGBA_Mask(sdls->format->Rmask,
sdls->format->Gmask,
sdls->format->Bmask,
sdls->format->Amask));
}
/*! Resample a region inside a surface to a new size. Returns a
new 32 bit RGBA image containing the scaled image. */
Surface *ecl::Resample (Surface *s, Rect rect, int neww, int newh,
ResampleFilter /*filter*/)
{
SDL_Surface *sdls = SDL_CreateRGBSurface(SDL_SWSURFACE, rect.w, rect.h, 32,
0, 0, 0, 0);
SDL_Rect r;
sdl::copy_rect (r, rect);
SDL_BlitSurface (s->get_surface(), &r, sdls, 0);
SDL_Surface *s_new;
s_new = zoomSurface (sdls,
(double)neww/rect.w,
(double)newh/rect.h, true);
SDL_FreeSurface (sdls);
return Surface::make_surface (s_new);
}

View File

@@ -0,0 +1,366 @@
/*
* Copyright (C) 2002,2003 Daniel Heck
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef ECL_VIDEO_HH_INCLUDED
#define ECL_VIDEO_HH_INCLUDED
#include "ecl_fwd.hh"
#include "ecl_geom.hh"
#include "SDL.h"
namespace ecl
{
/* -------------------- Colors -------------------- */
struct RGBA_Mask {
RGBA_Mask(Uint32 rr=0, Uint32 gg=0, Uint32 bb=0, Uint32 aa=0)
: r(rr), g(gg), b(bb), a(aa)
{}
Uint32 r,g,b,a;
};
struct RGB {
RGB(char rr=0, char gg=0, char bb=0)
: r(rr), g(gg), b(bb)
{}
char r,g,b;
};
struct RGBA {
RGBA(char rr=0, char gg=0, char bb=0, char aa=0)
: r(rr), g(gg), b(bb), a(aa)
{}
char r,g,b,a;
};
typedef Uint32 PackedColor;
/* -------------------- Graphics State (GS) -------------------- */
enum GS_Flags {
GS_DEFAULT = 0,
GS_ANTIALIAS = 1,
GS_NOCLIP = 2
};
struct GraphicsState {
// Constructors.
GraphicsState (const Rect &clipr = Rect())
: cliprect(clipr), pcolor(0), flags(GS_DEFAULT)
{}
// Variables.
Rect cliprect; // current clipping rectangle
PackedColor pcolor; // current color
unsigned flags;
};
typedef GraphicsState GS;
/* -------------------- Drawable -------------------- */
class Drawable {
public:
virtual ~Drawable() {}
/* ---------- Drawable interface ---------- */
virtual PackedColor map_color(int r, int g, int b) = 0;
virtual PackedColor map_color(int r, int g, int b, int a) = 0;
virtual void blit (const GS &gs, int x, int y, const Surface* s) = 0;
virtual void blit (const GS &gs, int x, int y, const Surface* s, const Rect& r) = 0;
virtual Uint32 get_pixel (int x, int y) = 0;
//! Set a single pixel
virtual void set_pixel (const GS &gs, int x, int y) = 0;
//! Set multiple pixels at once
virtual void set_pixels (const GS &gs, int n, const int *x, const int *y);
//! Draw a horizontal line
virtual void hline (const GS &gs, int x, int y, int w);
//! Draw a vertical line
virtual void vline (const GS &gs, int x, int y, int h);
//! Draw an arbitrary line
virtual void line (const GS &gs, int x1, int y1, int x2, int y2);
//! Draw a filled box.
virtual void box (const GS &gs, int x, int y, int w, int h);
//! Return size of drawable: Rect (0,0,width, height)
virtual Rect size() const = 0;
};
/* -------------------- Graphics Context (GC) -------------------- */
struct GC : public GraphicsState {
GC(Drawable* d) :GraphicsState (d->size()) {
drawable = d;
}
Drawable *drawable;
};
/* -------------------- Surface -------------------- */
class Surface : public Drawable {
public:
~Surface();
Surface *zoom(int w, int h);
void set_color_key (int r, int g, int b);
void set_alpha (int a);
void lock();
void unlock();
int bypp() const { return m_surface->format->BytesPerPixel; }
int bipp() const { return m_surface->format->BitsPerPixel; }
Uint32 pitch() const { return m_surface->pitch; }
inline void* scanline_pointer(int y) {
return (Uint8*)m_surface->pixels + y*pitch();
}
inline void* pixel_pointer(int x, int y) {
return static_cast<Uint8*>(scanline_pointer(y)) + x*bypp();
}
int height() const { return m_surface->h; }
int width() const { return m_surface->w; }
SDL_Surface *get_surface() const { return m_surface; }
/* ---------- Drawable interface ---------- */
PackedColor map_color(int r, int g, int b);
PackedColor map_color(int r, int g, int b, int a);
Rect size() const { return Rect(0,0,m_surface->w, m_surface->h); }
void box (const GS &gs, int x, int y, int w, int h);
void line (const GS &gs, int x1, int y1, int x2, int y2);
void blit (const GS &gs, int x, int y, const Surface* s, const Rect &r);
void blit (const GS &gs, int x, int y, const Surface* src);
/* ---------- Static methods ---------- */
//! Create a new surface
static Surface *make_surface (SDL_Surface *s);
protected:
// Constructor.
Surface (SDL_Surface* sfc);
// Variables
SDL_Surface *m_surface;
private:
};
class SurfaceLock {
Surface *s;
public:
SurfaceLock (Surface *s_) : s(s_) { s->lock(); }
~SurfaceLock() { s->unlock(); }
};
/* -------------------- Screen -------------------- */
class Screen {
public:
Screen (Surface *s);
Screen (SDL_Surface *s);
~Screen();
void update_all();
void update_rect(const Rect& r);
void flush_updates();
void set_caption(const char* str);
/* ---------- Accessors ---------- */
Surface *get_surface() const { return m_surface; }
Rect size() const;
int width() const;
int height() const;
/* ---------- Static methods ---------- */
static Screen *get_instance();
private:
// Variables.
static Screen *m_instance;
Surface *m_surface;
SDL_Surface *m_sdlsurface;
RectList m_dirtyrects;
bool update_all_p;
Screen(const Screen&);
Screen& operator=(const Screen&);
};
/* -------------------- Graphics primitives -------------------- */
inline void set_color (GC &gc, int r, int g, int b, int a) {
gc.pcolor = gc.drawable->map_color(r, g, b, a);
}
inline void set_color (GC &gc, int r, int g, int b) {
gc.pcolor = gc.drawable->map_color(r, g, b);
}
inline void set_color (GC &gc, const RGB &c) {
set_color (gc, c.r, c.g, c.b);
}
inline void set_color (GS &gs, PackedColor c) {
gs.pcolor=c;
}
inline void enable_clipping(GS &gs) {
clear_flags (gs.flags, GS_NOCLIP);
}
inline void disable_clipping (GS &gs) {
set_flags (gs.flags, GS_NOCLIP);
}
inline void clip (GS &gs, const Rect& r) {
gs.cliprect = r;
enable_clipping(gs);
}
inline void clip (GC &gc, const Rect& r) {
gc.cliprect = intersect (r, gc.drawable->size());
enable_clipping(gc);
}
inline void clip (GC &gc) {
clip (gc, gc.drawable->size());
}
inline void blit (const GC &gc, int x, int y, const Surface *s) {
gc.drawable->blit (gc, x, y, s);
}
inline void blit(const GC &gc, int x, int y, const Surface *s, const Rect &r) {
gc.drawable->blit (gc, x, y, s, r);
}
inline void set_pixel(const GC &gc, int x, int y) {
gc.drawable->set_pixel (gc, x, y);
}
inline void hline (const GC & gc, int x, int y, int w) {
gc.drawable->hline (gc, x, y, w);
}
inline void vline (const GC & gc, int x, int y, int h) {
gc.drawable->vline (gc, x, y, h);
}
inline void box (const GC &gc, const Rect& r) {
gc.drawable->box(gc, r.x, r.y, r.w, r.h);
}
inline void box (const GC &gc, int x, int y, int w, int h) {
gc.drawable->box (gc, x, y, w, h);
}
void line (const GC &gc, int x1, int y1, int x2, int y2);
void frame (const GC & gc, int x, int y, int w, int h);
inline void frame (const GC &gc, const Rect& r) {
frame (gc, r.x, r.y, r.w, r.h);
}
/* -------------------- Functions -------------------- */
Screen *OpenScreen (int w, int h, int bipp);
Screen* DisplayFormat(Screen* s);
/*! Create a new surface. */
Surface *MakeSurface(int w, int h, int bipp,
const RGBA_Mask &mask = RGBA_Mask());
/*! Create a surface from image data that is already somewhere in
memory. */
Surface * MakeSurface(void* data, int w, int h, int bipp, int pitch,
const RGBA_Mask &mask = RGBA_Mask());
/*! Create a new surface with the same image format as
`surface'. */
Surface *MakeSurfaceLike (int w, int h, Surface *surface);
/*! Create a copy of a surface. */
Surface *Duplicate(const Surface *s);
/*! Save a surface to a PNG file. */
void SavePNG (const Surface *s, const std::string& filename);
/*! Create a new surface from a selection of an old one. Performs
proper clipping and returns a surface of the appropriate size
(this may be smaller than the original size given in `r'.) The
function stores the real region in `r'. */
Surface *Grab(const Surface *s, Rect &r);
/*! Convert a surface to the current screen's native format. */
Surface* DisplayFormat(Surface* s);
/*! Load an image using SDL_image and convert it to an optimized
format. */
Surface* LoadImage(const char* filename);
Surface* LoadImage(SDL_RWops *src, int freesrc);
Surface* LoadImage(SDL_Surface *tmpImage);
/*! Overlay a rectangle `rect' in `s' with a transparent colored
box. */
void TintRect(Surface *s, Rect rect, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
enum ResampleFilter {
FILTER_BILINEAR,
FILTER_LANCZOS
};
/*! Resample a region inside a surface to a new size. Returns a
new 32 bit RGBA image containing the scaled image.
(Only partially implemented so far.)
*/
Surface *Resample (Surface *s, Rect rect, int neww, int newh,
ResampleFilter filter = FILTER_BILINEAR);
}
#endif /* !ECL_VIDEO_HH_INCLUDED */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,97 @@
// Copyright 2003 Jeremy Sawicki
//
// This file is part of OxydLib.
//
// OxydLib is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// OxydLib is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with OxydLib; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#ifndef BITMAP_H
#define BITMAP_H
#include "VecUtils.h"
#include <string>
namespace OxydLib {
using std::string;
class Palette
{
public:
Palette();
~Palette();
int getNumColors() const;
void setNumColors(int numColors);
void getColor(int nColor,
unsigned int *pRed,
unsigned int *pGreen,
unsigned int *pBlue) const;
void setColor(int nColor,
unsigned int red,
unsigned int green,
unsigned int blue);
private:
std::vector<unsigned int> m_colors;
};
class Bitmap
{
public:
Bitmap();
~Bitmap();
void clear();
int getBitDepth() const { return m_bitDepth; }
void setBitDepth(int bitDepth) { m_bitDepth = bitDepth; }
unsigned char getPixel(int x, int y) const;
void setPixel(int x, int y, unsigned char pixelVal);
int getBit(int x, int y, int bitNum) const;
void setBit(int x, int y, int bitNum, int bitVal);
private:
int m_bitDepth;
ByteVec m_pixels;
};
// Both parseBitmap and unparseBitmap work with 16-color palettes,
// regardless of the bit depth of the bitmap.
bool parseBitmap(const ByteVec &in,
Bitmap *pBitmap,
Palette *pPalette,
string *pMsg = 0);
bool unparseBitmap(const Bitmap &bitmap,
const Palette &palette,
ByteVec *pOut,
string *pMsg = 0);
// The palette passed to bitmapToPPM should have 2^(bit depth of bitmap)
// colors.
void bitmapToPPM(const Bitmap &bitmap,
const Palette &palette,
ByteVec *pOut);
void bitPlaneToPPM(const Bitmap &bitmap,
int nBitPlane,
ByteVec *pOut);
}
#endif

View File

@@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@@ -0,0 +1,612 @@
// Copyright 2003 Jeremy Sawicki
//
// This file is part of OxydLib.
//
// OxydLib is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// OxydLib is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with OxydLib; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "DatFile.h"
#include "VecUtils.h"
#include <stdio.h>
#include <algorithm>
namespace OxydLib {
using namespace std;
namespace
{
unsigned char levelShifts[OxydVersion_Count][16] =
{{0x45, 0x23, 0xEA, 0xB9, 0x11, 0xF1, 0x9F, 0x5A,
0x33, 0x3E, 0x0F, 0xB4, 0x41, 0x56, 0xAF, 0xAA},
{0x45, 0x23, 0xEA, 0xB9, 0x11, 0xF1, 0x9F, 0x5A,
0x33, 0x3E, 0x0F, 0xB4, 0x41, 0x56, 0xAF, 0xAA},
{0x45, 0x23, 0xEA, 0xB9, 0x11, 0xF1, 0x9F, 0x5A,
0x33, 0x3E, 0x0F, 0xB4, 0x41, 0x56, 0xAF, 0xAA},
{0xAA, 0xE1, 0x82, 0x34, 0xAF, 0x24, 0x72, 0x42,
0x37, 0x3E, 0x83, 0x98, 0x22, 0xFF, 0x2F, 0x31},
{0x45, 0x23, 0xEA, 0xB9, 0x11, 0xF1, 0x9F, 0x5A,
0x33, 0x3E, 0x0F, 0xB4, 0x41, 0x56, 0xAF, 0xAA}};
void unshiftBytes(ByteVec *pVec, OxydVersion ver)
{
for (int nByte = 0; nByte < (int)pVec->size(); nByte++) {
(*pVec)[nByte] =
(int((*pVec)[nByte]) + 256 - levelShifts[ver][nByte % 16]) % 256;
}
}
void shiftBytes(ByteVec *pVec, OxydVersion ver)
{
for (int nByte = 0; nByte < (int)pVec->size(); nByte++) {
(*pVec)[nByte] =
(int((*pVec)[nByte]) + levelShifts[ver][nByte % 16]) % 256;
}
}
void unscrambleChunkTableData(ByteVec::iterator it)
{
unsigned int val = getInt4(it);
unsigned int valPrime = 0xffffffff &
~(((val & 0x1fffffff) << 3) +
((val & 0xe0000000) >> 29));
putInt4(it, valPrime);
}
void scrambleChunkTableData(ByteVec::iterator it)
{
unsigned int val = getInt4(it);
unsigned int valPrime = 0xffffffff &
~(((val & 0xfffffff8) >> 3) +
((val & 0x00000007) << 29));
putInt4(it, valPrime);
}
}
DatFile::DatFile()
{
clear();
}
DatFile::~DatFile()
{
}
void DatFile::clear()
{
m_bInit = false;
m_ver = OxydVersion_Oxyd1;
m_credits.clear();
m_codes.clear();
m_levels.clear();
m_levels.resize(200);
m_chunks.clear();
}
void DatFile::getChunkNames(set<string> *pChunkNames) const
{
pChunkNames->clear();
ChunkMap::const_iterator iter = m_chunks.begin();
ChunkMap::const_iterator end = m_chunks.end();
for (; iter != end; ++iter) {
pChunkNames->insert(iter->first);
}
}
void DatFile::addChunk(const string &chunkName)
{
m_chunks[chunkName];
}
void DatFile::removeChunk(const string &chunkName)
{
m_chunks.erase(chunkName);
}
const ByteVec *DatFile::getChunk(const string &chunkName) const
{
ChunkMap::const_iterator iter = m_chunks.find(chunkName);
if (iter == m_chunks.end()) {
return 0;
} else {
return &iter->second;
}
}
ByteVec *DatFile::getChunkForWrite(const string &chunkName)
{
ChunkMap::iterator iter = m_chunks.find(chunkName);
if (iter == m_chunks.end()) {
return 0;
} else {
return &iter->second;
}
}
namespace
{
bool uncompressChunk(const ByteVec &in,
ByteVec *pOut,
string *pMsg)
{
string msg;
if (!pMsg) {
pMsg = &msg;
}
ByteVec &out = *pOut;
int compressedSize = in.size();
int uncompressedSize = out.size();
if (compressedSize == uncompressedSize) {
copy(in.begin(), in.end(), out.begin());
} else {
unsigned char keyByte = 0;
int curBit = 0;
int curIn = 0;
int curOut = 0;
int szIn = in.size();
int szOut = out.size();
while (curOut < szOut) {
if (curBit == 0) {
if (curIn + 1 > szIn) {
pMsg->assign("Not enough compressed data reading key byte.");
return false;
}
keyByte = in[curIn];
curIn++;
}
if (keyByte & (1 << curBit)) {
if (curIn + 1 > szIn) {
pMsg->assign("Not enough compressed data reading literal byte.");
return false;
}
unsigned char literalByte = in[curIn];
curIn++;
out[curOut] = literalByte;
curOut++;
} else {
if (curIn + 2 > szIn) {
pMsg->assign("Not enough compressed data reading compressed byte.");
return false;
}
unsigned char b1 = in[curIn];
curIn++;
unsigned char b2 = in[curIn];
curIn++;
int outBytes = ((int)(b2 & 0x0f)) + 3;
if (curOut + outBytes > szOut) {
pMsg->assign("Too much uncompressed data.");
return false;
}
int offset = ((int)b1) + ((((int)b2) & 0xf0) << 4);
offset = ((offset + 0x12) & 0x0fff);
offset |= (curOut & ~0x0fff);
if (offset >= curOut) {
offset -= 0x1000;
}
if (offset + outBytes < 0) {
pMsg->assign("Referencing data unnecessarily far before beginning of output.");
return false;
}
for (int i = 0; i < outBytes; i++) {
if (offset < 0) {
out[curOut] = 0x20;
} else {
out[curOut] = out[offset];
}
curOut++;
offset++;
}
}
curBit = ((curBit + 1) & 0x7);
}
if (curIn < szIn) {
pMsg->assign("Too much compressed data while uncompressing chunk.");
return false;
}
while (curBit != 0) {
if (keyByte & (1 << curBit)) {
pMsg->assign("Extra bit in compressed chunk key byte is not 0.");
return false;
}
curBit = ((curBit + 1) & 0x7);
}
}
return true;
}
}
bool parseDatFile(const ByteVec &in,
OxydVersion ver,
DatFile *pDatFile,
string *pMsg)
{
string msg;
if (!pMsg) {
pMsg = &msg;
}
pDatFile->clear();
pDatFile->setVersion(ver);
int sz = in.size();
int cur = 0;
if (cur + 600 + 4 + 4 + 400 > sz) {
pMsg->assign("File too small for header.");
return false;
}
ByteVec *pCredits = pDatFile->getCreditsForWrite();
pCredits->resize(600);
copy(in.begin() + cur, in.begin() + cur + 600, pCredits->begin());
cur += 600;
int levelSkip = getInt4(in.begin() + cur);
cur += 4;
if (levelSkip < (4 + 4 + 400)) {
pMsg->assign("Level skip value is too small.");
return false;
}
ByteVec *pCodes = pDatFile->getCodesForWrite();
pCodes->resize(4);
copy(in.begin() + cur, in.begin() + cur + 4, pCodes->begin());
cur += 4;
vector<int> levelSizes;
levelSizes.resize(200);
int levelSizeTotal = 0;
int nLevel;
for (nLevel = 0; nLevel < 200; nLevel++) {
int levelSize = getInt2(in.begin() + cur);
cur += 2;
levelSizes[nLevel] = levelSize;
levelSizeTotal += levelSize;
}
if (levelSkip != 4 + 4 + 400 + levelSizeTotal) {
pMsg->assign("Level skip value does not correspond to sum of level sizes.");
return false;
}
if (cur + levelSizeTotal > sz) {
pMsg->assign("File too small for levels.");
return false;
}
for (nLevel = 0; nLevel < 200; nLevel++) {
ByteVec *pLevelData = pDatFile->getLevelForWrite(nLevel);
pLevelData->resize(levelSizes[nLevel]);
copy(in.begin() + cur,
in.begin() + cur + levelSizes[nLevel],
pLevelData->begin());
unshiftBytes(pLevelData, ver);
cur += levelSizes[nLevel];
}
// Chunks
if (cur + 2 > sz) {
pMsg->assign("Not enough data reading number of chunks.");
return false;
}
int numChunks = getInt2(in.begin() + cur);
cur += 2;
if (cur + (24 * numChunks) > sz) {
pMsg->assign("Not enough data reading chunk table.");
return false;
}
vector<int> chunkCompressedSizes, chunkUncompressedSizes, chunkOffsets;
vector<string> chunkNames;
chunkCompressedSizes.resize(numChunks);
chunkUncompressedSizes.resize(numChunks);
chunkOffsets.resize(numChunks);
chunkNames.resize(numChunks);
int nChunk;
for (nChunk = 0; nChunk < numChunks; nChunk++) {
ByteVec chunkTableEntry;
chunkTableEntry.resize(24);
copy(in.begin() + cur, in.begin() + cur + 24,
chunkTableEntry.begin());
cur += 24;
for (int i = 0; i < 24; i += 4) {
unscrambleChunkTableData(chunkTableEntry.begin() + i);
}
chunkCompressedSizes[nChunk] = getInt4(chunkTableEntry.begin() + 0);
chunkUncompressedSizes[nChunk] = getInt4(chunkTableEntry.begin() + 4);
chunkOffsets[nChunk] = getInt4(chunkTableEntry.begin() + 8);
string &chunkName = chunkNames[nChunk];
for (int nChar = 0; nChar < 12; nChar++) {
char ch = chunkTableEntry[12 + nChar];
if ((int)chunkName.size() == nChar) {
if (ch != 0x00) {
chunkName.append(1, ch);
}
} else {
if (ch != 0x00) {
pMsg->assign("Chunk name has non-null byte after null byte.");
return false;
}
}
}
if (pDatFile->getChunk(chunkName)) {
pMsg->assign("Duplicate chunk name.");
return false;
}
pDatFile->addChunk(chunkName);
}
int chunkOffset = 2 + (24 * numChunks);
for (nChunk = 0; nChunk < numChunks; nChunk++) {
if (chunkOffset != chunkOffsets[nChunk]) {
pMsg->assign("Unexpected chunk starting point.");
return false;
}
int compressedSize = chunkCompressedSizes[nChunk];
if (cur + compressedSize > sz) {
pMsg->assign("Not enough data reading chunk.");
return false;
}
ByteVec compressedChunk;
compressedChunk.resize(compressedSize);
copy(in.begin() + cur, in.begin() + cur + compressedSize,
compressedChunk.begin());
cur += compressedSize;
chunkOffset += compressedSize;
const string &chunkName = chunkNames[nChunk];
int uncompressedSize = chunkUncompressedSizes[nChunk];
ByteVec &uncompressedChunk = *pDatFile->getChunkForWrite(chunkName);
uncompressedChunk.resize(uncompressedSize);
if (!uncompressChunk(compressedChunk, &uncompressedChunk, pMsg)) {
return false;
}
}
if (cur < sz) {
pMsg->assign("Extra data after reading chunks.");
return false;
}
pDatFile->setInit(true);
return true;
}
namespace
{
bool compressChunk(const ByteVec &in,
ByteVec *pOut,
string *pMsg)
{
string msg;
if (!pMsg) {
pMsg = &msg;
}
ByteVec out;
// We could do some real compression here instead.
out.resize(in.size());
copy(in.begin(), in.end(), out.begin());
pOut->resize(out.size());
copy(out.begin(), out.end(), pOut->begin());
return true;
}
}
bool unparseDatFile(const DatFile &datFile,
ByteVec *pOut,
string *pMsg)
{
string msg;
if (!pMsg) {
pMsg = &msg;
}
if (!datFile.getInit()) {
pMsg->assign("DatFile not initialized.");
return false;
}
ByteVec out;
out.clear();
int cur = 0;
out.resize(out.size() + 600 + 4 + 4 + 400);
const ByteVec &credits = datFile.getCredits();
if (credits.size() != 600) {
pMsg->assign("Credits must be 600 bytes.");
return false;
}
copy(credits.begin(), credits.end(), out.begin() + cur);
cur += 600;
int levelSizeTotal = 0;
int nLevel;
for (nLevel = 0; nLevel < 200; nLevel++) {
levelSizeTotal += datFile.getLevel(nLevel).size();
}
putInt4(out.begin() + cur, 4 + 4 + 400 + levelSizeTotal);
cur += 4;
const ByteVec &codes = datFile.getCodes();
if (codes.size() != 4) {
pMsg->assign("Codes must be 4 bytes.");
return false;
}
copy(codes.begin(), codes.end(), out.begin() + cur);
cur += 4;
for (nLevel = 0; nLevel < 200; nLevel++) {
putInt2(out.begin() + cur, datFile.getLevel(nLevel).size());
cur += 2;
}
out.resize(out.size() + levelSizeTotal);
for (nLevel = 0; nLevel < 200; nLevel++) {
const ByteVec &level = datFile.getLevel(nLevel);
ByteVec encodedLevel;
encodedLevel.resize(level.size());
copy(level.begin(), level.end(),
encodedLevel.begin());
shiftBytes(&encodedLevel, datFile.getVersion());
copy(encodedLevel.begin(), encodedLevel.end(),
out.begin() + cur);
cur += level.size();
}
// Chunks
set<string> chunkNameSet;
datFile.getChunkNames(&chunkNameSet);
int numChunks = chunkNameSet.size();
vector<string> chunkNames;
vector<ByteVec> compressedChunks;
chunkNames.resize(numChunks);
compressedChunks.resize(numChunks);
int nChunk = 0;
set<string>::const_iterator chunkIter = chunkNameSet.begin();
set<string>::const_iterator chunkEnd = chunkNameSet.end();
for (; chunkIter != chunkEnd; ++chunkIter) {
const string &chunkName = *chunkIter;
chunkNames[nChunk] = chunkName;
if (!compressChunk(*datFile.getChunk(chunkName),
&compressedChunks[nChunk],
pMsg)) {
return false;
}
nChunk++;
}
out.resize(out.size() + 2 + (24 * numChunks));
putInt2(out.begin() + cur, numChunks);
cur += 2;
int chunkOffset = 2 + (24 * numChunks);
for (nChunk = 0; nChunk < numChunks; nChunk++) {
ByteVec chunkTableEntry;
chunkTableEntry.resize(24);
const string &chunkName = chunkNames[nChunk];
int uncompressedSize = datFile.getChunk(chunkName)->size();
int compressedSize = compressedChunks[nChunk].size();
putInt4(chunkTableEntry.begin(), compressedSize);
putInt4(chunkTableEntry.begin() + 4, uncompressedSize);
putInt4(chunkTableEntry.begin() + 8, chunkOffset);
if (chunkName.size() > 12) {
pMsg->assign("Chunk name too long.");
return false;
}
for (int nChar = 0; nChar < 12; nChar++) {
char ch = 0x00;
if (nChar < (int)chunkName.size()) {
ch = chunkName[nChar];
}
chunkTableEntry[12 + nChar] = ch;
}
for (int i = 0; i < 24; i += 4) {
scrambleChunkTableData(chunkTableEntry.begin() + i);
}
copy(chunkTableEntry.begin(), chunkTableEntry.end(), out.begin() + cur);
cur += 24;
chunkOffset += compressedSize;
}
for (nChunk = 0; nChunk < numChunks; nChunk++) {
const ByteVec &compressedChunk = compressedChunks[nChunk];
int compressedSize = compressedChunk.size();
out.resize(out.size() + compressedSize);
copy(compressedChunk.begin(),
compressedChunk.end(),
out.begin() + cur);
cur += compressedSize;
}
if (cur != (int)out.size()) {
pMsg->assign("Error computing size of unparsed data file.");
return false;
}
pOut->clear();
pOut->resize(out.size());
copy(out.begin(), out.end(), pOut->begin());
return true;
}
}

View File

@@ -0,0 +1,84 @@
// Copyright 2003 Jeremy Sawicki
//
// This file is part of OxydLib.
//
// OxydLib is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// OxydLib is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with OxydLib; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#ifndef DATFILE_H
#define DATFILE_H
#include "VecUtils.h"
#include "OxydVersion.h"
#include <string>
#include <set>
#include <map>
namespace OxydLib {
class DatFile
{
public:
DatFile();
~DatFile();
void clear();
bool getInit() const { return m_bInit; }
void setInit(bool bInit) { m_bInit = bInit; }
OxydVersion getVersion() const { return m_ver; }
void setVersion(OxydVersion ver) { m_ver = ver; }
const ByteVec &getCredits() const { return m_credits; }
ByteVec *getCreditsForWrite() { return &m_credits; }
const ByteVec &getCodes() const { return m_codes; }
ByteVec *getCodesForWrite() { return &m_codes; }
const ByteVec &getLevel(int nLevel) const { return m_levels[nLevel]; }
ByteVec *getLevelForWrite(int nLevel) { return &m_levels[nLevel]; }
void getChunkNames(std::set<std::string> *pChunkNames) const;
void addChunk(const std::string &chunkName);
void removeChunk(const std::string &chunkName);
const ByteVec *getChunk(const std::string &chunkName) const;
ByteVec *getChunkForWrite(const std::string &chunkName);
private:
bool m_bInit;
OxydVersion m_ver;
ByteVec m_credits;
ByteVec m_codes;
std::vector<ByteVec> m_levels;
typedef std::map<std::string, ByteVec> ChunkMap;
ChunkMap m_chunks;
};
bool parseDatFile(const ByteVec &in,
OxydVersion ver,
DatFile *pDatFile,
std::string *pMsg = 0);
bool unparseDatFile(const DatFile &datFile,
ByteVec *pOut,
std::string *pMsg = 0);
}
#endif

View File

@@ -0,0 +1,81 @@
// Copyright 2003 Jeremy Sawicki
//
// This file is part of OxydLib.
//
// OxydLib is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// OxydLib is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with OxydLib; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "FileUtils.h"
#include <stdio.h>
namespace OxydLib {
using namespace std;
bool readFile(const string &fileName, ByteVec *pBuf)
{
pBuf->clear();
FILE *inFile = fopen(fileName.c_str(), "rb");
if (!inFile) {
return false;
}
while (!feof(inFile)) {
unsigned char tmpBuf[65536];
int count = fread(tmpBuf,
sizeof(unsigned char),
65536,
inFile);
if (count == 0) {
fclose(inFile);
return false;
}
int ii;
for (ii = 0; ii < count; ii++) {
pBuf->push_back(tmpBuf[ii]);
}
}
fclose(inFile);
return true;
}
bool writeFile(const string &fileName, const ByteVec &data)
{
FILE *outFile = fopen(fileName.c_str(), "wb");
if (!outFile) {
return false;
}
int count = fwrite(&data[0], //.begin(),
sizeof(unsigned char),
data.size(),
outFile);
if (count != (int)data.size()) {
fclose(outFile);
return false;
}
fclose(outFile);
return true;
}
}

View File

@@ -0,0 +1,34 @@
// Copyright 2003 Jeremy Sawicki
//
// This file is part of OxydLib.
//
// OxydLib is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// OxydLib is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with OxydLib; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#ifndef FILEUTILS_H
#define FILEUTILS_H
#include "VecUtils.h"
#include <string>
namespace OxydLib {
using std::string;
bool readFile(const string &fileName, ByteVec *pBuffer);
bool writeFile(const string &fileName, const ByteVec &data);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,482 @@
// Copyright 2003 Jeremy Sawicki
//
// This file is part of OxydLib.
//
// OxydLib is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// OxydLib is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with OxydLib; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#ifndef LEVEL_H
#define LEVEL_H
#include "VecUtils.h"
#include <string>
#include <set>
#include <map>
namespace OxydLib {
// using std::string;
// using std::set;
// using std::map;
enum Language
{
Language_Invalid = -1,
Language_First = 0,
Language_German = Language_First,
Language_English,
Language_French,
Language_International,
Language_Count,
Language_Last = Language_Count - 1
};
enum GameMode
{
GameMode_Invalid = -1,
GameMode_First = 0,
GameMode_Hard = GameMode_First,
GameMode_Easy,
GameMode_Count,
GameMode_Last = GameMode_Count - 1
};
enum GridType
{
GridType_Invalid = -1,
GridType_First = 0,
GridType_Surfaces = GridType_First,
GridType_Pieces,
GridType_Objects,
GridType_Count,
GridType_Last = GridType_Count - 1
};
enum MarbleType
{
MarbleType_Invalid = -1,
MarbleType_First = 0,
MarbleType_Black = MarbleType_First,
MarbleType_White,
MarbleType_Meditation,
MarbleType_Horse,
MarbleType_Jack,
MarbleType_LifeSpitter,
MarbleType_DynamiteHolder,
MarbleType_Rotor, /* Oxyd 1 */
MarbleType_Bug, /* Oxyd 1 */
MarbleType_Count,
MarbleType_Last = MarbleType_Count - 1
};
class Marble
{
public:
Marble();
~Marble();
MarbleType getMarbleType() const { return m_marbleType; }
void setMarbleType(MarbleType marbleType) { m_marbleType = marbleType; }
unsigned int getX() const { return m_x; }
void setX(unsigned int x) { m_x = x; }
unsigned int getY() const { return m_y; }
void setY(unsigned int y) { m_y = y; }
const std::string &getData(GameMode gameMode) const { return m_data[gameMode]; }
std::string *getDataForWrite(GameMode gameMode) { return &m_data[gameMode]; }
private:
MarbleType m_marbleType;
unsigned int m_x;
unsigned int m_y;
std::string m_data[GameMode_Count];
};
class RubberBand
{
public:
RubberBand();
~RubberBand();
int getNaturalLength() const { return m_naturalLength; }
void setNaturalLength(int naturalLength) { m_naturalLength = naturalLength; }
int getForce() const { return m_force; }
void setForce(int force) { m_force = force; }
int getFirstEndMarble() const { return m_firstEndMarble; }
void setFirstEndMarble(int nMarble) { m_firstEndMarble = nMarble; }
bool isSecondEndMarble() const { return m_bSecondEndIsMarble; }
int getSecondEndMarble() const { return m_secondEndMarble; }
void setSecondEndMarble(int nMarble);
unsigned int getSecondEndPieceX() const { return m_secondEndPieceX; }
unsigned int getSecondEndPieceY() const { return m_secondEndPieceY; }
void setSecondEndPiece(unsigned int x, unsigned int y);
bool operator == (const RubberBand &other) const;
bool operator != (const RubberBand &other) const;
private:
int m_naturalLength;
int m_force;
int m_firstEndMarble;
bool m_bSecondEndIsMarble;
int m_secondEndMarble;
unsigned int m_secondEndPieceX;
unsigned int m_secondEndPieceY;
};
class Block
{
public:
Block();
Block(unsigned int x, unsigned int y);
~Block();
unsigned int getX() const { return m_x; }
void setX(unsigned int x) { m_x = x; }
unsigned int getY() const { return m_y; }
void setY(unsigned int y) { m_y = y; }
bool operator < (const Block &other) const;
bool operator == (const Block &other) const;
bool operator != (const Block &other) const;
private:
unsigned int m_x;
unsigned int m_y;
};
enum Direction
{
Direction_Invalid = -1,
Direction_First = 0,
Direction_Up = Direction_First,
Direction_Down,
Direction_Left,
Direction_Right,
Direction_Count,
Direction_Last = Direction_Count - 1
};
class ScrambleItem
{
public:
ScrambleItem();
ScrambleItem(unsigned int x, unsigned int y, Direction dir);
~ScrambleItem();
unsigned int getX() const { return m_x; }
void setX(unsigned int x) { m_x = x; }
unsigned int getY() const { return m_y; }
void setY(unsigned int y) { m_y = y; }
Direction getDir() const { return m_dir; }
void setDir(Direction dir) { m_dir = dir; }
private:
unsigned int m_x;
unsigned int m_y;
Direction m_dir;
};
class Laser
{
public:
Laser();
Laser(Direction dir, bool bOn);
~Laser();
Direction getDir() const { return m_dir; }
void setDir(Direction dir) { m_dir = dir; }
bool getOn() const { return m_bOn; }
void setOn(bool bOn) { m_bOn = bOn; }
bool operator == (const Laser &other) const;
bool operator != (const Laser &other) const;
private:
Direction m_dir;
bool m_bOn;
};
class Oscillator
{
public:
Oscillator();
Oscillator(unsigned int period, bool bOn);
~Oscillator();
unsigned int getPeriod() const { return m_period; }
void setPeriod(unsigned int period) { m_period = period; }
bool getOn() const { return m_bOn; }
void setOn(bool bOn) { m_bOn = bOn; }
bool operator == (const Oscillator &other) const;
bool operator != (const Oscillator &other) const;
private:
unsigned int m_period;
bool m_bOn;
};
typedef std::map<Block, Oscillator> OscillatorMap;
class SignalLocation
{
public:
SignalLocation();
SignalLocation(unsigned int x, unsigned int y, GridType gridType);
~SignalLocation();
unsigned int getX() const { return m_x; }
void setX(unsigned int x) { m_x = x; }
unsigned int getY() const { return m_y; }
void setY(unsigned int y) { m_y = y; }
GridType getGridType() const { return m_gridType; }
void setGridType(GridType gridType) { m_gridType = gridType; }
bool operator < (const SignalLocation &other) const;
bool operator == (const SignalLocation &other) const;
bool operator != (const SignalLocation &other) const
{ return !(*this == other); }
private:
unsigned int m_x;
unsigned int m_y;
GridType m_gridType;
};
class Grid
{
public:
Grid();
Grid(int width, int height);
~Grid();
unsigned int getWidth() const { return m_width; }
unsigned int getHeight() const { return m_height; }
private:
friend class Level;
void resize(unsigned int width, unsigned int height);
public:
unsigned char get(unsigned int x, unsigned int y) const;
void set(unsigned int x, unsigned int y, unsigned char val);
private:
unsigned int m_width;
unsigned int m_height;
ByteVec m_data;
};
class Level
{
public:
Level();
~Level();
void clear();
bool getInit() const { return m_bInit; }
void setInit(bool bInit) { m_bInit = bInit; }
bool isEmpty() const { return m_bEmpty; }
void setEmpty(bool bEmpty) { m_bEmpty = bEmpty; }
unsigned int getWidth() const { return m_width; }
unsigned int getHeight() const { return m_height; }
void resize(unsigned int width, unsigned int height);
bool getMeditation() const { return m_bMeditation; }
void setMeditation(bool bMeditation) { m_bMeditation = bMeditation; }
bool getHarmlessMeditationMarbles() const
{ return m_bHarmlessMeditationMarbles; }
void setHarmlessMeditationMarbles(bool bHarmlessMeditationMarbles)
{ m_bHarmlessMeditationMarbles = bHarmlessMeditationMarbles; }
size_t getNumMarbles() const { return m_marbles.size(); }
void setNumMarbles(int num) { m_marbles.resize(num); }
const Marble &getMarble(int nMarble) const { return m_marbles[nMarble]; }
Marble *getMarbleForWrite(int nMarble) { return &m_marbles[nMarble]; }
int getNumRubberBands(GameMode gameMode) const;
const RubberBand &getRubberBand(GameMode gameMode, int nRubberBand) const;
RubberBand *getRubberBandForWrite(GameMode gameMode, int nRubberBand);
void addRubberBand(GameMode gameMode,
const RubberBand &rubberBand,
int nRubberBand = -1);
void removeRubberBand(GameMode gameMode, int nRubberBand);
int getBlackRubberBandPieceNaturalLength(GameMode gameMode) const;
void setBlackRubberBandPieceNaturalLength(GameMode gameMode,
int naturalLength);
int getBlackRubberBandPieceForce(GameMode gameMode) const;
void setBlackRubberBandPieceForce(GameMode gameMode, int force);
int getWhiteRubberBandPieceNaturalLength(GameMode gameMode) const;
void setWhiteRubberBandPieceNaturalLength(GameMode gameMode,
int naturalLength);
int getWhiteRubberBandPieceForce(GameMode gameMode) const;
void setWhiteRubberBandPieceForce(GameMode gameMode, int force);
int getRubberBandObjectNaturalLength(GameMode gameMode) const;
void setRubberBandObjectNaturalLength(GameMode gameMode, int naturalLength);
int getRubberBandObjectForce(GameMode gameMode) const;
void setRubberBandObjectForce(GameMode gameMode, int force);
int getBlackRubberBandObjectMarble() const;
void setBlackRubberBandObjectMarble(int nMarble);
int getWhiteRubberBandObjectMarble() const;
void setWhiteRubberBandObjectMarble(int nMarble);
bool getRequireMagicPiece() const
{ return m_bRequireMagicPiece; }
void setRequireMagicPiece(bool bRequireMagicPiece)
{ m_bRequireMagicPiece = bRequireMagicPiece; }
bool getScrolling() const { return m_bScrolling; }
void setScrolling(bool bScrolling) { m_bScrolling = bScrolling; }
bool getReset(GameMode gameMode) const
{ return m_bReset[gameMode]; }
void setReset(GameMode gameMode, bool bReset)
{ m_bReset[gameMode] = bReset; }
bool getWalkThroughPuzzle() const
{ return m_bWalkThroughPuzzle; }
void setWalkThroughPuzzle(bool bWalkThroughPuzzle)
{ m_bWalkThroughPuzzle = bWalkThroughPuzzle; }
int getFlatForce(GameMode gameMode) const
{ return m_flatForce[gameMode]; }
void setFlatForce(GameMode gameMode, int flatForce)
{ m_flatForce[gameMode] = flatForce; }
int getSlopeForce(GameMode gameMode) const
{ return m_slopeForce[gameMode]; }
void setSlopeForce(GameMode gameMode, int slopeForce)
{ m_slopeForce[gameMode] = slopeForce; }
int getFriction(GameMode gameMode) const
{ return m_friction[gameMode]; }
void setFriction(GameMode gameMode, int friction)
{ m_friction[gameMode] = friction; }
int getNumScrambleItems() const;
const ScrambleItem &getScrambleItem(int nScrambleItem) const;
ScrambleItem *getScrambleItemForWrite(int nScrambleItem);
void addScrambleItem(const ScrambleItem &scrambleItem,
int nScrambleItem = -1);
void removeScrambleItem(int nScrambleItem);
const Laser &getLaser(int nLaser) const;
void setLaser(int nLaser, const Laser &laser);
const OscillatorMap &getOscillators(GameMode gameMode) const;
OscillatorMap *getOscillatorsForWrite(GameMode gameMode);
const std::string &getNoteText(int nNote, Language lang) const;
void setNoteText(int nNote, Language lang, const std::string &noteText);
const Grid &getGrid(GridType gridType) const { return m_grids[gridType]; }
Grid *getGridForWrite(GridType gridType) { return &m_grids[gridType]; }
const std::vector<std::string> &getSpecialItems() const { return m_specialItems; }
std::vector<std::string> *getSpecialItemsForWrite() { return &m_specialItems; }
void getSenders(std::set<SignalLocation> *pSenders) const;
int getNumRecipients(const SignalLocation &sender) const;
const SignalLocation &getRecipient(const SignalLocation &sender,
int nRecipient) const;
void setRecipient(const SignalLocation &sender,
int nRecipient,
const SignalLocation &recipient);
void addRecipient(const SignalLocation &sender,
const SignalLocation &recipient,
int nRecipient = -1);
void removeRecipient(const SignalLocation &sender,
int nRecipient);
private:
bool m_bInit;
bool m_bEmpty;
unsigned int m_width;
unsigned int m_height;
bool m_bMeditation;
bool m_bHarmlessMeditationMarbles;
std::vector<Marble> m_marbles;
std::vector<RubberBand> m_rubberBands[GameMode_Count];
int m_blackRubberBandPieceNaturalLength[GameMode_Count];
int m_blackRubberBandPieceForce[GameMode_Count];
int m_whiteRubberBandPieceNaturalLength[GameMode_Count];
int m_whiteRubberBandPieceForce[GameMode_Count];
int m_rubberBandObjectNaturalLength[GameMode_Count];
int m_rubberBandObjectForce[GameMode_Count];
int m_blackRubberBandObjectMarble;
int m_whiteRubberBandObjectMarble;
bool m_bRequireMagicPiece;
bool m_bScrolling;
bool m_bReset[GameMode_Count];
bool m_bWalkThroughPuzzle;
int m_flatForce[GameMode_Count];
int m_slopeForce[GameMode_Count];
int m_friction[GameMode_Count];
std::vector<ScrambleItem> m_scrambleItems;
Laser m_lasers[3];
OscillatorMap m_oscillators[GameMode_Count];
std::string m_noteText[2][Language_Count];
Grid m_grids[GridType_Count];
std::vector<std::string> m_specialItems;
typedef std::map<SignalLocation, std::vector<SignalLocation> > SignalMap;
SignalMap m_signals;
};
bool parseNumberList(const std::string &str, std::vector<int> *pNumberList);
bool parseLevel(const ByteVec &in, Level *pLevel, std::string *pMsg = 0);
bool unparseLevel(const Level &level, ByteVec *pOut, std::string *pMsg = 0);
}
#endif

View File

@@ -0,0 +1,41 @@
// Copyright 2003 Jeremy Sawicki
//
// This file is part of OxydLib.
//
// OxydLib is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// OxydLib is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with OxydLib; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#ifndef OXYDVERSION_H
#define OXYDVERSION_H
namespace OxydLib {
enum OxydVersion
{
OxydVersion_Invalid = -1,
OxydVersion_First = 0,
OxydVersion_Oxyd1 = OxydVersion_First,
OxydVersion_OxydMagnum,
OxydVersion_OxydMagnumGold,
OxydVersion_PerOxyd,
OxydVersion_OxydExtra,
OxydVersion_Count,
OxydVersion_Last = OxydVersion_Count - 1
};
}
#endif

View File

@@ -0,0 +1,27 @@
General information
-------------------
OxydLib is a C++ library for reading and writing the data files
used by the Oxyd series of games by Dongleware. It is still a
work in progress. Some parts of the data files aren't properly
handled yet.
OxydLib was written by Jeremy Sawicki (jeremy AT sawicki DOT us).
Copying
-------
OxydLib is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
OxydLib is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OxydLib; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

View File

@@ -0,0 +1,4 @@
This directory contains a slightly modified version of Jeremy Sawicki's
oxydlib. The original version can be downloaded from
http://www.sawicki.us/oxyd/.

View File

@@ -0,0 +1,79 @@
// Copyright 2003 Jeremy Sawicki
//
// This file is part of OxydLib.
//
// OxydLib is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// OxydLib is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with OxydLib; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "VecUtils.h"
namespace OxydLib {
unsigned int getInt2(ByteVec::const_iterator it)
{
return (((unsigned int)(*it)) << 8) |
(((unsigned int)(*(it + 1))));
}
unsigned int getInt4(ByteVec::const_iterator it)
{
return (((unsigned int)(*it)) << 24) |
(((unsigned int)(*(it + 1))) << 16) |
(((unsigned int)(*(it + 2))) << 8) |
(((unsigned int)(*(it + 3))));
}
void putInt2(ByteVec::iterator it, unsigned int ii)
{
*it = (unsigned char)((ii & 0xff00) >> 8);
*(it + 1) = (unsigned char)((ii & 0x00ff));
}
void putInt4(ByteVec::iterator it, unsigned int ii)
{
*it = (unsigned char)((ii & 0xff000000) >> 24);
*(it + 1) = (unsigned char)((ii & 0x00ff0000) >> 16);
*(it + 2) = (unsigned char)((ii & 0x0000ff00) >> 8);
*(it + 3) = (unsigned char)((ii & 0x000000ff));
}
unsigned int getInt2Reversed(ByteVec::const_iterator it)
{
return (((unsigned int)(*it))) |
(((unsigned int)(*(it + 1))) << 8);
}
unsigned int getInt4Reversed(ByteVec::const_iterator it)
{
return (((unsigned int)(*it))) |
(((unsigned int)(*(it + 1))) << 8) |
(((unsigned int)(*(it + 2))) << 16) |
(((unsigned int)(*(it + 3))) << 24);
}
void putInt2Reversed(ByteVec::iterator it, unsigned int ii)
{
*it = (unsigned char)((ii & 0x00ff));
*(it + 1) = (unsigned char)((ii & 0xff00) >> 8);
}
void putInt4Reversed(ByteVec::iterator it, unsigned int ii)
{
*it = (unsigned char)((ii & 0x000000ff));
*(it + 1) = (unsigned char)((ii & 0x0000ff00) >> 8);
*(it + 2) = (unsigned char)((ii & 0x00ff0000) >> 16);
*(it + 3) = (unsigned char)((ii & 0xff000000) >> 24);
}
}

View File

@@ -0,0 +1,42 @@
// Copyright 2003 Jeremy Sawicki
//
// This file is part of OxydLib.
//
// OxydLib is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// OxydLib is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with OxydLib; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#ifndef VECUTILS_H
#define VECUTILS_H
#include <vector>
namespace OxydLib {
typedef std::vector<unsigned char> ByteVec;
unsigned int getInt2(ByteVec::const_iterator it);
unsigned int getInt4(ByteVec::const_iterator it);
void putInt2(ByteVec::iterator it, unsigned int ii);
void putInt4(ByteVec::iterator it, unsigned int ii);
unsigned int getInt2Reversed(ByteVec::const_iterator it);
unsigned int getInt4Reversed(ByteVec::const_iterator it);
void putInt2Reversed(ByteVec::iterator it, unsigned int ii);
void putInt4Reversed(ByteVec::iterator it, unsigned int ii);
}
#endif

View File

@@ -0,0 +1,7 @@
Main author: Thomas Sondergaard (thomass@deltadata.dk)
Windows support: Kevin Shea (kevin.shea@d-cubed.co.uk)
Bug fixes and test suite: Kirk Klobe (kirkk@visi.com)
The files zipios++/directory.h and zipios++/directory.cpp originate
from the dir_it library written by Dietmar Kuehl (it's available for
download at http://www.boost.org)

View File

@@ -0,0 +1,515 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations
below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
^L
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it
becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
^L
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control
compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
^L
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
^L
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
^L
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
^L
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply, and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License
may add an explicit geographical distribution limitation excluding those
countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
^L
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
^L
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms
of the ordinary General Public License).
To apply these terms, attach the following notices to the library.
It is safest to attach them to the start of each source file to most
effectively convey the exclusion of warranty; and each file should
have at least the "copyright" line and a pointer to where the full
notice is found.
<one line to give the library's name and a brief idea of what it
does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper
mail.
You should also get your employer (if you work as a programmer) or
your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James
Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,182 @@
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
The file `configure.in' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment. Using
a Bourne-compatible shell, you can do that on the command line like
this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
Or on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
==================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`configure' also accepts some other, not widely useful, options.

View File

@@ -0,0 +1,64 @@
Release notes for Zipios++ 0.1.5
--------------------------------
New features:
- Support for Visual C++ 6
- VFS feature finished
- Support for writing zip archives (pre-beta!)
Bug fixes:
- Code reorganized and many minor bug fixes
Changes:
- flex/lex is no longer required
Release notes for Zipios++ 0.1.4
--------------------------------
Bug fixes:
- A bug in a code fragment used in all the test programs for copying
data from an istream to an ostream has been fixed
- A nasty and embarrasing bug in ZipInputStreambuf and
InflateInputStreambuf that prevented zip entries containing the character
255 from being correctly decompressed has been fixed
Release notes for Zipios++ 0.1.3
--------------------------------
Changes:
- Changed the license to GNU Lesser General Public License
Release notes for Zipios++ 0.1.2
--------------------------------
New features:
- ZipFile can now be used to read zip files embedded in other files. The
static method ZipFile::openEmbeddedZipFile() can be used to open zip
files embedded in another file with the binary appendzip, which is
also part of the Zipios++ distribution
Bug fixes:
Installation:
- Header files are now installed (under (usr/include/)zipios++/)
- The library libzipios.a is now installed
- The test binaries are no longer installed
- Renamed config.h to zipios-config.h to avoid file name collisions
Building:
- Added a switch --with-std-compliant-iostream (and --without-...)
to the configure script, such that the library can be build against
the old iostream.h library, even if a newer std compliant iostream
implementation is available in iostream
Source:
- Most functions now throw exceptions (reflected in the documentation)
instead of printing error messages to stderr
- Fixes to make the library compile and work with gcc 2.95.2
Missing features and known bugs:
- DirectoryCollection::entries() end DirectoryCollection::size() are
not implemented yet

View File

@@ -0,0 +1,81 @@
Introduction
------------
Zipios++ is a small C++ library for reading zip files. The structure
and public interface are based (somewhat loosely) on the java.util.zip
package. The streams created to access the individual entries in a zip
file are based on the standard iostream library.
Zipios++ also provides a way for an application to support files from
multiple sources (e.g. from zip files or from ordinary directories)
transparently.
The source code is released under the GNU Lesser General Public
License.
Installation (Unix)
-------------------
This software package uses autoconf/automake, so the fast installation
procedure is
./configure
make
make install
For details about installation of autoconfiscated packages refer to
the INSTALL file
'make install' installs the Zipios++ header files under
/usr/include/zipios++/ and the library libzipios.a under
/usr/lib/. You can choose another base path than /usr/ by using the
--prefix switch with configure. See the INSTALL file for
details. Running make also builds a number of test programs that
remain in the source directory zipios++/. The built example binaries
and the corresponding source code have names that start with test_ and
example_. These test programs demonstrate the most important features
in Zipios++.
Installation (Windows)
----------------------
Currently, makefiles are only provided for Visual C++, along with a
Developer Studio project. It is also planned to support Inprise and Gnu
compilers in the near future.
Before building, if zlib is not in a standard compiler path, the location of
its headers and .lib file must be defined at the top of win32\Makefile.com
To install, using the appropriate make program and one of the following
makefiles:
Makefile.vc5 - Visual C++ 5, 6
the procedure (for Visual C++) is
cd win32
nmake -f Makefile.vc5
To use the Developer Studio project, run configure.bat from win32 before
compiling. Again, a non-standard location for zlib must be defined in the
project settings before building.
No install options have been defined yet.
Status and Documentation
-------------
Please refer to the online documentation at
http://zipios.sourceforge.net. A printable version of the online
documentation is also available at the same URL. The documentation can
be automatically generated from the source if you have Doxygen
installed by running
./configure
make doc
Bugs
----
Submit bug reports and patches to thomass@deltadata.dk
Contributing
------------
If you're interested in helping with Zipios++ then drop me a note at
thomass@deltadata.dk.

View File

@@ -0,0 +1,117 @@
#ifndef BACKBUFFER_H
#define BACKBUFFER_H
#include "zipios++/zipios-config.h"
#include <algorithm>
#include "zipios++/meta-iostreams.h"
#include <vector>
#include "zipios++/fcollexceptions.h"
#include "zipios++/ziphead.h"
#include "zipios++/zipheadio.h"
#include "zipios++/virtualseeker.h"
#include "zipios_common.h"
namespace zipios {
using std::ios ;
using std::cerr ;
using std::endl ;
/** A BackBuffer instance is useful for reading the last part of a
file in an efficient manner, when it is not known exactly how far
back (towards the front!) to go, to find the start of the desired
data block. BackBuffer is a vector< unsigned char > that fills
itself with data from a file by reading chunks from the end of the
file progressing towards the start. Upon construction the
BackBuffer instance is associated with a file and a chunksize can
be specified. To read a chunk of the file into the BackBuffer call
readChunk(). */
class BackBuffer : public vector< unsigned char > {
public:
/** BackBuffer constructor.
@param is The istream to read the data from. The stream must be seekable,
as BackBuffer will reposition the file position to read chunks from the back
of the file.
@param chunk_size specifies the size of the chunks to read the file into
the BackBuffer in.
@throw FCollException Thrown if the VirtualSeeker vs that has been specified is
invalid for the istream is. */
inline explicit BackBuffer( istream &is, VirtualSeeker vs = VirtualSeeker(),
int chunk_size = 1024 ) ;
/** Reads another chunk and returns the size of the chunk that has
been read. Returns 0 on I/O failure.
@param read_pointer When a new chunk is read in the already
stored bytes change position in the BackBuffer. read_pointer is
assumed by readChunk() to be a pointer into a position in the
BackBuffer, and is updated to point to the same position in the file
as it pointed to before the new chunk was read. */
inline int readChunk( int &read_pointer ) ;
private:
VirtualSeeker _vs ;
int _chunk_size ;
istream &_is ;
streampos _file_pos ;
};
BackBuffer::BackBuffer( istream &is, VirtualSeeker vs, int chunk_size )
: _vs ( vs ),
_chunk_size( chunk_size ),
_is ( is )
{
_vs.vseekg( is, 0, ios::end ) ;
_file_pos = _vs.vtellg( is ) ;
// Only happens if _vs.startOffset() is a position
// in the file that lies after _vs.endOffset(), which
// is clearly not a valid situation.
if ( _file_pos < 0 )
throw FCollException( "Invalid virtual file endings" ) ;
}
int BackBuffer::readChunk( int &read_pointer ) {
// Update chunk_size and file position
_chunk_size = min<int> ( static_cast< int >( _file_pos ), _chunk_size ) ;
_file_pos -= _chunk_size ;
_vs.vseekg( _is, _file_pos, ios::beg ) ;
// Make space for _chunk_size new bytes first in buffer
insert ( begin(), _chunk_size, static_cast< char > ( 0 ) ) ;
// Read in the next _chunk_size of bytes
readByteSeq ( _is, &( (*this)[ 0 ] ), _chunk_size ) ;
read_pointer += _chunk_size ;
if ( _is.good() )
return _chunk_size ;
else
return 0 ;
}
}
#endif
/** \file
The header file for BackBuffer
*/
/*
Zipios++ - a small C++ library that provides easy access to .zip files.
Copyright (C) 2000 Thomas Søndergaard
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -0,0 +1,163 @@
#include "zipios++/zipios-config.h"
#include <assert.h>
#include "zipios++/meta-iostreams.h"
#include <string>
#include "zipios_common.h"
#include "zipios++/basicentry.h"
#include "zipios++/zipios_defs.h"
#include "outputstringstream.h"
namespace zipios {
using std::ifstream ;
using std::ios ;
//
// Public definitions
//
BasicEntry::BasicEntry( const string &filename, const string &comment,
const FilePath &basepath )
: _filename ( filename ),
_comment ( comment ),
_basepath ( basepath )
{
string full_path = _basepath + _filename ;
ifstream is( full_path.c_str(), ios::in | ios::binary ) ;
if ( ! is ) {
_valid = false ;
} else {
is.seekg( 0, ios::end ) ;
_size = is.tellg() ;
is.close() ;
_valid = true ;
}
}
string BasicEntry::getComment() const {
return _comment ;
}
uint32 BasicEntry::getCompressedSize() const {
return getSize() ;
}
uint32 BasicEntry::getCrc() const {
return 0 ;
}
vector< unsigned char > BasicEntry::getExtra() const {
return vector< unsigned char > () ;
}
StorageMethod BasicEntry::getMethod() const {
return STORED ;
}
string BasicEntry::getName() const {
return _filename ;
}
string BasicEntry::getFileName() const {
if ( isDirectory() )
return string() ;
string::size_type pos ;
pos = _filename.find_last_of( separator ) ;
if ( pos != string::npos ) { // separator found!
// isDirectory() check means pos should not be last, so pos+1 is ok
return _filename.substr(pos + 1) ;
} else {
return _filename ;
}
}
uint32 BasicEntry::getSize() const {
return _size ;
}
int BasicEntry::getTime() const {
return 0 ; // FIXME later
}
bool BasicEntry::isValid() const {
return _valid ;
}
// virtual int hashCode() const {}
bool BasicEntry::isDirectory() const {
assert( _filename.size() != 0 ) ;
return _filename[ _filename.size() - 1 ] == separator ;
}
void BasicEntry::setComment( const string &comment ) {
_comment = comment ;
}
void BasicEntry::setCompressedSize( uint32 size ) {
}
void BasicEntry::setCrc( uint32 crc ) {
}
void BasicEntry::setExtra( const vector< unsigned char > &extra ) {
}
void BasicEntry::setMethod( StorageMethod method ) {
}
void BasicEntry::setName( const string &name ) {
_filename = name ;
}
void BasicEntry::setSize( uint32 size ) {
_size = size ;
}
void BasicEntry::setTime( int time ) {
}
string BasicEntry::toString() const {
OutputStringStream sout ;
sout << _filename << " (" << _size << " bytes)" ;
return sout.str() ;
}
FileEntry *BasicEntry::clone() const {
return new BasicEntry( *this ) ;
}
BasicEntry::~BasicEntry() {
}
} // namespace
/** \file
Implementation of BasicEntry.
*/
/*
Zipios++ - a small C++ library that provides easy access to .zip files.
Copyright (C) 2000 Thomas Søndergaard
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -0,0 +1,162 @@
#include "zipios++/zipios-config.h"
#include "zipios++/meta-iostreams.h"
#include "zipios++/collcoll.h"
#include "zipios_common.h"
namespace zipios {
using std::ifstream ;
CollectionCollection *CollectionCollection::_inst = 0 ;
CollectionCollection::CollectionCollection() {
_valid = true ; // we're valid even though we are empty!
}
bool CollectionCollection::addCollection( const FileCollection &collection ) {
if ( ! _valid )
throw InvalidStateException( "Attempt to add a FileCollection to an invalid CollectionCollection" ) ;
if ( this == &collection || ! collection.isValid() )
return false ;
_collections.push_back( collection.clone() ) ;
return true ;
}
bool CollectionCollection::addCollection( FileCollection *collection ) {
if ( ! _valid )
throw InvalidStateException( "Attempt to add a FileCollection to an invalid CollectionCollection" ) ;
if ( collection == 0 || this == collection || ! collection->isValid() )
return false ;
_collections.push_back( collection ) ;
return true ;
}
void CollectionCollection::close() {
_valid = false ;
}
ConstEntries CollectionCollection::entries() const {
if ( ! _valid )
throw InvalidStateException( "Attempt to get entries from an invalid CollectionCollection" ) ;
ConstEntries all_entries ;
std::vector< FileCollection * >::const_iterator it ;
for ( it = _collections.begin() ; it != _collections.end() ; it++ )
all_entries += (*it)->entries() ;
return all_entries ;
}
ConstEntryPointer CollectionCollection::getEntry( const string &name,
MatchPath matchpath ) const {
if ( ! _valid )
throw InvalidStateException( "Attempt to get an entry from an invalid CollectionCollection" ) ;
// Returns the first matching entry.
std::vector< FileCollection * >::const_iterator it ;
ConstEntryPointer cep ;
getEntry( name, cep, it, matchpath ) ;
return cep ;
}
istream *CollectionCollection::getInputStream( const ConstEntryPointer &entry ) {
if ( ! _valid )
throw InvalidStateException( "Attempt to get an input stream from an invalid CollectionCollection" ) ;
return getInputStream( entry->getName() ) ;
}
istream *CollectionCollection::getInputStream( const string &entry_name,
MatchPath matchpath ) {
if ( ! _valid )
throw InvalidStateException( "Attempt to get an input stream from an invalid CollectionCollection" ) ;
std::vector< FileCollection * >::const_iterator it ;
ConstEntryPointer cep ;
getEntry( entry_name, cep, it, matchpath ) ;
if ( cep == 0 )
return 0 ;
else
return (*it)->getInputStream( entry_name ) ;
}
int CollectionCollection::size() const {
if ( ! _valid )
throw InvalidStateException( "Attempt to get the size of an invalid CollectionCollection" ) ;
int sz = 0 ;
std::vector< FileCollection * >::const_iterator it ;
for ( it = _collections.begin() ; it != _collections.end() ; it++ )
sz += (*it)->size() ;
return sz ;
}
FileCollection *CollectionCollection::clone() const {
return new CollectionCollection( *this ) ;
}
CollectionCollection::~CollectionCollection() {
std::vector< FileCollection * >::iterator it ;
for ( it = _collections.begin() ; it != _collections.end() ; ++it )
delete *it ;
}
//
// Protected member functions
//
void CollectionCollection::getEntry( const string &name,
ConstEntryPointer &cep,
std::vector< FileCollection * >::const_iterator &it,
MatchPath matchpath ) const {
// Returns the first matching entry.
cep = 0 ;
for ( it = _collections.begin() ; it != _collections.end() ; it++ ) {
cep = (*it)->getEntry( name, matchpath ) ;
if ( cep )
break ;
}
}
} // namespace
/** \file
Implementation of CollectionCollection.
*/
/*
Zipios++ - a small C++ library that provides easy access to .zip files.
Copyright (C) 2000 Thomas Søndergaard
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -0,0 +1,224 @@
#include "zipios++/zipios-config.h"
#include "zipios++/meta-iostreams.h"
#include <zlib.h>
#include "zipios++/fcollexceptions.h"
#include "zipios++/deflateoutputstreambuf.h"
#include "outputstringstream.h"
namespace zipios {
using std::cerr ;
using std::endl ;
DeflateOutputStreambuf::DeflateOutputStreambuf( streambuf *outbuf, bool user_init,
bool del_outbuf )
: FilterOutputStreambuf( outbuf, del_outbuf ),
_zs_initialized ( false ),
_invecsize ( 1000 ),
_invec ( _invecsize ),
_outvecsize ( 1000 ),
_outvec ( _outvecsize )
{
// NOTICE: It is important that this constructor and the methods it
// calls doesn't do anything with the output streambuf _outbuf The
// reason is that this class can be subclassed, and the subclass
// should get a chance to write to the buffer first
// zlib init:
_zs.zalloc = Z_NULL ;
_zs.zfree = Z_NULL ;
_zs.opaque = Z_NULL ;
if ( user_init && ! init() )
cerr << "DeflateOutputStreambuf::reset() failed!\n" ; // FIXME: throw something
}
DeflateOutputStreambuf::~DeflateOutputStreambuf() {
closeStream() ;
}
// This method is called in the constructor, so it must not write
// anything to the output streambuf _outbuf (see notice in
// constructor)
bool DeflateOutputStreambuf::init( int comp_level ) {
static const int default_mem_level = 8 ;
// _zs.next_in and avail_in must be set according to
// zlib.h (inline doc).
_zs.next_in = reinterpret_cast< unsigned char * >( &( _invec[ 0 ] ) ) ;
_zs.avail_in = 0 ;
_zs.next_out = reinterpret_cast< unsigned char * >( &( _outvec[ 0 ] ) ) ;
_zs.avail_out = _outvecsize ;
int err ;
if( _zs_initialized ) { // just reset it
endDeflation() ;
err = deflateReset( &_zs ) ;
// FIXME: bug, for deflateReset we do not update the compression level
} else { // init it
err = deflateInit2( &_zs, comp_level, Z_DEFLATED, -MAX_WBITS,
default_mem_level, Z_DEFAULT_STRATEGY ) ;
/* windowBits is passed < 0 to tell that no zlib header should be
written. */
_zs_initialized = true ;
}
// streambuf init:
setp( &( _invec[ 0 ] ), &( _invec[ 0 ] ) + _invecsize ) ;
_crc32 = crc32( 0, Z_NULL, 0 ) ;
_overflown_bytes = 0 ;
if ( err == Z_OK )
return true ;
else
return false ;
}
bool DeflateOutputStreambuf::closeStream() {
int err = Z_OK ;
if( _zs_initialized ) {
endDeflation() ;
err = deflateEnd( &_zs ) ;
_zs_initialized = false ;
}
if ( err == Z_OK )
return true ;
else {
cerr << "DeflateOutputStreambuf::closeStream(): deflateEnd failed" ;
#ifdef HAVE_ZERROR
cerr << ": " << zError( err ) ;
#endif
cerr << endl ;
return false ;
}
}
int DeflateOutputStreambuf::overflow( int c ) {
_zs.avail_in = pptr() - pbase() ;
_zs.next_in = reinterpret_cast< unsigned char * >( &( _invec[ 0 ] ) ) ;
_crc32 = crc32( _crc32, _zs.next_in, _zs.avail_in ) ; // update crc32
_overflown_bytes += _zs.avail_in ;
_zs.next_out = reinterpret_cast< unsigned char * >( &( _outvec[ 0 ] ) ) ;
_zs.avail_out = _outvecsize ;
// Deflate until _invec is empty.
int err = Z_OK ;
while ( ( _zs.avail_in > 0 || _zs.avail_out == 0 ) && err == Z_OK ) {
if ( _zs.avail_out == 0 )
flushOutvec() ;
err = deflate( &_zs, Z_NO_FLUSH ) ;
}
flushOutvec() ;
// Update 'put' pointers
setp( &( _invec[ 0 ] ), &( _invec[ 0 ] ) + _invecsize ) ;
if( err != Z_OK && err != Z_STREAM_END ) {
#if defined (HAVE_STD_IOSTREAM) && defined (USE_STD_IOSTREAM)
// Throw an exception to make istream set badbit
OutputStringStream msgs ;
msgs << "Deflation failed" ;
#ifdef HAVE_ZERROR
msgs << ": " << zError( err ) ;
#endif
throw IOException( msgs.str() ) ;
#endif
cerr << "Deflation failed\n" ;
return EOF ;
}
if ( c != EOF ) {
*pptr() = c ;
pbump( 1 ) ;
}
return 0 ;
}
int DeflateOutputStreambuf::sync() {
// FIXME: Do something
// return overflow() ;
return 0 ;
}
bool DeflateOutputStreambuf::flushOutvec() {
int deflated_bytes = _outvecsize - _zs.avail_out ;
int bc = _outbuf->sputn( &( _outvec[ 0 ] ), deflated_bytes ) ;
_zs.next_out = reinterpret_cast< unsigned char * >( &( _outvec[ 0 ] ) ) ;
_zs.avail_out = _outvecsize ;
return deflated_bytes == bc ;
}
void DeflateOutputStreambuf::endDeflation() {
overflow() ;
_zs.next_out = reinterpret_cast< unsigned char * >( &( _outvec[ 0 ] ) ) ;
_zs.avail_out = _outvecsize ;
// Deflate until _invec is empty.
int err = Z_OK ;
while ( err == Z_OK ) {
if ( _zs.avail_out == 0 )
flushOutvec() ;
err = deflate( &_zs, Z_FINISH ) ;
}
flushOutvec() ;
if ( err != Z_STREAM_END ) {
cerr << "DeflateOutputStreambuf::endDeflation(): deflation failed:\n" ;
#ifdef HAVE_ZERROR
cerr << ": " << zError( err ) ;
#endif
cerr << endl ;
}
}
} // namespace
/** \file
Implementation of DeflateOutputStreambuf.
*/
/*
Zipios++ - a small C++ library that provides easy access to .zip files.
Copyright (C) 2000 Thomas Søndergaard
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -0,0 +1,170 @@
#include "zipios++/zipios-config.h"
#include "zipios++/meta-iostreams.h"
#include <vector>
#include <sys/stat.h>
#include "zipios++/dircoll.h"
#include "directory.h"
using namespace zipios;
DirectoryCollection::DirectoryCollection( const string &path, bool recursive,
bool load_now )
: _entries_loaded( false ),
_recursive ( recursive ),
_filepath ( path )
{
_filename = _filepath ;
_valid = _filepath.isDirectory() ;
if( _valid && load_now )
loadEntries() ;
}
void DirectoryCollection::close() {
_valid = false ;
}
ConstEntries DirectoryCollection::entries() const {
if ( ! _valid )
throw InvalidStateException( "Attempt to use an invalid DirectoryCollection" ) ;
loadEntries() ;
return FileCollection::entries() ;
}
ConstEntryPointer
DirectoryCollection::getEntry( const string &name,
MatchPath matchpath ) const {
if ( ! _valid )
throw InvalidStateException( "Attempt to use an invalid DirectoryCollection" ) ;
if ( matchpath != MATCH || _entries_loaded ) {
loadEntries() ;
return FileCollection::getEntry( name, matchpath ) ;
} else {
// avoid loading entries if possible.
ConstEntryPointer ent ( new DirEntry( name, "", _filepath ) ) ;
if ( ent->isValid() )
return ent ;
else
return 0 ;
}
}
istream *DirectoryCollection::getInputStream( const ConstEntryPointer &entry ) {
if ( ! _valid )
throw InvalidStateException( "Attempt to use an invalid DirectoryCollection" ) ;
return getInputStream( entry->getName() ) ;
}
std::istream *DirectoryCollection::getInputStream( const string &entry_name,
MatchPath matchpath )
{
using std::ifstream ;
if ( ! _valid )
throw InvalidStateException( "Attempt to use an invalid DirectoryCollection" ) ;
if ( matchpath != MATCH || _entries_loaded ) {
loadEntries() ;
ConstEntryPointer ent = getEntry( entry_name, matchpath ) ;
if ( ent == 0 )
return 0 ;
else {
string real_path( _filepath + entry_name ) ;
return new ifstream( real_path.c_str(), ios::in | ios::binary ) ;
}
} else {
// avoid loading entries if possible.
string real_path( _filepath + entry_name ) ;
ifstream *ifs = new ifstream( real_path.c_str(), ios::in | ios::binary ) ;
if( ! *ifs ) {
delete ifs ;
return 0 ;
} else
return ifs ;
}
}
int DirectoryCollection::size() const {
if ( ! _valid )
throw InvalidStateException( "Attempt to use an invalid DirectoryCollection" ) ;
loadEntries() ;
return _entries.size() ;
}
FileCollection *DirectoryCollection::clone() const {
return new DirectoryCollection( *this ) ;
}
DirectoryCollection::~DirectoryCollection() {}
void DirectoryCollection::loadEntries() const {
if( _entries_loaded )
return ;
const_cast< DirectoryCollection * >( this )->load( _recursive ) ;
_entries_loaded = true ;
}
void DirectoryCollection::load( bool recursive, const FilePath &subdir ) {
using namespace boost::filesystem ;
BasicEntry *ent ;
for ( dir_it it( _filepath + subdir ) ; it != dir_it() ; ++it ) {
if ( *it == "." || *it == ".." || *it == "..." )
continue ;
if ( get< is_directory >( it ) && recursive ) {
load( recursive, subdir + *it ) ;
} else {
_entries.push_back( ent = new BasicEntry( subdir + *it, "", _filepath ) ) ;
ent->setSize( get< boost::filesystem::size >( it ) ) ;
}
}
}
// namespace
/** \file
Implementation of DirectoryCollection.
*/
/*
Zipios++ - a small C++ library that provides easy access to .zip files.
Copyright (C) 2000 Thomas Søndergaard
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -0,0 +1,393 @@
/** \file
This file and directory.h are borrowed from the dir_it library
available at http://www.boost.org. dir_it is a directory iterator.
*/
// -*-C++-*- directory.cc
// <!!---------------------------------------------------------------------->
// <!! Copyright (C) 1998 Dietmar Kuehl, Claas Solutions GmbH >
// <!!>
// <!! Permission to use, copy, modify, distribute and sell this >
// <!! software for any purpose is hereby granted without fee, provided >
// <!! that the above copyright notice appears in all copies and that >
// <!! both that copyright notice and this permission notice appear in >
// <!! supporting documentation. Dietmar Kuehl and Claas Solutions make no >
// <!! representations about the suitability of this software for any >
// <!! purpose. It is provided "as is" without express or implied warranty. >
// <!!---------------------------------------------------------------------->
// Author: Dietmar Kuehl dietmar.kuehl@claas-solutions.de
// Title: Implementation of the directory iterator
// Version: $Name: $ $Id: directory.cpp,v 1.5 2004/05/01 17:33:11 dheck Exp $
// --------------------------------------------------------------------------
#include "directory.h"
# define BOOST_UNIX 1
// --------------------------------------------------------------------------
// The POSIX version uses the functions opendir(), readdir(), and closdir()
// to find directory entries. In addition, stat() is used to find out
// about specific file attributes.
#if 1
#ifndef __USE_BSD
#define __USE_BSD
#endif
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
struct boost::filesystem::dir_it::representation
{
representation():
m_handle(0),
m_refcount(1),
m_stat_p(false)
{
}
representation(std::string const &dirname):
m_handle(opendir(dirname.c_str())),
m_refcount(1),
m_directory(dirname),
m_stat_p(false)
{
if( m_directory.size() == 0 )
m_directory = "./" ;
if (m_directory[m_directory.size() - 1] != '/')
m_directory += '/';
operator++ ();
}
~representation() { if ( m_handle ) closedir(m_handle); }
representation *reference()
{
++m_refcount;
return this;
}
representation *release() { return --m_refcount? 0: this; }
representation &operator++()
{
if (m_handle)
{
m_stat_p = false;
dirent *rc = readdir(m_handle);
if (rc != 0)
m_current = rc->d_name;
else
{
m_current = "";
closedir(m_handle);
m_handle = 0;
}
}
return *this;
}
bool operator== (representation const &rep) const
{
return (m_handle == 0) == (rep.m_handle == 0);
}
std::string const &operator* () { return m_current; }
struct stat &get_stat()
{
if (!m_stat_p)
stat( (m_directory + m_current).c_str(), &m_stat);
return m_stat;
}
void set_mode(mode_t m, bool nv)
{
if (((get_stat().st_mode & m) == 0) == nv)
chmod((m_directory + m_current).c_str(), get_stat().st_mode ^ m);
}
void change_owner(uid_t uid) { chown((m_directory + m_current).c_str(), uid, get_stat().st_gid); }
void change_group(gid_t gid) { chown((m_directory + m_current).c_str(), get_stat().st_uid, gid); }
private:
DIR *m_handle;
int m_refcount;
std::string m_directory;
std::string m_current;
struct stat m_stat;
bool m_stat_p;
};
namespace boost
{
namespace filesystem
{
template <> bool get<is_link>(dir_it const &it) { return S_ISLNK(it.rep->get_stat().st_mode); }
template <> bool get<is_regular>(dir_it const &it) { return S_ISREG(it.rep->get_stat().st_mode); }
template <> bool get<is_directory>(dir_it const &it) { return S_ISDIR(it.rep->get_stat().st_mode); }
template <> bool get<is_char_device>(dir_it const &it) { return S_ISCHR(it.rep->get_stat().st_mode); }
template <> bool get<is_block_device>(dir_it const &it) { return S_ISBLK(it.rep->get_stat().st_mode); }
template <> bool get<is_fifo>(dir_it const &it) { return S_ISFIFO(it.rep->get_stat().st_mode); }
template <> bool get<is_socket>(dir_it const &it) { return S_ISSOCK(it.rep->get_stat().st_mode); }
template <> bool get<user_read>(dir_it const &it) { return it.rep->get_stat().st_mode & S_IRUSR; }
template <> void set<user_read>(dir_it const &it, bool nv) { it.rep->set_mode(S_IRUSR, nv); }
template <> bool get<user_write>(dir_it const &it) { return it.rep->get_stat().st_mode & S_IWUSR; }
template <> void set<user_write>(dir_it const &it, bool nv) { it.rep->set_mode(S_IWUSR, nv); }
template <> bool get<user_execute>(dir_it const &it) { return it.rep->get_stat().st_mode & S_IXUSR; }
template <> void set<user_execute>(dir_it const &it, bool nv) { it.rep->set_mode(S_IXUSR, nv); }
template <> bool get<set_uid>(dir_it const &it) { return it.rep->get_stat().st_mode & S_ISUID; }
template <> void set<set_uid>(dir_it const &it, bool nv) { it.rep->set_mode(S_ISUID, nv); }
template <> bool get<group_read>(dir_it const &it) { return it.rep->get_stat().st_mode & S_IRGRP; }
template <> void set<group_read>(dir_it const &it, bool nv) { it.rep->set_mode(S_IRGRP, nv); }
template <> bool get<group_write>(dir_it const &it) { return it.rep->get_stat().st_mode & S_IWGRP; }
template <> void set<group_write>(dir_it const &it, bool nv) { it.rep->set_mode(S_IWGRP, nv); }
template <> bool get<group_execute>(dir_it const &it) { return it.rep->get_stat().st_mode & S_IXGRP; }
template <> void set<group_execute>(dir_it const &it, bool nv) { it.rep->set_mode(S_IXGRP, nv); }
template <> bool get<set_gid>(dir_it const &it) { return it.rep->get_stat().st_mode & S_ISGID; }
template <> void set<set_gid>(dir_it const &it, bool nv) { it.rep->set_mode(S_ISGID, nv); }
template <> bool get<other_read>(dir_it const &it) { return it.rep->get_stat().st_mode & S_IROTH; }
template <> void set<other_read>(dir_it const &it, bool nv) { it.rep->set_mode(S_IROTH, nv); }
template <> bool get<other_write>(dir_it const &it) { return it.rep->get_stat().st_mode & S_IWOTH; }
template <> void set<other_write>(dir_it const &it, bool nv) { it.rep->set_mode(S_IWOTH, nv); }
template <> bool get<other_execute>(dir_it const &it) { return it.rep->get_stat().st_mode & S_IXOTH; }
template <> void set<other_execute>(dir_it const &it, bool nv) { it.rep->set_mode(S_IXOTH, nv); }
template <> bool get<sticky>(dir_it const &it) { return it.rep->get_stat().st_mode & S_ISVTX; }
template <> void set<sticky>(dir_it const &it, bool nv) { it.rep->set_mode(S_ISVTX, nv); }
template <> nlink_t get<links>(dir_it const &it) { return it.rep->get_stat().st_nlink; }
template <> size_t get<size>(dir_it const &it) { return it.rep->get_stat().st_size; }
template <> unsigned long get<blocks>(dir_it const &it) { return it.rep->get_stat().st_blocks; }
template <> unsigned long get<blksize>(dir_it const &it) { return it.rep->get_stat().st_blksize; }
template <> mtime::value_type get<mtime>(dir_it const &it) { return (const time_t*)&it.rep->get_stat().st_mtime; }
template <> atime::value_type get<atime>(dir_it const &it) { return (time_t*)&it.rep->get_stat().st_atime; }
template <> ctime::value_type get<ctime>(dir_it const &it) { return (time_t*)&it.rep->get_stat().st_ctime; }
template <> uid_t get<uid>(dir_it const &it) { return it.rep->get_stat().st_uid; }
template <> void set<uid>(dir_it const &it, uid_t uid) { it.rep->change_owner(uid); }
template <> std::string get<uname>(dir_it const &it)
{
struct passwd *pw = getpwuid(it.rep->get_stat().st_uid);
if (pw == 0)
throw unknown_uid(it.rep->get_stat().st_uid);
return pw->pw_name;
}
template <> void set<uname>(dir_it const &it, std::string name)
{
struct passwd *pw = getpwnam(name.c_str());
if (pw != 0)
it.rep->change_owner(pw->pw_uid);
else
throw unknown_uname(name);
}
template <> gid_t get<gid>(dir_it const &it) { return it.rep->get_stat().st_gid; }
template <> void set<gid>(dir_it const &it, gid_t gid) { it.rep->change_group(gid); }
template <> std::string get<gname>(dir_it const &it)
{
struct group *grp = getgrgid(it.rep->get_stat().st_gid);
if (grp == 0)
throw unknown_gid(it.rep->get_stat().st_gid);
return grp->gr_name;
}
template <> void set<gname>(dir_it const &it, std::string name)
{
struct group *grp = getgrnam(name.c_str());
if (grp != 0)
it.rep->change_group(grp->gr_gid);
else
throw unknown_gname(name);
}
template <> bool get<is_hidden>(dir_it const &it) { return (*it)[0] == '.'; }
}
}
#elif defined(BOOST_WINNT)
#include "io.h"
#include "direct.h"
struct boost::filesystem::dir_it::representation
{
representation():
m_handle(-1),
m_refcount(1)
{
}
representation(std::string const &dirname):
m_handle(_findfirst((dirname + "\\*").c_str(), &m_data)),
m_refcount(1)
{
}
~representation() { if (m_handle != -1) _findclose(m_handle); }
representation *reference()
{
++m_refcount;
return this;
}
representation *release() { return --m_refcount? 0: this; }
representation &operator++()
{
if (m_handle != -1)
{
if (_findnext(m_handle, &m_data) == -1)
{
_findclose(m_handle);
m_handle = -1;
}
}
return *this;
}
bool operator== (representation const &rep) const
{
return (m_handle == -1) == (rep.m_handle == -1);
}
std::string operator* () { return m_data.name; }
struct _finddata_t const &get_data() const
{
return m_data;
}
#if 0
void set_mode(mode_t m, bool nv)
{
if (((get_stat().st_mode & m) == 0) == nv)
chmod((m_directory + m_current).c_str(), get_stat().st_mode ^ m);
}
void change_owner(uid_t uid) { chown((m_directory + m_current).c_str(), uid, get_stat().st_gid); }
void change_group(gid_t gid) { chown((m_directory + m_current).c_str(), get_stat().st_uid, gid); }
#endif
private:
struct _finddata_t m_data;
long m_handle;
int m_refcount;
std::string m_directory;
};
namespace boost
{
namespace filesystem
{
#if 0
template <> size_t get<size> (dir_it const &it) //::operator size::value_type() const
{
return it.rep->get_data().size;
}
template <> get<mtime>::operator mtime::value_type() const
{
return &m_it.rep->get_data().time_write;
}
template <> get<is_directory>::operator is_directory::value_type() const
{
return (m_it.rep->get_data().attrib & _A_SUBDIR) != 0;
}
template <> get<is_regular>::operator is_regular::value_type() const
{
return (m_it.rep->get_data().attrib & _A_SUBDIR) == 0;
}
template <> get<is_hidden>::operator is_hidden::value_type() const
{
return (m_it.rep->get_data().attrib & _A_HIDDEN) != 0;
}
template <> get<user_read>::operator user_read::value_type() const
{
return true;
}
template <> get<user_write>::operator user_write::value_type() const
{
return (m_it.rep->get_data().attrib & _A_RDONLY) == 0;
}
template <> get<user_execute>::operator user_execute::value_type() const
{
std::string name(*m_it);
std::string ext(name.substr(name.find_last_of('.')));
return ext == ".exe" || ext == ".bat";
}
#endif
}
}
#endif
// --------------------------------------------------------------------------
boost::filesystem::dir_it::dir_it():
rep(new representation())
{
}
boost::filesystem::dir_it::dir_it(std::string const &dirname):
rep(new representation(dirname))
{
}
boost::filesystem::dir_it::dir_it(boost::filesystem::dir_it const &it):
rep(it.rep->reference())
{
}
boost::filesystem::dir_it::~dir_it()
{
delete rep->release();
}
boost::filesystem::dir_it &boost::filesystem::dir_it::operator= (boost::filesystem::dir_it const &it)
{
it.rep->reference();
delete rep->release();
rep = it.rep;
return *this;
}
// --------------------------------------------------------------------------
std::string boost::filesystem::dir_it::operator* () const
{
return *(*rep);
}
boost::filesystem::dir_it &boost::filesystem::dir_it::operator++ ()
{
++(*rep);
return *this;
}
boost::filesystem::dir_it::proxy boost::filesystem::dir_it::operator++ (int)
{
std::string rc(*(*rep));
++(*rep);
return rc;
}
// --------------------------------------------------------------------------
bool boost::filesystem::dir_it::operator== (boost::filesystem::dir_it const &it) const
{
return *rep == *(it.rep);
}
bool boost::filesystem::dir_it::operator!= (boost::filesystem::dir_it const &it) const
{
return !(*rep == *(it.rep));
}

View File

@@ -0,0 +1,351 @@
/** \file
This file and directory.cpp are borrowed from the dir_it library
available at http://www.boost.org. dir_it is a directory iterator.
*/
// -*-C++-*- directory.h
// <!!---------------------------------------------------------------------->
// <!! Copyright (C) 1998 Dietmar Kuehl, Claas Solutions GmbH >
// <!!>
// <!! Permission to use, copy, modify, distribute and sell this >
// <!! software for any purpose is hereby granted without fee, provided >
// <!! that the above copyright notice appears in all copies and that >
// <!! both that copyright notice and this permission notice appear in >
// <!! supporting documentation. Dietmar Kuehl and Claas Solutions make no >
// <!! representations about the suitability of this software for any >
// <!! purpose. It is provided "as is" without express or implied warranty. >
// <!!---------------------------------------------------------------------->
// Author: Dietmar Kuehl dietmar.kuehl@claas-solutions.de
// Title: An input iterator used to list the entries in a directory
// Version: $Name: $ $Id: directory.h,v 1.6 2004/05/01 17:33:10 dheck Exp $
// --------------------------------------------------------------------------
#if !defined(BOOST_DIRECTORY_H)
#define BOOST_DIRECTORY_H 1
// --------------------------------------------------------------------------
#include <iterator>
#include <string>
#include <ctime>
#include <stdexcept>
// #include <boost.h> Contents of boost.h
// Allow control over DLL version being built
# define BOOST_DECL
#include <sys/types.h>
// --------------------------------------------------------------------------
namespace boost
{
namespace filesystem
{
class dir_it;
#if defined(__GNUG__)
template <class Property>
typename Property::value_type get(dir_it const &);
template <class Property>
void set(dir_it const &, typename Property::value_type);
#else
template <class Property> class get;
template <class Property> class set;
#endif
class BOOST_DECL dir_it //: public std::iterator<std::input_iterator_tag, std::string>
{
#if defined(__GNUG__)
template <class Property>
friend typename Property::value_type get(dir_it const &);
template <class Property>
friend void set(dir_it const &, typename Property::value_type);
#endif
struct representation;
public:
typedef ptrdiff_t difference_type;
typedef std::string value_type;
typedef std::string *pointer;
typedef std::string &reference;
class proxy
{
friend class dir_it;
proxy(std::string const &ent): entry(ent) {}
public:
std::string operator*() const { return entry; }
private:
std::string entry;
};
dir_it();
dir_it(std::string const &);
dir_it(dir_it const &);
~dir_it();
dir_it &operator= (dir_it const &);
std::string operator* () const;
dir_it &operator++ ();
proxy operator++ (int);
bool operator== (dir_it const &) const;
bool operator!= (dir_it const &) const;
#if defined(__GNUG__)
private:
#endif
representation *rep;
};
struct size { typedef size_t value_type; };
struct mtime { typedef time_t const *value_type; };
struct is_directory { typedef bool value_type; };
struct is_regular { typedef bool value_type; };
struct is_hidden { typedef bool value_type; };
struct user_read { typedef bool value_type; };
struct user_write { typedef bool value_type; };
struct user_execute { typedef bool value_type; };
#if defined(__GNUG__)
template <> size::value_type get<size>(dir_it const &);
template <> mtime::value_type get<mtime>(dir_it const &);
template <> bool get<is_directory>(dir_it const &);
template <> bool get<is_regular>(dir_it const &);
template <> bool get<is_hidden>(dir_it const &);
template <> bool get<user_read>(dir_it const &);
template <> void set<user_read>(dir_it const &, bool);
template <> bool get<user_write>(dir_it const &);
template <> void set<user_write>(dir_it const &, bool);
template <> bool get<user_execute>(dir_it const &);
template <> void set<user_execute>(dir_it const &, bool);
#else
template <> class BOOST_DECL get<size>
{
typedef size::value_type value_type;
public:
get(dir_it const &it): m_it(it) {}
operator value_type() const;
private:
dir_it const &m_it;
};
template <> class BOOST_DECL get<mtime>
{
typedef mtime::value_type value_type;
public:
get(dir_it const &it): m_it(it) {}
operator value_type() const;
private:
dir_it const &m_it;
};
template <> class BOOST_DECL get<is_directory>
{
typedef is_directory::value_type value_type;
public:
get(dir_it const &it): m_it(it) {}
operator value_type() const;
private:
dir_it const &m_it;
};
template <> class BOOST_DECL get<is_regular>
{
typedef is_regular::value_type value_type;
public:
get(dir_it const &it): m_it(it) {}
operator value_type() const;
private:
dir_it const &m_it;
};
template <> class BOOST_DECL get<is_hidden>
{
typedef is_hidden::value_type value_type;
public:
get(dir_it const &it): m_it(it) {}
operator value_type() const;
private:
dir_it const &m_it;
};
template <> class BOOST_DECL set<is_hidden>
{
public:
set(dir_it const &, is_hidden::value_type);
};
template <> class BOOST_DECL get<user_read>
{
typedef user_read::value_type value_type;
public:
get(dir_it const &it): m_it(it) {}
operator value_type() const;
private:
dir_it const &m_it;
};
template <> class BOOST_DECL get<user_write>
{
typedef user_write::value_type value_type;
public:
get(dir_it const &it): m_it(it) {}
operator value_type() const;
private:
dir_it const &m_it;
};
template <> class BOOST_DECL set<user_write>
{
public:
set(dir_it const &, user_write::value_type);
};
template <> class BOOST_DECL get<user_execute>
{
typedef user_execute::value_type value_type;
public:
get(dir_it const &it): m_it(it) {}
operator value_type() const;
private:
dir_it const &m_it;
};
#endif
struct is_link { typedef bool value_type; };
template <> bool get<is_link>(dir_it const &);
struct is_char_device { typedef bool value_type; };
template <> bool get<is_char_device>(dir_it const &);
struct is_block_device { typedef bool value_type; };
template <> bool get<is_block_device>(dir_it const &);
struct is_fifo { typedef bool value_type; };
template <> bool get<is_fifo>(dir_it const &);
struct is_socket { typedef bool value_type; };
template <> bool get<is_socket>(dir_it const &);
struct atime { typedef time_t *value_type; };
template <> atime::value_type get<atime>(dir_it const &);
struct ctime { typedef time_t *value_type; };
template <> ctime::value_type get<ctime>(dir_it const &);
struct group_read { typedef bool value_type; };
template <> bool get<group_read>(dir_it const &);
template <> void set<group_read>(dir_it const &, bool);
struct group_write { typedef bool value_type; };
template <> bool get<group_write>(dir_it const &);
template <> void set<group_write>(dir_it const &, bool);
struct group_execute { typedef bool value_type; };
template <> bool get<group_execute>(dir_it const &);
template <> void set<group_execute>(dir_it const &, bool);
struct other_read { typedef bool value_type; };
template <> bool get<other_read>(dir_it const &);
template <> void set<other_read>(dir_it const &, bool);
struct other_write { typedef bool value_type; };
template <> bool get<other_write>(dir_it const &);
template <> void set<other_write>(dir_it const &, bool);
struct other_execute { typedef bool value_type; };
template <> bool get<other_execute>(dir_it const &);
template <> void set<other_execute>(dir_it const &, bool);
struct set_uid { typedef bool value_type; };
template <> bool get<set_uid>(dir_it const &);
template <> void set<set_uid>(dir_it const &, bool);
struct set_gid { typedef bool value_type; };
template <> bool get<set_gid>(dir_it const &);
template <> void set<set_gid>(dir_it const &, bool);
struct sticky { typedef bool value_type; };
template <> bool get<sticky>(dir_it const &);
template <> void set<sticky>(dir_it const &, bool);
struct mode { typedef mode_t value_type; };
template <> mode_t get<mode>(dir_it const &);
template <> void set<mode>(dir_it const &, mode_t);
struct links { typedef nlink_t value_type; };
template<> nlink_t get<links>(dir_it const &);
struct blocks { typedef unsigned long value_type; };
template<> unsigned long get<blocks>(dir_it const &);
struct blksize { typedef unsigned long value_type; };
template<> unsigned long get<blksize>(dir_it const &);
class unknown_uid: public std::invalid_argument
{
public:
unknown_uid(uid_t u): std::invalid_argument("unknown user ID"), m_uid(u) {}
uid_t uid() const { return m_uid; }
private:
uid_t m_uid;
};
struct uid { typedef uid_t value_type; };
template<> uid_t get<uid>(dir_it const &);
template<> void set<uid>(dir_it const &, uid_t);
class unknown_uname: public std::invalid_argument
{
public:
unknown_uname(std::string u): std::invalid_argument("unknown user name"), m_uname(u) {}
// TODO: Why does this destructor have to be redefined so as to avoid the "looser throw specifier" error.
~unknown_uname() throw() { }
std::string uname() const { return m_uname; }
private:
std::string m_uname;
};
struct uname { typedef std::string value_type; };
template<> std::string get<uname>(dir_it const &);
template<> void set<uname>(dir_it const &, std::string );
class unknown_gid: public std::invalid_argument
{
public:
unknown_gid(gid_t g): std::invalid_argument("unknown group ID"), m_gid(g) {}
gid_t gid() const { return m_gid; }
private:
gid_t m_gid;
};
struct gid { typedef gid_t value_type; };
template<> gid_t get<gid>(dir_it const &);
template<> void set<gid>(dir_it const &, gid_t);
class unknown_gname: public std::invalid_argument
{
public:
unknown_gname(std::string g): std::invalid_argument("unknown group name"), m_gname(g) {}
// TODO: Why does this destructor have to be redefined so as to avoid the "looser throw specifier" error.
~unknown_gname() throw() { }
std::string gname() const { return m_gname; }
private:
std::string m_gname;
};
struct gname { typedef std::string value_type; };
template<> std::string get<gname>(dir_it const &);
template<> void set<gname>(dir_it const &, std::string );
} // namespace filesystem
} // namespace boost
namespace std
{
template <>
struct iterator_traits<boost::filesystem::dir_it> {
public:
typedef ptrdiff_t difference_type;
typedef std::string value_type;
typedef std::string *pointer;
typedef std::string &reference;
typedef input_iterator_tag iterator_category;
};
} // namespace std
// --------------------------------------------------------------------------
#endif /* BOOST_DIRECTORY_H */

View File

@@ -0,0 +1,90 @@
#include "zipios++/zipios-config.h"
#include <algorithm>
#include <string>
#include <vector>
#include "zipios++/fcoll.h"
namespace zipios {
using std::find_if ;
// FIXME: make InvalidStateException message customized for
// subclasses. maybe make an InvalidStateException factory ;-)
ConstEntries FileCollection::entries() const {
if ( ! _valid )
throw InvalidStateException( "Attempt to get entries from an invalid FileCollection" ) ;
// The constructor below is not in all vector impl. (not those
// without member templates)
// ConstEntries ( _entries.begin(), _entries.end() ) ;
// Instead of using that we copy the vector manually
ConstEntries cep_vec ;
cep_vec.reserve( _entries.size() ) ;
Entries::const_iterator cit ;
for ( cit = _entries.begin() ; cit != _entries.end() ; ++cit )
cep_vec.push_back( *cit ) ;
return cep_vec ;
}
ConstEntryPointer FileCollection::getEntry( const string &name,
MatchPath matchpath ) const {
if ( ! _valid )
throw InvalidStateException( "Attempt to get an entry from an invalid FileCollection" ) ;
Entries::const_iterator iter ;
if ( matchpath == MATCH )
iter = find_if( _entries.begin(), _entries.end(), FileEntry::MatchName( name ) ) ;
else
iter = find_if( _entries.begin(), _entries.end(), FileEntry::MatchFileName( name ) ) ;
if ( iter == _entries.end() )
return 0 ;
else
return *iter ;
}
string FileCollection::getName() const {
if ( ! _valid )
throw InvalidStateException( "Attempt to get the name of an invalid FileCollection" ) ;
return _filename ;
}
int FileCollection::size() const {
if ( ! _valid )
throw InvalidStateException( "Attempt to get size of an invalid FileCollection" ) ;
return _entries.size() ;
}
FileCollection::~FileCollection() {
}
} // namespace
/** \file
Implementation of FileCollection.
*/
/*
Zipios++ - a small C++ library that provides easy access to .zip files.
Copyright (C) 2000 Thomas Søndergaard
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -0,0 +1,144 @@
#include "zipios++/zipios-config.h"
#include "zipios++/meta-iostreams.h"
#include "zipios++/fcollexceptions.h"
namespace zipios {
using std::cerr ;
using std::endl ;
IOException::IOException() throw ()
: _what( "I/O exception" ) {}
IOException::IOException( const string &msg ) throw ()
: _what( msg ) {}
IOException::IOException( const IOException &src ) throw ()
: _what( src._what ) {}
IOException &IOException::operator= ( const IOException &src ) throw () {
_what = src._what ;
return *this ;
}
const char *IOException::what() const throw () {
return _what.c_str() ;
}
IOException::~IOException() throw () {}
FCollException::FCollException() throw ()
: _what( "FileCollection exception" ) {}
FCollException::FCollException( const string &msg ) throw ()
: _what( msg ) {}
FCollException::FCollException( const FCollException &src ) throw ()
: _what( src._what ) {}
FCollException &FCollException::operator= ( const FCollException &src ) throw () {
_what = src._what ;
return *this ;
}
const char *FCollException::what() const throw () {
return _what.c_str() ;
}
FCollException::~FCollException() throw () {}
InvalidStateException::InvalidStateException() throw ()
: _what( "InvalidState exception" ) {}
InvalidStateException::InvalidStateException( const string &msg ) throw ()
: _what( msg ) {}
InvalidStateException::
InvalidStateException( const InvalidStateException &src ) throw ()
: _what( src._what ) {}
InvalidStateException &InvalidStateException::
operator= ( const InvalidStateException &src ) throw () {
_what = src._what ;
return *this ;
}
const char *InvalidStateException::what() const throw () {
return _what.c_str() ;
}
InvalidStateException::~InvalidStateException() throw () {}
Exception::Exception() throw ()
: _what( "Exception" ) {}
Exception::Exception( const string &msg ) throw ()
: _what( msg ) {}
Exception::
Exception( const Exception &src ) throw ()
: _what( src._what ) {}
Exception &Exception::
operator= ( const Exception &src ) throw () {
_what = src._what ;
return *this ;
}
const char *Exception::what() const throw () {
return _what.c_str() ;
}
Exception::~Exception() throw () {}
} // namespace
/** \file
Implementation of a number of Exceptions used by FileCollection and its
subclasses.
*/
/*
Zipios++ - a small C++ library that provides easy access to .zip files.
Copyright (C) 2000 Thomas Søndergaard
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -0,0 +1,39 @@
#include "zipios++/zipios-config.h"
#include "zipios++/meta-iostreams.h"
#include <string>
#include "zipios++/fileentry.h"
namespace zipios {
ostream &operator<< ( ostream &os, const FileEntry &entry ) {
os << entry.toString() ;
return os ;
}
} // namespace
/** \file
Implementation of FileEntry.
*/
/*
Zipios++ - a small C++ library that provides easy access to .zip files.
Copyright (C) 2000 Thomas Søndergaard
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -0,0 +1,72 @@
#include "zipios++/zipios-config.h"
#include <stdexcept>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include "zipios++/filepath.h"
namespace zipios {
using namespace std ;
const char FilePath::_separator = '/' ;
FilePath::FilePath( const string &path, bool check_exists )
: _checked( false ),
_path( path ) {
pruneTrailingSeparator() ;
if ( check_exists )
exists() ;
}
void FilePath::check() const {
_checked = true ;
_exists = false ;
_is_reg = false ;
_is_dir = false ;
_is_char = false ;
_is_block = false ;
_is_socket = false ;
_is_fifo = false ;
struct stat buf ;
if ( stat( _path.c_str(), &buf ) != -1 ) {
_exists = true ;
_is_reg = S_ISREG ( buf.st_mode ) ;
_is_dir = S_ISDIR ( buf.st_mode ) ;
_is_char = S_ISCHR ( buf.st_mode ) ;
_is_block = S_ISBLK ( buf.st_mode ) ;
// _is_socket = S_ISSOCK( buf.st_mode ) ; // doesn't work with mingw32
_is_fifo = S_ISFIFO( buf.st_mode ) ;
}
}
} // namespace
/** \file
Implementation of FilePath.
*/
/*
Zipios++ - a small C++ library that provides easy access to .zip files.
Copyright (C) 2000 Thomas Søndergaard
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -0,0 +1,47 @@
#include "zipios++/zipios-config.h"
#include "zipios++/filterinputstreambuf.h"
namespace zipios {
FilterInputStreambuf::FilterInputStreambuf( streambuf *inbuf, bool del_inbuf )
: _inbuf( inbuf),
_del_inbuf( del_inbuf )
{
if ( _inbuf == NULL ) {
// throw an exception
}
}
FilterInputStreambuf::~FilterInputStreambuf() {
if ( _del_inbuf )
delete _inbuf ;
}
} // namespace
/** \file
Implementation of FilterInputStreambuf.
*/
/*
Zipios++ - a small C++ library that provides easy access to .zip files.
Copyright (C) 2000 Thomas Søndergaard
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

Some files were not shown because too many files have changed in this diff Show More