Merge trunk to the cpcmode5 branch. This gets us a more recent grafx2 with the cpcmode5 drawing. Now to make this mode optional so users can still work in regular mode :)

git-svn-id: svn://pulkomandy.tk/GrafX2/branches/cpcmode5@1719 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
Adrien Destugues 2011-02-13 21:49:31 +00:00
parent 4e60f5ad74
commit eba26aaa96
65 changed files with 8669 additions and 3286 deletions

View File

@ -1,5 +1,6 @@
# Grafx2 - The Ultimate 256-color bitmap paint program # Grafx2 - The Ultimate 256-color bitmap paint program
# #
# Copyright 2011 Pawel Góralski
# Copyright 2009 Per Olofsson # Copyright 2009 Per Olofsson
# Copyright 2008 Peter Gordon # Copyright 2008 Peter Gordon
# Copyright 2008-2010 Yves Rizoud # Copyright 2008-2010 Yves Rizoud
@ -25,6 +26,7 @@
bindir = $(exec_prefix)/bin bindir = $(exec_prefix)/bin
datarootdir = $(prefix)/share datarootdir = $(prefix)/share
datadir = $(datarootdir) datadir = $(datarootdir)
pixmapdir = $(datarootdir)/icons
# Compile with OPTIM=0 to disable gcc optimizations, to enable debug. # Compile with OPTIM=0 to disable gcc optimizations, to enable debug.
STRIP = strip STRIP = strip
@ -42,8 +44,8 @@ ifdef COMSPEC
RMDIR = rmdir RMDIR = rmdir
CP = cp CP = cp
BIN = ../bin/grafx2.exe BIN = ../bin/grafx2.exe
COPT = -W -Wall -Wdeclaration-after-statement -O$(OPTIM) -g -ggdb `sdl-config --cflags` $(TTFCOPT) $(JOYCOPT) $(LUACOPT) $(LAYERCOPT) COPT = -W -Wall -Wdeclaration-after-statement -O$(OPTIM) -g -ggdb `sdl-config --cflags` $(TTFCOPT) $(JOYCOPT) $(VKEYCOPT) $(LUACOPT) $(LAYERCOPT)
LOPT = `sdl-config --libs` -lSDL_image $(TTFLOPT) -lpng $(LUALOPT) LOPT = `sdl-config --libs` -lSDL_image $(TTFLOPT) -lpng14 $(LUALOPT)
LUALOPT = -llua LUALOPT = -llua
CC = gcc CC = gcc
OBJDIR = ../obj/win32 OBJDIR = ../obj/win32
@ -52,7 +54,7 @@ ifdef COMSPEC
PLATFORMOBJ = $(OBJDIR)/winres.o PLATFORMOBJ = $(OBJDIR)/winres.o
PLATFORM = win32 PLATFORM = win32
#some misc files we have to add to the release archive under windows. #some misc files we have to add to the release archive under windows.
PLATFORMFILES = bin/SDL.dll bin/SDL_image.dll bin/libpng13.dll bin/zlib1.dll $(TTFLIBS) PLATFORMFILES = bin/SDL.dll bin/SDL_image.dll bin/libpng14-14.dll bin/zlib1.dll $(TTFLIBS)
ZIP = zip ZIP = zip
else else
@ -88,7 +90,7 @@ else
FWDIR = /Library/Frameworks FWDIR = /Library/Frameworks
SDLCOPT = -arch i386 -I$(FWDIR)/SDL.framework/Headers -I$(FWDIR)/SDL_image.framework/Headers -I$(FWDIR)/SDL_ttf.framework/Headers -D_THREAD_SAFE SDLCOPT = -arch i386 -I$(FWDIR)/SDL.framework/Headers -I$(FWDIR)/SDL_image.framework/Headers -I$(FWDIR)/SDL_ttf.framework/Headers -D_THREAD_SAFE
SDLLOPT = -arch i386 -L/usr/lib -framework SDL -framework SDL_image -framework SDL_ttf -framework Cocoa -framework Carbon -framework OpenGL SDLLOPT = -arch i386 -L/usr/lib -framework SDL -framework SDL_image -framework SDL_ttf -framework Cocoa -framework Carbon -framework OpenGL
COPT = -D__macosx__ -D__linux__ -W -Wall -Wdeclaration-after-statement -O$(OPTIM) -std=c99 -c -g $(SDLCOPT) $(TTFCOPT) -I/usr/X11/include COPT = -D_DARWIN_C_SOURCE -D__macosx__ -D__linux__ -W -Wall -Wdeclaration-after-statement -O$(OPTIM) -std=c99 -c -g $(SDLCOPT) $(TTFCOPT) -I/usr/X11/include
LOPT = $(SDLLOPT) -L/usr/X11/lib -R/usr/X11/lib -lpng LOPT = $(SDLLOPT) -L/usr/X11/lib -R/usr/X11/lib -lpng
# Use gcc for compiling. Use ncc to build a callgraph and analyze the code. # Use gcc for compiling. Use ncc to build a callgraph and analyze the code.
CC = gcc CC = gcc
@ -152,8 +154,15 @@ else
RMDIR = rmdir RMDIR = rmdir
CP = cp CP = cp
BIN = ../bin/grafx2 BIN = ../bin/grafx2
COPT = -W -Wall -c -g `sdl-config --cflags` $(TTFCOPT) -I/boot/common/include ifeq ($(NOLUA),1)
LOPT = `sdl-config --libs` -lSDL_image -lpng -ljpeg -lz $(TTFLOPT) LUACOPT =
LUALOPT =
else
LUACOPT = -D__ENABLE_LUA__
LUALOPT = -llua
endif
COPT = -W -Wall -c -g `sdl-config --cflags` $(TTFCOPT) -I/boot/common/include $(LUACOPT)
LOPT = `sdl-config --libs` -lSDL_image -lpng -ljpeg -lz $(TTFLOPT) -lfreetype -lbe $(LUALOPT)
CC = gcc CC = gcc
OBJDIR = ../obj/haiku OBJDIR = ../obj/haiku
ZIP = zip ZIP = zip
@ -197,19 +206,15 @@ else
CP = cp CP = cp
ZIP = zip ZIP = zip
PLATFORMFILES = gfx2.png PLATFORMFILES = gfx2.png
ifneq ($(ATARICROSS),1)
ifeq ($(NOLUA),1) ifeq ($(NOLUA),1)
LUACOPT = LUACOPT =
LUALOPT = LUALOPT =
else else
ifeq (`pkg-config --exists lua --print-errors`,"") LUACOPT = `pkg-config lua --cflags --silence-errors ||pkg-config lua5.1 --cflags --silence-errors ||pkg-config lua-5.1 --cflags`
LUACOPT = `pkg-config lua --cflags` LUALOPT = `pkg-config lua --libs --silence-errors ||pkg-config lua5.1 --libs --silence-errors ||pkg-config lua-5.1 --libs`
LUALOPT = `pkg-config lua --libs` endif
else
LUACOPT = `pkg-config lua5.1 --cflags`
LUALOPT = `pkg-config lua5.1 --libs`
endif
endif endif
# These can only be used under linux and maybe freebsd. They allow to compile for the gp2x or to create a windows binary # These can only be used under linux and maybe freebsd. They allow to compile for the gp2x or to create a windows binary
ifdef WIN32CROSS ifdef WIN32CROSS
#cross compile a Win32 executable #cross compile a Win32 executable
@ -225,18 +230,41 @@ else
#cross compile an exec for the gp2x #cross compile an exec for the gp2x
CC = /opt/open2x/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/bin/arm-open2x-linux-gcc CC = /opt/open2x/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/bin/arm-open2x-linux-gcc
BIN = ../bin/grafx2.gpe BIN = ../bin/grafx2.gpe
COPT = -W -Wall -Wdeclaration-after-statement -pedantic -std=c99 -static -g -O$(OPTIM) -I/opt/open2x/gcc-4.1.1-glibc-2.3.6/include `/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin/sdl-config --cflags` $(TTFCOPT) -D__GP2X__ $(TTFCOPT) $(JOYCOPT) $(LUACOPT) $(LAYERCOPT) COPT = -W -Wall -Wdeclaration-after-statement -pedantic -std=c99 -static -g -O$(OPTIM) -I/opt/open2x/gcc-4.1.1-glibc-2.3.6/include `/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin/sdl-config --cflags` $(TTFCOPT) -D__GP2X__ $(TTFCOPT) $(JOYCOPT) $(VKEYCOPT) $(LUACOPT) $(LAYERCOPT)
LOPT = -static -lSDL_image `/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin/sdl-config --static-libs` -ljpeg -lpng -lz -lm $(TTFLOPT) $(LUALOPT) LOPT = -static -lSDL_image `/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin/sdl-config --static-libs` -ljpeg -lpng -lz -lm $(TTFLOPT) $(LUALOPT)
OBJDIR = ../obj/gp2x OBJDIR = ../obj/gp2x
NOTTF = 1 NOTTF = 1
PLATFORM = gp2x PLATFORM = gp2x
STRIP = /opt/open2x/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/bin/arm-open2x-linux-strip STRIP = /opt/open2x/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/bin/arm-open2x-linux-strip
JOYCOPT = -DUSE_JOYSTICK JOYCOPT = -DUSE_JOYSTICK
else ifdef AROS32CROSS
#cross compile an Aros 32 bit executable
BIN = ../bin/grafx2
COPT = -Wall -g `i386-linux-aros-sdl-config --cflags` $(TTFCOPT)
LOPT = -lSDL_image `i386-linux-aros-sdl-config --libs` -lpng -ljpeg -lz $(TTFLOPT) -lfreetype2shared
CC = i386-aros-gcc
OBJDIR = ../obj/aros
STRIP = strip --strip-unneeded --remove-section .comment
PLATFORM = AROS
ZIP = lha
ZIPOPT = a
else ifdef ATARICROSS
#cross compile an exec for atari TOS/MiNT machine
CC = m68k-atari-mint-gcc
BIN = ../bin/grafx2.ttp
LUALOPT = -llua
OBJDIR = ../obj/m68k-atari-mint
PLATFORM = m68k-atari-mint
STRIP = m68k-atari-mint-strip -s
X11LOPT =
COPT = -W -Wall -m68020-60 -fomit-frame-pointer -pedantic -std=c99 -Wdeclaration-after-statement -D__MINT__ -DNO_INLINE_MATH -O$(OPTIM) -c -I$(prefix)/include `$(prefix)/bin/libpng12-config --cflags` `$(prefix)/bin/sdl-config --cflags` $() $(JOYCOPT) $(LAYERCOPT) $(LUACOPT)
LOPT = -static -m68020-60 -lSDL_image `$(prefix)/bin/sdl-config --libs` -L$(prefix)/lib -ltiff -ljpeg `$(prefix)/bin/libpng12-config --libs` -lz -lm $(TTFLOPT) -lfreetype $(LUALOPT) $(LAYERLOPT)
else else
# Compiles a regular linux executable for the native platform # Compiles a regular linux executable for the native platform
BIN = ../bin/grafx2 BIN = ../bin/grafx2
COPT = -W -Wall -Wdeclaration-after-statement -std=c99 -c -g `sdl-config --cflags` $(TTFCOPT) $(LUACOPT) COPT = -W -Wall -Wdeclaration-after-statement -std=c99 -c -g `sdl-config --cflags` $(TTFCOPT) $(LUACOPT) $(JOYCOPT) $(VKEYCOPT) -O$(OPTIM)
LOPT = `sdl-config --libs` -lSDL_image $(TTFLOPT) -lpng $(LUALOPT) -lm LOPT = `sdl-config --libs` -lSDL_image $(TTFLOPT) -lpng $(LUALOPT) -lm
# Use gcc for compiling. Use ncc to build a callgraph and analyze the code. # Use gcc for compiling. Use ncc to build a callgraph and analyze the code.
CC = gcc CC = gcc
@ -258,6 +286,7 @@ endif
### BUILD SETTINGS are set according to vars set in the platform selection, the "overridable defaults", and environment variables set before launching make ### BUILD SETTINGS are set according to vars set in the platform selection, the "overridable defaults", and environment variables set before launching make
#TrueType is optional: make NOTTF=1 to disable support and dependencies. #TrueType is optional: make NOTTF=1 to disable support and dependencies.
ifndef ($(ATARICROSS,1))
ifeq ($(NOTTF),1) ifeq ($(NOTTF),1)
TTFCOPT = -DNOTTF=1 TTFCOPT = -DNOTTF=1
TTFLOPT = TTFLOPT =
@ -265,10 +294,23 @@ ifeq ($(NOTTF),1)
TTFLABEL = -nottf TTFLABEL = -nottf
else else
TTFCOPT = TTFCOPT =
TTFLOPT = -L/usr/local/lib -lSDL_ttf $(X11LOPT) TTFLOPT = -L$(prefix)/lib -lSDL_ttf $(X11LOPT)
TTFLIBS = bin/libfreetype-6.dll bin/SDL_ttf.dll TTFLIBS = bin/libfreetype-6.dll bin/SDL_ttf.dll
TTFLABEL = TTFLABEL =
endif endif
else
ifeq ($(NOTTF),1)
TTFCOPT = -DNOTTF=1
TTFLOPT =
TTFLIBS =
TTFLABEL = -nottf
else
TTFCOPT =
TTFLOPT = -L$(prefix)/lib -lSDL_ttf $(X11LOPT)
TTFLIBS =
TTFLABEL =
endif
endif
#Lua scripting is optional too #Lua scripting is optional too
ifeq ($(NOLUA),1) ifeq ($(NOLUA),1)
@ -289,6 +331,14 @@ ifeq ($(USE_JOYSTICK),1)
JOYCOPT = -DUSE_JOYSTICK JOYCOPT = -DUSE_JOYSTICK
endif endif
#To enable virtual keyboard input (mouse-driven), make VIRT_KEY=1
#This is automatically enabled on some platforms, but this
#switch allows you to test the virtual keyboard on any other platform.
ifeq ($(VIRT_KEY),1)
VKEYCOPT = -DVIRT_KEY
endif
#To speed up rendering, can disable the layered editing #To speed up rendering, can disable the layered editing
# with NOLAYERS=1 # with NOLAYERS=1
ifeq ($(NOLAYERS),1) ifeq ($(NOLAYERS),1)
@ -304,11 +354,16 @@ endif
# This is the list of the objects we want to build. Dependancies are built by "make depend" automatically. # This is the list of the objects we want to build. Dependancies are built by "make depend" automatically.
OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(OBJDIR)/factory.o $(PLATFORMOBJ) $(OBJDIR)/fileformats.o $(OBJDIR)/miscfileformats.o $(OBJDIR)/libraw2crtc.o $(OBJDIR)/brush_ops.o $(OBJDIR)/buttons_effects.o $(OBJDIR)/layers.o $(OBJDIR)/oldies.o OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(OBJDIR)/factory.o $(PLATFORMOBJ) $(OBJDIR)/fileformats.o $(OBJDIR)/miscfileformats.o $(OBJDIR)/libraw2crtc.o $(OBJDIR)/brush_ops.o $(OBJDIR)/buttons_effects.o $(OBJDIR)/layers.o $(OBJDIR)/oldies.o
SKIN_FILES = ../share/grafx2/skins/skin_classic.png ../share/grafx2/skins/skin_modern.png ../share/grafx2/skins/skin_DPaint.png ../share/grafx2/skins/font_Classic.png ../share/grafx2/skins/font_Fun.png ../share/grafx2/skins/font_Fairlight.png ../share/grafx2/skins/font_Melon.png ../share/grafx2/skins/font_DPaint.png ../share/grafx2/skins/skin_scenish.png ../share/grafx2/skins/font_Seen.png SKIN_FILES = ../share/grafx2/skins/skin_classic.png ../share/grafx2/skins/skin_modern.png ../share/grafx2/skins/skin_DPaint.png ../share/grafx2/skins/font_Classic.png ../share/grafx2/skins/font_Fun.png ../share/grafx2/skins/font_Fairlight.png ../share/grafx2/skins/font_Melon.png ../share/grafx2/skins/font_DPaint.png ../share/grafx2/skins/skin_scenish.png ../share/grafx2/skins/font_Seen.png ../share/grafx2/skins/skin_Aurora.png ../share/grafx2/skins/skin_Clax3.gif ../share/grafx2/skins/skin_Clax2.gif ../share/grafx2/skins/skin_Clax4.gif
SCRIPT_FILES1 = ../share/grafx2/scripts/bru_db_Amigaball.lua ../share/grafx2/scripts/bru_db_ColorSphere.lua ../share/grafx2/scripts/bru_db_FindAA.lua ../share/grafx2/scripts/bru_db_Fisheye.lua ../share/grafx2/scripts/bru_db_GrayscaleAvg.lua ../share/grafx2/scripts/bru_db_GrayscaleDesat.lua ../share/grafx2/scripts/bru_db_Halfsmooth.lua ../share/grafx2/scripts/bru_db_Mandelbrot.lua ../share/grafx2/scripts/bru_db_Waves.lua ../share/grafx2/scripts/pal_db_Desaturate.lua ../share/grafx2/scripts/pal_db_ExpandColors.lua ../share/grafx2/scripts/pal_db_FillColorCube.lua ../share/grafx2/scripts/pal_db_InvertedRGB.lua ../share/grafx2/scripts/pal_db_Set3bit.lua ../share/grafx2/scripts/pal_db_Set6bit.lua ../share/grafx2/scripts/pal_db_SetC64Palette.lua ../share/grafx2/scripts/pal_db_ShiftHue.lua ../share/grafx2/scripts/pic_db_Pic2isometric.lua ../share/grafx2/scripts/pic_db_Rainbow-Dark2Bright.lua ../share/grafx2/scripts/pic_db_SierpinskyCarpet.lua SCRIPT_FILES1 = ../share/grafx2/scripts/bru_db_Amigaball.lua ../share/grafx2/scripts/bru_db_ColorSphere.lua ../share/grafx2/scripts/bru_db_FindAA.lua ../share/grafx2/scripts/bru_db_Fisheye.lua ../share/grafx2/scripts/bru_db_GrayscaleAvg.lua ../share/grafx2/scripts/bru_db_GrayscaleDesat.lua ../share/grafx2/scripts/bru_db_Halfsmooth.lua ../share/grafx2/scripts/bru_db_Mandelbrot.lua ../share/grafx2/scripts/bru_db_Waves.lua ../share/grafx2/scripts/pal_db_Desaturate.lua ../share/grafx2/scripts/pal_db_ExpandColors.lua ../share/grafx2/scripts/pal_db_FillColorCube.lua ../share/grafx2/scripts/pal_db_InvertedRGB.lua ../share/grafx2/scripts/pal_db_Set3bit.lua ../share/grafx2/scripts/pal_db_Set6bit.lua ../share/grafx2/scripts/pal_db_SetC64Palette.lua ../share/grafx2/scripts/pal_db_ShiftHue.lua ../share/grafx2/scripts/pic_db_Pic2isometric.lua ../share/grafx2/scripts/pic_db_Rainbow-Dark2Bright.lua ../share/grafx2/scripts/pic_db_SierpinskyCarpet.lua
SCRIPT_FILES2 = ../share/grafx2/scripts/pic_db_SierpinskyTriangle.lua ../share/grafx2/scripts/pic_ni_Colorspace12bit.lua ../share/grafx2/scripts/pic_ni_Colorspace15bit.lua ../share/grafx2/scripts/pic_ni_Colorspace18bit.lua ../share/grafx2/scripts/pic_ni_GlassGridFilter.lua ../share/grafx2/scripts/pic_ni_Grid8.lua ../share/grafx2/scripts/pic_ni_Grid8red.lua ../share/grafx2/scripts/pic_ni_GridIso.lua ../share/grafx2/scripts/pic_ni_PaletteX1.lua ../share/grafx2/scripts/pic_ni_PaletteX8.lua ../share/grafx2/scripts/scn_db_RemapImage2RGB.lua ../share/grafx2/scripts/scn_db_RemapImage2RGB_ed.lua ../share/grafx2/scripts/scn_db_RemapImageTo3bitPal.lua SCRIPT_FILES2 = ../share/grafx2/scripts/pic_db_SierpinskyTriangle.lua ../share/grafx2/scripts/pic_ni_GlassGridFilter.lua ../share/grafx2/scripts/scn_db_RemapImage2RGB.lua ../share/grafx2/scripts/scn_db_RemapImage2RGB_ed.lua ../share/grafx2/scripts/scn_db_RemapImageTo3bitPal.lua
SCRIPT_FILES1= SCRIPT_FILES1 SCRIPT_FILES2 SCRIPT_FILES= $(SCRIPT_FILES1) $(SCRIPT_FILES2)
SCRIPTLIB_FILES = ../share/grafx2/scripts/libs/memory.lua
FONT_FILES = ../share/grafx2/fonts/8pxfont.png ../share/grafx2/fonts/Tuffy.ttf ../share/grafx2/fonts/PF_Arma_5__.png ../share/grafx2/fonts/PF_Easta_7_.png ../share/grafx2/fonts/PF_Easta_7__.png ../share/grafx2/fonts/PF_Ronda_7__.png ../share/grafx2/fonts/PF_Tempesta_5.png ../share/grafx2/fonts/PF_Tempesta_5_.png ../share/grafx2/fonts/PF_Tempesta_5__.png ../share/grafx2/fonts/PF_Tempesta_5___.png ../share/grafx2/fonts/PF_Tempesta_7.png ../share/grafx2/fonts/PF_Tempesta_7_.png ../share/grafx2/fonts/PF_Tempesta_7__.png ../share/grafx2/fonts/PF_Tempesta_7___.png ../share/grafx2/fonts/PF_Westa_7_.png ../share/grafx2/fonts/PF_Westa_7__.png
ifeq ($(PLATFORM),Darwin) ifeq ($(PLATFORM),Darwin)
all : $(MACAPPEXE) all : $(MACAPPEXE)
@ -316,11 +371,11 @@ $(MACAPPEXE) : $(BIN)
rm -rf Grafx2.app rm -rf Grafx2.app
mkdir -p Grafx2.app Grafx2.app/Contents Grafx2.app/Contents/Frameworks Grafx2.app/Contents/MacOS Grafx2.app/Contents/Resources mkdir -p Grafx2.app Grafx2.app/Contents Grafx2.app/Contents/Frameworks Grafx2.app/Contents/MacOS Grafx2.app/Contents/Resources
echo 'APPL????' > Grafx2.app/Contents/PkgInfo echo 'APPL????' > Grafx2.app/Contents/PkgInfo
cp Info.plist Grafx2.app/Contents cp ../Info.plist Grafx2.app/Contents
cp -r English.lproj Grafx2.app/Contents/Resources cp -r English.lproj Grafx2.app/Contents/Resources
cp -r fonts Grafx2.app/Contents/Resources cp -r ../share/grafx2/fonts Grafx2.app/Contents/Resources
cp -r skins Grafx2.app/Contents/Resources cp -r ../share/grafx2/skins Grafx2.app/Contents/Resources
cp -r gfx2def.ini Grafx2.app/Contents/Resources cp -r ../share/grafx2/gfx2def.ini Grafx2.app/Contents/Resources
cp -Rp $(FWDIR)/SDL.framework Grafx2.app/Contents/Frameworks cp -Rp $(FWDIR)/SDL.framework Grafx2.app/Contents/Frameworks
cp -Rp $(FWDIR)/SDL_image.framework Grafx2.app/Contents/Frameworks cp -Rp $(FWDIR)/SDL_image.framework Grafx2.app/Contents/Frameworks
cp -Rp $(FWDIR)/SDL_ttf.framework Grafx2.app/Contents/Frameworks cp -Rp $(FWDIR)/SDL_ttf.framework Grafx2.app/Contents/Frameworks
@ -341,9 +396,9 @@ ziprelease: version $(BIN) release
echo `sed "s/.*=\"\(.*\)\";/\1/" pversion.c`.`svnversion` | tr " :" "_-" | sed -e "s/\(wip\)\\./\1/I" > $(OBJDIR)/versiontag echo `sed "s/.*=\"\(.*\)\";/\1/" pversion.c`.`svnversion` | tr " :" "_-" | sed -e "s/\(wip\)\\./\1/I" > $(OBJDIR)/versiontag
tar cvzf "../src-`cat $(OBJDIR)/versiontag`.tgz" --strip=1 ../src/*.c ../src/*.h ../src/Makefile ../src/Makefile.dep ../src/gfx2.ico tar cvzf "../src-`cat $(OBJDIR)/versiontag`.tgz" --strip=1 ../src/*.c ../src/*.h ../src/Makefile ../src/Makefile.dep ../src/gfx2.ico
cd .. && $(ZIP) $(ZIPOPT) "grafx2-`cat $(OBJDIR:../%=%)/versiontag`$(TTFLABEL)-$(PLATFORM).$(ZIP)" $(BIN:../%=%) share/grafx2/gfx2def.ini $(SCRIPT_FILES:../%=%) $(SKIN_FILES:../%=%) share/grafx2/gfx2.gif share/icons/grafx2.svg doc/README.txt doc/COMPILING.txt doc/gpl-2.0.txt share/grafx2/fonts/8pxfont.png doc/README-zlib1.txt doc/README-SDL.txt doc/README-SDL_image.txt doc/README-SDL_ttf.txt doc/README-lua.txt share/grafx2/fonts/Tuffy.ttf src-`cat $(OBJDIR:../%=%)/versiontag`.tgz $(PLATFORMFILES:../%=%) cd .. && $(ZIP) $(ZIPOPT) "grafx2-`cat $(OBJDIR:../%=%)/versiontag`$(TTFLABEL)-$(PLATFORM).$(ZIP)" $(BIN:../%=%) share/grafx2/gfx2def.ini $(SCRIPT_FILES:../%=%) $(SCRIPTLIB_FILES:../%=%) $(SKIN_FILES:../%=%) share/grafx2/gfx2.gif share/icons/grafx2.svg doc/README.txt doc/COMPILING.txt doc/gpl-2.0.txt doc/PF_fonts.txt $(FONT_FILES:../%=%) doc/README-zlib1.txt doc/README-SDL.txt doc/README-SDL_image.txt doc/README-SDL_ttf.txt doc/README-lua.txt src-`cat $(OBJDIR:../%=%)/versiontag`.tgz $(PLATFORMFILES:../%=%)
$(DELCOMMAND) "../src-`cat $(OBJDIR)/versiontag`.tgz" $(DELCOMMAND) "../src-`cat $(OBJDIR)/versiontag`.tgz"
tar cvzf "../grafx2-`cat $(OBJDIR)/versiontag`$(TTFLABEL)-src.tgz" --strip=1 --transform 's,^,grafx2/,g' ../src/*.c ../src/*.h ../src/Makefile ../src/Makefile.dep ../share/grafx2/gfx2def.ini $(SCRIPT_FILES) $(SKIN_FILES) ../src/gfx2.ico ../share/grafx2/gfx2.gif ../share/icons/grafx2.svg ../doc/README.txt ../doc/COMPILING.txt ../doc/gpl-2.0.txt ../misc/unix/grafx2.1 ../misc/unix/grafx2.xpm ../misc/unix/grafx2.desktop ../share/grafx2/fonts/8pxfont.png ../share/grafx2/fonts/Tuffy.ttf tar cvzf "../grafx2-`cat $(OBJDIR)/versiontag`$(TTFLABEL)-src.tgz" --strip=1 --transform 's,^,grafx2/,g' ../src/*.c ../src/*.h ../src/Makefile ../src/Makefile.dep ../share/grafx2/gfx2def.ini $(SCRIPT_FILES) $(SCRIPTLIB_FILES) $(SKIN_FILES) ../src/gfx2.ico ../share/grafx2/gfx2.gif ../share/icons/grafx2.svg ../doc/README.txt ../doc/COMPILING.txt ../doc/gpl-2.0.txt ../doc/PF_fonts.txt ../misc/unix/grafx2.1 ../misc/unix/grafx2.xpm ../misc/unix/grafx2.desktop $(FONT_FILES)
$(DELCOMMAND) "$(OBJDIR)/versiontag" $(DELCOMMAND) "$(OBJDIR)/versiontag"
testsed : testsed :
@ -400,8 +455,9 @@ install : $(BIN)
test -d $(DESTDIR)$(datadir)/grafx2/fonts || $(MKDIR) $(DESTDIR)$(datadir)/grafx2/fonts test -d $(DESTDIR)$(datadir)/grafx2/fonts || $(MKDIR) $(DESTDIR)$(datadir)/grafx2/fonts
test -d $(DESTDIR)$(datadir)/grafx2/skins || $(MKDIR) $(DESTDIR)$(datadir)/grafx2/skins test -d $(DESTDIR)$(datadir)/grafx2/skins || $(MKDIR) $(DESTDIR)$(datadir)/grafx2/skins
test -d $(DESTDIR)$(datadir)/grafx2/scripts || $(MKDIR) $(DESTDIR)$(datadir)/grafx2/scripts test -d $(DESTDIR)$(datadir)/grafx2/scripts || $(MKDIR) $(DESTDIR)$(datadir)/grafx2/scripts
test -d $(DESTDIR)$(datadir)/grafx2/scripts/libs || $(MKDIR) $(DESTDIR)$(datadir)/grafx2/scripts/libs
test -d $(DESTDIR)$(datadir)/applications || $(MKDIR) $(DESTDIR)$(datadir)/applications test -d $(DESTDIR)$(datadir)/applications || $(MKDIR) $(DESTDIR)$(datadir)/applications
test -d $(DESTDIR)$(datadir)/icons || $(MKDIR) $(DESTDIR)$(datadir)/icons test -d $(DESTDIR)$(pixmapdir) || $(MKDIR) $(DESTDIR)$(pixmapdir)
# Copy files # Copy files
$(CP) $(BIN) $(DESTDIR)$(bindir) $(CP) $(BIN) $(DESTDIR)$(bindir)
$(CP) ../share/grafx2/gfx2def.ini $(DESTDIR)$(datadir)/grafx2/ $(CP) ../share/grafx2/gfx2def.ini $(DESTDIR)$(datadir)/grafx2/
@ -409,10 +465,11 @@ install : $(BIN)
$(CP) ../share/grafx2/fonts/* $(DESTDIR)$(datadir)/grafx2/fonts/ $(CP) ../share/grafx2/fonts/* $(DESTDIR)$(datadir)/grafx2/fonts/
$(CP) $(SKIN_FILES) $(DESTDIR)$(datadir)/grafx2/skins/ $(CP) $(SKIN_FILES) $(DESTDIR)$(datadir)/grafx2/skins/
$(CP) $(SCRIPT_FILES) $(DESTDIR)$(datadir)/grafx2/scripts/ $(CP) $(SCRIPT_FILES) $(DESTDIR)$(datadir)/grafx2/scripts/
$(CP) $(SCRIPTLIB_FILES) $(DESTDIR)$(datadir)/grafx2/scripts/libs/
# Icon and desktop file for debian # Icon and desktop file for debian
$(CP) ../misc/unix/grafx2.desktop $(DESTDIR)$(datadir)/applications/ $(CP) ../misc/unix/grafx2.desktop $(DESTDIR)$(datadir)/applications/
$(CP) ../misc/unix/grafx2.xpm $(DESTDIR)$(datadir)/icons/ $(CP) ../misc/unix/grafx2.xpm $(DESTDIR)$(pixmapdir)
$(CP) ../share/icons/grafx2.svg $(DESTDIR)$(datadir)/icons/ $(CP) ../share/icons/grafx2.svg $(DESTDIR)$(pixmapdir)
@echo Install complete @echo Install complete
# Linux uninstallation of the program # Linux uninstallation of the program
@ -424,13 +481,15 @@ uninstall :
$(if $(wildcard $(DESTDIR)$(datadir)/grafx2/fonts),,$(RMDIR) $(DESTDIR)$(datadir)/grafx2/fonts) $(if $(wildcard $(DESTDIR)$(datadir)/grafx2/fonts),,$(RMDIR) $(DESTDIR)$(datadir)/grafx2/fonts)
$(DELCOMMAND) $(SKIN_FILES:../share%=$(DESTDIR)$(datadir)%) $(DELCOMMAND) $(SKIN_FILES:../share%=$(DESTDIR)$(datadir)%)
$(if $(wildcard $(DESTDIR)$(datadir)/grafx2/skins),,$(RMDIR) $(DESTDIR)$(datadir)/grafx2/skins) $(if $(wildcard $(DESTDIR)$(datadir)/grafx2/skins),,$(RMDIR) $(DESTDIR)$(datadir)/grafx2/skins)
$(DELCOMMAND) $(SCRIPTLIB_FILES:../share%=$(DESTDIR)$(datadir)%)
$(if $(wildcard $(DESTDIR)$(datadir)/grafx2/scripts/libs),,$(RMDIR) $(DESTDIR)$(datadir)/grafx2/scripts/libs)
$(DELCOMMAND) $(SCRIPT_FILES:../share%=$(DESTDIR)$(datadir)%) $(DELCOMMAND) $(SCRIPT_FILES:../share%=$(DESTDIR)$(datadir)%)
$(if $(wildcard $(DESTDIR)$(datadir)/grafx2/scripts),,$(RMDIR) $(DESTDIR)$(datadir)/grafx2/scripts) $(if $(wildcard $(DESTDIR)$(datadir)/grafx2/scripts),,$(RMDIR) $(DESTDIR)$(datadir)/grafx2/scripts)
$(if $(wildcard $(DESTDIR)$(datadir)/grafx2),,$(RMDIR) $(DESTDIR)$(datadir)/grafx2) $(if $(wildcard $(DESTDIR)$(datadir)/grafx2),,$(RMDIR) $(DESTDIR)$(datadir)/grafx2)
# Icon and desktop file for debian # Icon and desktop file for debian
$(DELCOMMAND) $(DESTDIR)$(datadir)/applications/grafx2.desktop $(DELCOMMAND) $(DESTDIR)$(datadir)/applications/grafx2.desktop
$(DELCOMMAND) $(DESTDIR)$(datadir)/icons/grafx2.xpm $(DELCOMMAND) $(DESTDIR)$(pixmapdir)/grafx2.xpm
$(DELCOMMAND) $(DESTDIR)$(datadir)/icons/grafx2.svg $(DELCOMMAND) $(DESTDIR)$(pixmapdir)/grafx2.svg
@echo Uninstall complete @echo Uninstall complete
endif endif

View File

@ -1,3 +1,4 @@
$(OBJDIR)/SFont.o: SFont.c SFont.h
$(OBJDIR)/brush.o: brush.c global.h struct.h const.h graph.h misc.h errors.h \ $(OBJDIR)/brush.o: brush.c global.h struct.h const.h graph.h misc.h errors.h \
windows.h sdlscreen.h brush.h windows.h sdlscreen.h brush.h
$(OBJDIR)/brush_ops.o: brush_ops.c brush.h struct.h const.h buttons.h engine.h \ $(OBJDIR)/brush_ops.o: brush_ops.c brush.h struct.h const.h buttons.h engine.h \
@ -5,12 +6,13 @@ $(OBJDIR)/brush_ops.o: brush_ops.c brush.h struct.h const.h buttons.h engine.h \
$(OBJDIR)/buttons.o: buttons.c const.h struct.h global.h misc.h graph.h engine.h \ $(OBJDIR)/buttons.o: buttons.c const.h struct.h global.h misc.h graph.h engine.h \
readline.h filesel.h loadsave.h init.h buttons.h operatio.h pages.h \ readline.h filesel.h loadsave.h init.h buttons.h operatio.h pages.h \
palette.h errors.h readini.h saveini.h shade.h io.h help.h text.h \ palette.h errors.h readini.h saveini.h shade.h io.h help.h text.h \
sdlscreen.h windows.h brush.h input.h special.h sdlscreen.h windows.h brush.h input.h special.h setup.h
$(OBJDIR)/buttons_effects.o: buttons_effects.c buttons.h struct.h const.h engine.h \ $(OBJDIR)/buttons_effects.o: buttons_effects.c buttons.h struct.h const.h engine.h \
global.h graph.h help.h input.h misc.h readline.h sdlscreen.h windows.h global.h graph.h help.h input.h misc.h readline.h sdlscreen.h windows.h \
brush.h
$(OBJDIR)/engine.o: engine.c const.h struct.h global.h graph.h misc.h special.h \ $(OBJDIR)/engine.o: engine.c const.h struct.h global.h graph.h misc.h special.h \
buttons.h operatio.h shade.h errors.h sdlscreen.h windows.h brush.h \ buttons.h operatio.h shade.h errors.h sdlscreen.h windows.h brush.h \
input.h engine.h pages.h layers.h input.h engine.h pages.h layers.h factory.h loadsave.h io.h
$(OBJDIR)/factory.o: factory.c brush.h struct.h const.h buttons.h engine.h errors.h \ $(OBJDIR)/factory.o: factory.c brush.h struct.h const.h buttons.h engine.h errors.h \
filesel.h loadsave.h global.h graph.h io.h misc.h pages.h readline.h \ filesel.h loadsave.h global.h graph.h io.h misc.h pages.h readline.h \
sdlscreen.h windows.h palette.h input.h help.h sdlscreen.h windows.h palette.h input.h help.h
@ -21,7 +23,8 @@ $(OBJDIR)/filesel.o: filesel.c const.h struct.h global.h misc.h errors.h io.h \
help.h filesel.h help.h filesel.h
$(OBJDIR)/graph.o: graph.c global.h struct.h const.h engine.h buttons.h pages.h \ $(OBJDIR)/graph.o: graph.c global.h struct.h const.h engine.h buttons.h pages.h \
errors.h sdlscreen.h graph.h misc.h pxsimple.h pxtall.h pxwide.h \ errors.h sdlscreen.h graph.h misc.h pxsimple.h pxtall.h pxwide.h \
pxdouble.h pxtriple.h pxwide2.h pxtall2.h pxquad.h windows.h input.h pxdouble.h pxtriple.h pxwide2.h pxtall2.h pxquad.h windows.h input.h \
brush.h
$(OBJDIR)/help.o: help.c const.h struct.h global.h misc.h engine.h helpfile.h \ $(OBJDIR)/help.o: help.c const.h struct.h global.h misc.h engine.h helpfile.h \
help.h sdlscreen.h text.h keyboard.h windows.h input.h hotkeys.h \ help.h sdlscreen.h text.h keyboard.h windows.h input.h hotkeys.h \
errors.h pages.h errors.h pages.h
@ -29,9 +32,9 @@ $(OBJDIR)/hotkeys.o: hotkeys.c struct.h const.h global.h hotkeys.h
$(OBJDIR)/init.o: init.c buttons.h struct.h const.h errors.h global.h graph.h \ $(OBJDIR)/init.o: init.c buttons.h struct.h const.h errors.h global.h graph.h \
init.h io.h factory.h help.h hotkeys.h keyboard.h loadsave.h misc.h \ init.h io.h factory.h help.h hotkeys.h keyboard.h loadsave.h misc.h \
mountlist.h operatio.h palette.h sdlscreen.h setup.h transform.h \ mountlist.h operatio.h palette.h sdlscreen.h setup.h transform.h \
windows.h layers.h windows.h layers.h special.h
$(OBJDIR)/input.o: input.c global.h struct.h const.h keyboard.h sdlscreen.h \ $(OBJDIR)/input.o: input.c global.h struct.h const.h keyboard.h sdlscreen.h \
windows.h errors.h misc.h input.h windows.h errors.h misc.h buttons.h input.h loadsave.h
$(OBJDIR)/io.o: io.c struct.h const.h io.h realpath.h $(OBJDIR)/io.o: io.c struct.h const.h io.h realpath.h
$(OBJDIR)/keyboard.o: keyboard.c global.h struct.h const.h keyboard.h $(OBJDIR)/keyboard.o: keyboard.c global.h struct.h const.h keyboard.h
$(OBJDIR)/layers.o: layers.c const.h struct.h global.h windows.h engine.h pages.h \ $(OBJDIR)/layers.o: layers.c const.h struct.h global.h windows.h engine.h pages.h \
@ -39,18 +42,20 @@ $(OBJDIR)/layers.o: layers.c const.h struct.h global.h windows.h engine.h pages.
$(OBJDIR)/libraw2crtc.o: libraw2crtc.c const.h global.h struct.h loadsave.h $(OBJDIR)/libraw2crtc.o: libraw2crtc.c const.h global.h struct.h loadsave.h
$(OBJDIR)/loadsave.o: loadsave.c buttons.h struct.h const.h errors.h global.h io.h \ $(OBJDIR)/loadsave.o: loadsave.c buttons.h struct.h const.h errors.h global.h io.h \
loadsave.h misc.h graph.h op_c.h pages.h palette.h sdlscreen.h windows.h \ loadsave.h misc.h graph.h op_c.h pages.h palette.h sdlscreen.h windows.h \
engine.h engine.h brush.h setup.h
$(OBJDIR)/main.o: main.c const.h struct.h global.h graph.h misc.h init.h buttons.h \ $(OBJDIR)/main.o: main.c const.h struct.h global.h graph.h misc.h init.h buttons.h \
engine.h pages.h loadsave.h sdlscreen.h errors.h readini.h saveini.h \ engine.h pages.h loadsave.h sdlscreen.h errors.h readini.h saveini.h \
io.h text.h setup.h windows.h brush.h palette.h realpath.h io.h text.h setup.h windows.h brush.h palette.h realpath.h input.h
$(OBJDIR)/misc.o: misc.c struct.h const.h sdlscreen.h global.h errors.h buttons.h \ $(OBJDIR)/misc.o: misc.c struct.h const.h sdlscreen.h global.h errors.h buttons.h \
engine.h misc.h keyboard.h windows.h palette.h input.h graph.h pages.h engine.h misc.h keyboard.h windows.h palette.h input.h graph.h pages.h
$(OBJDIR)/miscfileformats.o: miscfileformats.c engine.h struct.h const.h errors.h \ $(OBJDIR)/miscfileformats.o: miscfileformats.c engine.h struct.h const.h errors.h \
global.h io.h libraw2crtc.h loadsave.h misc.h sdlscreen.h windows.h global.h io.h libraw2crtc.h loadsave.h misc.h sdlscreen.h windows.h
$(OBJDIR)/mountlist.o: mountlist.c mountlist.h $(OBJDIR)/mountlist.o: mountlist.c
$(OBJDIR)/op_c.o: op_c.c op_c.h struct.h const.h errors.h $(OBJDIR)/op_c.o: op_c.c op_c.h struct.h const.h errors.h global.h engine.h \
windows.h
$(OBJDIR)/operatio.o: operatio.c const.h struct.h global.h misc.h engine.h graph.h \ $(OBJDIR)/operatio.o: operatio.c const.h struct.h global.h misc.h engine.h graph.h \
operatio.h buttons.h pages.h errors.h sdlscreen.h brush.h windows.h operatio.h buttons.h pages.h errors.h sdlscreen.h brush.h windows.h \
input.h
$(OBJDIR)/pages.o: pages.c global.h struct.h const.h pages.h errors.h loadsave.h \ $(OBJDIR)/pages.o: pages.c global.h struct.h const.h pages.h errors.h loadsave.h \
misc.h windows.h misc.h windows.h
$(OBJDIR)/palette.o: palette.c const.h struct.h global.h misc.h engine.h readline.h \ $(OBJDIR)/palette.o: palette.c const.h struct.h global.h misc.h engine.h readline.h \
@ -63,34 +68,35 @@ $(OBJDIR)/pxquad.o: pxquad.c global.h struct.h const.h sdlscreen.h misc.h graph.
pxquad.h pxquad.h
$(OBJDIR)/pxsimple.o: pxsimple.c global.h struct.h const.h sdlscreen.h misc.h \ $(OBJDIR)/pxsimple.o: pxsimple.c global.h struct.h const.h sdlscreen.h misc.h \
graph.h pxsimple.h graph.h pxsimple.h
$(OBJDIR)/pxtall2.o: pxtall2.c global.h struct.h const.h sdlscreen.h misc.h graph.h \
pxtall2.h
$(OBJDIR)/pxtall.o: pxtall.c global.h struct.h const.h sdlscreen.h misc.h graph.h \ $(OBJDIR)/pxtall.o: pxtall.c global.h struct.h const.h sdlscreen.h misc.h graph.h \
pxtall.h pxsimple.h pxtall.h pxsimple.h
$(OBJDIR)/pxtall2.o: pxtall2.c global.h struct.h const.h sdlscreen.h misc.h graph.h \
pxtall2.h
$(OBJDIR)/pxtriple.o: pxtriple.c global.h struct.h const.h sdlscreen.h misc.h \ $(OBJDIR)/pxtriple.o: pxtriple.c global.h struct.h const.h sdlscreen.h misc.h \
graph.h pxtriple.h graph.h pxtriple.h
$(OBJDIR)/pxwide2.o: pxwide2.c global.h struct.h const.h sdlscreen.h misc.h graph.h \
pxwide2.h
$(OBJDIR)/pxwide.o: pxwide.c global.h struct.h const.h sdlscreen.h misc.h graph.h \ $(OBJDIR)/pxwide.o: pxwide.c global.h struct.h const.h sdlscreen.h misc.h graph.h \
pxwide.h pxwide.h
$(OBJDIR)/readini.o: readini.c const.h errors.h global.h struct.h misc.h readini.h $(OBJDIR)/pxwide2.o: pxwide2.c global.h struct.h const.h sdlscreen.h misc.h graph.h \
pxwide2.h
$(OBJDIR)/readini.o: readini.c const.h errors.h global.h struct.h misc.h readini.h \
setup.h
$(OBJDIR)/readline.o: readline.c const.h struct.h global.h misc.h errors.h \ $(OBJDIR)/readline.o: readline.c const.h struct.h global.h misc.h errors.h \
sdlscreen.h readline.h windows.h input.h sdlscreen.h readline.h windows.h input.h
$(OBJDIR)/realpath.o: realpath.c $(OBJDIR)/realpath.o: realpath.c
$(OBJDIR)/saveini.o: saveini.c const.h global.h struct.h readini.h io.h errors.h \ $(OBJDIR)/saveini.o: saveini.c const.h global.h struct.h readini.h io.h errors.h \
misc.h saveini.h misc.h saveini.h setup.h
$(OBJDIR)/sdlscreen.o: sdlscreen.c global.h struct.h const.h sdlscreen.h errors.h \ $(OBJDIR)/sdlscreen.o: sdlscreen.c global.h struct.h const.h sdlscreen.h errors.h \
misc.h misc.h
$(OBJDIR)/setup.o: setup.c struct.h const.h io.h setup.h $(OBJDIR)/setup.o: setup.c struct.h const.h io.h setup.h
$(OBJDIR)/SFont.o: SFont.c SFont.h
$(OBJDIR)/shade.o: shade.c global.h struct.h const.h graph.h engine.h errors.h \ $(OBJDIR)/shade.o: shade.c global.h struct.h const.h graph.h engine.h errors.h \
misc.h readline.h help.h sdlscreen.h windows.h input.h shade.h misc.h readline.h help.h sdlscreen.h windows.h input.h shade.h
$(OBJDIR)/special.o: special.c const.h struct.h global.h graph.h engine.h windows.h \ $(OBJDIR)/special.o: special.c const.h struct.h global.h graph.h engine.h windows.h \
special.h pages.h misc.h buttons.h special.h pages.h misc.h buttons.h
$(OBJDIR)/text.o: text.c SFont.h struct.h const.h global.h sdlscreen.h io.h \ $(OBJDIR)/text.o: text.c SFont.h struct.h const.h global.h sdlscreen.h io.h \
errors.h errors.h windows.h misc.h setup.h
$(OBJDIR)/tiles.o: tiles.c
$(OBJDIR)/transform.o: transform.c global.h struct.h const.h transform.h engine.h \ $(OBJDIR)/transform.o: transform.c global.h struct.h const.h transform.h engine.h \
sdlscreen.h windows.h input.h help.h misc.h readline.h buttons.h pages.h sdlscreen.h windows.h input.h help.h misc.h readline.h buttons.h pages.h
$(OBJDIR)/version.o: version.c $(OBJDIR)/version.o: version.c
$(OBJDIR)/windows.o: windows.c windows.h struct.h const.h engine.h errors.h \ $(OBJDIR)/windows.o: windows.c windows.h struct.h const.h engine.h errors.h \
global.h graph.h input.h misc.h readline.h sdlscreen.h global.h graph.h input.h misc.h op_c.h readline.h sdlscreen.h palette.h

View File

@ -69,7 +69,7 @@ static Uint32 GetPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y)
SFont_Font* SFont_InitFont(SDL_Surface* Surface) SFont_Font* SFont_InitFont(SDL_Surface* Surface)
{ {
int x = 0, i = 0; int x = 0, i = 33;
Uint32 pixel; Uint32 pixel;
SFont_Font* Font; SFont_Font* Font;
Uint32 pink; Uint32 pink;
@ -78,21 +78,42 @@ SFont_Font* SFont_InitFont(SDL_Surface* Surface)
return NULL; return NULL;
Font = (SFont_Font *) malloc(sizeof(SFont_Font)); Font = (SFont_Font *) malloc(sizeof(SFont_Font));
memset(Font, 0, sizeof(SFont_Font));
Font->Surface = Surface; Font->Surface = Surface;
SDL_LockSurface(Surface); SDL_LockSurface(Surface);
pink = SDL_MapRGB(Surface->format, 255, 0, 255); pink = GetPixel(Surface, 0, 0);
while (x < Surface->w) { while (x < Surface->w) {
if (GetPixel(Surface, x, 0) == pink) { if (GetPixel(Surface, x, 0) != pink) {
Font->CharPos[i++]=x; Font->CharBegin[i]=x;
while((x < Surface->w) && (GetPixel(Surface, x, 0)== pink)) while((x < Surface->w) && (GetPixel(Surface, x, 0)!= pink))
x++; x++;
Font->CharPos[i++]=x; Font->CharWidth[i]=x-Font->CharBegin[i];
i++;
} }
x++; x++;
} }
Font->MaxPos = x-1;
// Create lowercase characters, if not present
for (i=0; i <26; i++)
{
if (Font->CharWidth['a'+i]==0)
{
Font->CharBegin['a'+i]=Font->CharBegin['A'+i];
Font->CharWidth['a'+i]=Font->CharWidth['A'+i];
}
}
// Determine space width.
// This strange format doesn't allow font designer to write explicit
// space as a character.
// Rule: A space should be as large as the character " if available,
// or 'a' if it's not.
Font->Space = Font->CharWidth[(int)'"'];
if (Font->Space<2)
Font->Space = Font->CharWidth[(int)'a'];
pixel = GetPixel(Surface, 0, Surface->h-1); pixel = GetPixel(Surface, 0, Surface->h-1);
SDL_UnlockSurface(Surface); SDL_UnlockSurface(Surface);
@ -111,7 +132,6 @@ void SFont_Write(SDL_Surface *Surface, const SFont_Font *Font,
int x, int y, const char *text) int x, int y, const char *text)
{ {
const char* c; const char* c;
int charoffset;
SDL_Rect srcrect, dstrect; SDL_Rect srcrect, dstrect;
if(text == NULL) if(text == NULL)
@ -123,42 +143,39 @@ void SFont_Write(SDL_Surface *Surface, const SFont_Font *Font,
srcrect.h = dstrect.h = Font->Surface->h - 1; srcrect.h = dstrect.h = Font->Surface->h - 1;
for(c = text; *c != '\0' && x <= Surface->w ; c++) { for(c = text; *c != '\0' && x <= Surface->w ; c++) {
charoffset = ((int) (*c - 33)) * 2 + 1;
// skip spaces and nonprintable characters // skip spaces and nonprintable characters
if (*c == ' ' || charoffset < 0 || charoffset > Font->MaxPos) { if (*c == ' ' || Font->CharWidth[(int)*c]==0) {
x += Font->CharPos[2]-Font->CharPos[1]; x += Font->Space;
continue; continue;
} }
srcrect.w = Font->CharPos[charoffset+2] - Font->CharPos[charoffset]; srcrect.w = Font->CharWidth[(int)*c];
dstrect.w = srcrect.w; dstrect.w = srcrect.w;
srcrect.x = Font->CharPos[charoffset]; srcrect.x = Font->CharBegin[(int)*c];
dstrect.x = x; dstrect.x = x;
SDL_BlitSurface(Font->Surface, &srcrect, Surface, &dstrect); SDL_BlitSurface(Font->Surface, &srcrect, Surface, &dstrect);
x += Font->CharPos[charoffset+1] - Font->CharPos[charoffset]; x += Font->CharWidth[(int)*c];
} }
} }
int SFont_TextWidth(const SFont_Font *Font, const char *text) int SFont_TextWidth(const SFont_Font *Font, const char *text)
{ {
const char* c; const char* c;
int charoffset=0;
int width = 0; int width = 0;
if(text == NULL) if(text == NULL)
return 0; return 0;
for(c = text; *c != '\0'; c++) { for(c = text; *c != '\0'; c++) {
charoffset = ((int) *c - 33) * 2 + 1;
// skip spaces and nonprintable characters // skip spaces and nonprintable characters
if (*c == ' ' || charoffset < 0 || charoffset > Font->MaxPos) { if (*c == ' ' || Font->CharWidth[(int)*c]==0) {
width += Font->CharPos[2]-Font->CharPos[1]; width += Font->Space;
continue; continue;
} }
width += Font->CharPos[charoffset+1] - Font->CharPos[charoffset]; width += Font->CharWidth[(int)*c];
} }
return width; return width;

View File

@ -56,8 +56,9 @@ extern "C" {
/// and call InitFont( YourFont ); /// and call InitFont( YourFont );
typedef struct { typedef struct {
SDL_Surface *Surface; SDL_Surface *Surface;
int CharPos[512]; int CharBegin[256];
int MaxPos; int CharWidth[256];
int Space;
} SFont_Font; } SFont_Font;
/// ///

View File

@ -587,66 +587,97 @@ void Display_paintbrush(short x,short y,byte color,byte is_preview)
} }
} }
/// /// @return 0 on success, non-zero on failure (memory?).
/// Changes the Brush size, discarding its previous content. /// @param new_brush: Optionally, you can provide an already allocated new
/// @return 0 OK, 1 Failed /// brush - otherwise, this function performs the allocation.
byte Realloc_brush(word new_brush_width, word new_brush_height) /// @param old_brush: If the caller passes NULL, this function will free the old
/// pixel data. If the caller provides the address of a (free) byte
/// pointer, the function will make it point to the original pixel data,
/// in this case it will be the caller's responsibility to free() it
/// (after transferring pixels to Brush, usually).
byte Realloc_brush(word new_brush_width, word new_brush_height, byte *new_brush, byte **old_brush)
{ {
byte return_code=0;
byte *new_smear_brush;
byte *new_brush_remapped;
word new_smear_brush_width;
word new_smear_brush_height;
byte new_brush_is_provided;
new_brush_is_provided = (new_brush!=NULL);
if (!new_brush_is_provided)
{
new_brush=(byte *)malloc(((long)new_brush_height)*new_brush_width);
if (new_brush == NULL)
{
Error(0);
if (old_brush)
*old_brush=NULL;
return 1;
}
}
new_smear_brush_width=(new_brush_width>MAX_PAINTBRUSH_SIZE)?new_brush_width:MAX_PAINTBRUSH_SIZE;
new_smear_brush_height=(new_brush_height>MAX_PAINTBRUSH_SIZE)?new_brush_height:MAX_PAINTBRUSH_SIZE;
new_smear_brush=NULL;
if ( (((long)Smear_brush_height)*Smear_brush_width) !=
(((long)new_smear_brush_width)*new_smear_brush_height) )
{
new_smear_brush=(byte *)malloc(((long)new_smear_brush_height)*new_smear_brush_width);
if (new_smear_brush == NULL)
{
Error(0);
if (old_brush)
*old_brush=NULL;
if (!new_brush_is_provided)
free(new_brush);
return 2;
}
}
new_brush_remapped=NULL;
if ( (((long)Brush_height)*Brush_width) != if ( (((long)Brush_height)*Brush_width) !=
(((long)new_brush_height)*new_brush_width) ) (((long)new_brush_height)*new_brush_width) )
{ {
free(Brush); new_brush_remapped=(byte *)malloc(((long)new_brush_height)*new_brush_width);
Brush=(byte *)malloc(((long)new_brush_height)*new_brush_width); if (new_brush_remapped == NULL)
if (Brush == NULL)
{ {
Error(0); Error(0);
return_code=1; free(new_smear_brush);
if (old_brush)
Brush=(byte *)malloc(1*1); *old_brush=NULL;
if(Brush == NULL) if (!new_brush_is_provided)
{ free(new_brush);
Error(ERROR_MEMORY); return 3;
exit(ERROR_MEMORY);
}
new_brush_height=new_brush_width=1;
*Brush=Fore_color;
} }
} }
// All allocations successful: can replace globals
Brush_width=new_brush_width; Brush_width=new_brush_width;
Brush_height=new_brush_height; Brush_height=new_brush_height;
Brush_original_back_color=Back_color;
free(Smear_brush); if (new_smear_brush)
Smear_brush_width=(Brush_width>MAX_PAINTBRUSH_SIZE)?Brush_width:MAX_PAINTBRUSH_SIZE;
Smear_brush_height=(Brush_height>MAX_PAINTBRUSH_SIZE)?Brush_height:MAX_PAINTBRUSH_SIZE;
Smear_brush=(byte *)malloc(((long)Smear_brush_height)*Smear_brush_width);
if (Smear_brush == NULL) // Failed to allocate the smear brush
{ {
Error(0); free(Smear_brush);
return_code=1; Smear_brush=new_smear_brush;
free(Brush);
Brush=(byte *)malloc(1*1);
if(Brush == NULL)
{
Error(ERROR_MEMORY);
exit(ERROR_MEMORY);
}
Brush_height=1;
Brush_width=1;
Smear_brush=(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE);
if(Smear_brush == NULL)
{
Error(ERROR_MEMORY);
exit(ERROR_MEMORY);
}
Smear_brush_height=MAX_PAINTBRUSH_SIZE;
Smear_brush_width=MAX_PAINTBRUSH_SIZE;
} }
return return_code; Smear_brush_width=new_smear_brush_width;
Smear_brush_height=new_smear_brush_height;
// Save or free the old brush pixels
if (old_brush)
*old_brush=Brush_original_pixels;
else
free(old_brush);
Brush_original_pixels=new_brush;
// Assign new brush
if (new_brush_remapped)
{
free(Brush);
Brush=new_brush_remapped;
}
return 0;
} }
@ -828,7 +859,7 @@ void Capture_brush(short start_x,short start_y,short end_x,short end_y,short cle
if (start_y+new_brush_height>Main_image_height) if (start_y+new_brush_height>Main_image_height)
new_brush_height=Main_image_height-start_y; new_brush_height=Main_image_height-start_y;
if (Realloc_brush(new_brush_width, new_brush_height) != 0) if (Realloc_brush(new_brush_width, new_brush_height, NULL, NULL))
return; // Unable to allocate the new brush, keep the old one. return; // Unable to allocate the new brush, keep the old one.
Copy_image_to_brush(start_x,start_y,Brush_width,Brush_height,Main_image_width); Copy_image_to_brush(start_x,start_y,Brush_width,Brush_height,Main_image_width);
@ -843,6 +874,10 @@ void Capture_brush(short start_x,short start_y,short end_x,short end_y,short cle
} }
Update_part_of_screen(start_x,start_y,Brush_width,Brush_height); Update_part_of_screen(start_x,start_y,Brush_width,Brush_height);
} }
// Grab palette
memcpy(Brush_original_palette, Main_palette,sizeof(T_Palette));
// Remap (no change)
Remap_brush();
// On centre la prise sur la brosse // On centre la prise sur la brosse
Brush_offset_X=(Brush_width>>1); Brush_offset_X=(Brush_width>>1);
@ -851,32 +886,25 @@ void Capture_brush(short start_x,short start_y,short end_x,short end_y,short cle
} }
void Rotate_90_deg() void Rotate_90_deg(void)
{ {
short temp; byte * old_brush;
byte * new_brush;
new_brush=(byte *)malloc(((size_t)Brush_height)*Brush_width); if (Realloc_brush(Brush_height, Brush_width, NULL, &old_brush))
if (new_brush)
{ {
Rotate_90_deg_lowlevel(Brush,new_brush,Brush_width,Brush_height);
free(Brush);
Brush=new_brush;
temp=Brush_width;
Brush_width=Brush_height;
Brush_height=temp;
temp=Smear_brush_width;
Smear_brush_width=Smear_brush_height;
Smear_brush_height=temp;
// On centre la prise sur la brosse
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
}
else
Error(0); Error(0);
return;
}
Rotate_90_deg_lowlevel(old_brush,Brush_original_pixels,Brush_height,Brush_width);
free(old_brush);
// Remap according to the last used remap table
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
// On centre la prise sur la brosse
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
} }
@ -884,34 +912,45 @@ void Remap_brush(void)
{ {
short x_pos; // Variable de balayage de la brosse short x_pos; // Variable de balayage de la brosse
short y_pos; // Variable de balayage de la brosse short y_pos; // Variable de balayage de la brosse
byte used[256]; // Tableau de booléens "La couleur est utilisée"
int color; int color;
// On commence par initialiser le tableau de booléens à faux // On commence par initialiser le tableau de booléens à faux
for (color=0;color<=255;color++) for (color=0;color<=255;color++)
used[color]=0; Brush_colormap[color]=0;
// On calcule la table d'utilisation des couleurs // On calcule la table d'utilisation des couleurs
for (y_pos=0;y_pos<Brush_height;y_pos++) for (y_pos=0;y_pos<Brush_height;y_pos++)
for (x_pos=0;x_pos<Brush_width;x_pos++) for (x_pos=0;x_pos<Brush_width;x_pos++)
used[Read_pixel_from_brush(x_pos,y_pos)]=1; Brush_colormap[*(Brush_original_pixels + y_pos * Brush_width + x_pos)]=1;
// On n'est pas censé remapper la couleur de transparence, sinon la brosse // On n'est pas censé remapper la couleur de transparence, sinon la brosse
// changera de forme, donc on dit pour l'instant qu'elle n'est pas utilisée // changera de forme, donc on dit pour l'instant qu'elle n'est pas utilisée
// ainsi on ne s'embêtera pas à la recalculer // ainsi on ne s'embêtera pas à la recalculer
used[Back_color]=0; Brush_colormap[Back_color]=0;
// On va maintenant se servir de la table "used" comme table de // On va maintenant se servir de la table comme table de
// conversion: pour chaque indice, la table donne une couleur de // conversion: pour chaque indice, la table donne une couleur de
// remplacement. // remplacement.
// Note : Seules les couleurs utilisées on besoin d'êtres recalculées: les // Note : Seules les couleurs utilisées on besoin d'êtres recalculées: les
// autres ne seront jamais consultées dans la nouvelle table de // autres ne seront jamais consultées dans la nouvelle table de
// conversion puisque elles n'existent pas dans la brosse, donc elles // conversion puisque elles n'existent pas dans la brosse, donc elles
// ne seront pas utilisées par Remap_brush_LOWLEVEL. // ne seront pas utilisées par Remap_general_lowlevel.
for (color=0;color<=255;color++) for (color=0;color<=255;color++)
if (used[color] != 0) if (Brush_colormap[color] != 0)
used[color]=Best_color(Spare_palette[color].R,Spare_palette[color].G,Spare_palette[color].B); {
byte r,g,b;
r=Brush_original_palette[color].R;
g=Brush_original_palette[color].G;
b=Brush_original_palette[color].B;
// When remapping to same palette, ensure we keep same color index
if (r==Main_palette[color].R && g==Main_palette[color].G && b==Main_palette[color].B)
Brush_colormap[color]=color;
else
// Usual method: closest by r g b
Brush_colormap[color]=Best_color_perceptual(r,g,b);
}
// Il reste une couleur non calculée dans la table qu'il faut mettre à // Il reste une couleur non calculée dans la table qu'il faut mettre à
// jour: c'est la couleur de fond. On l'avait inhibée pour éviter son // jour: c'est la couleur de fond. On l'avait inhibée pour éviter son
@ -919,13 +958,13 @@ void Remap_brush(void)
// la brosse, on va mettre dans la table une relation d'équivalence entre // la brosse, on va mettre dans la table une relation d'équivalence entre
// les deux palettes: comme on ne veut pas que la couleur soit remplacée, // les deux palettes: comme on ne veut pas que la couleur soit remplacée,
// on va dire qu'on veut qu'elle soit remplacée par la couleur en question. // on va dire qu'on veut qu'elle soit remplacée par la couleur en question.
used[Back_color]=Back_color; Brush_colormap[Back_color]=Back_color;
// Maintenant qu'on a une super table de conversion qui n'a que le nom // Maintenant qu'on a une super table de conversion qui n'a que le nom
// qui craint un peu, on peut faire l'échange dans la brosse de toutes les // qui craint un peu, on peut faire l'échange dans la brosse de toutes les
// teintes. // teintes.
Remap_general_lowlevel(used,Brush,Brush_width,Brush_height,Brush_width); Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
//Remap_brush_LOWLEVEL(used);
} }
@ -934,104 +973,97 @@ void Outline_brush(void)
{ {
long /*Pos,*/x_pos,y_pos; long /*Pos,*/x_pos,y_pos;
byte state; byte state;
byte * new_brush; byte * old_brush;
byte * temp; word old_width;
word width; word old_height;
word height; int i;
old_width=Brush_width;
old_height=Brush_height;
width=Brush_width+2; SWAP_PBYTES(Brush, Brush_original_pixels);
height=Brush_height+2; if(Realloc_brush(Brush_width+2, Brush_height+2, NULL, &old_brush))
new_brush=(byte *)malloc(((long)width)*height);
if (new_brush)
{ {
// On remplit la bordure ajoutée par la Backcolor Error(0);
memset(new_brush,Back_color,((long)width)*height); SWAP_PBYTES(Brush, Brush_original_pixels);
return;
}
// On copie la brosse courante dans la nouvelle // On remplit la bordure ajoutée par la Backcolor
Copy_part_of_image_to_another(Brush, // source memset(Brush,Back_color,((long)Brush_width)*Brush_height);
0, 0, Brush_width, Brush_height, Brush_width,
new_brush, // Destination
1, 1, width);
// On intervertit la nouvelle et l'ancienne brosse: // On copie la brosse courante dans la nouvelle
temp=Brush; Copy_part_of_image_to_another(old_brush, // source
Brush=new_brush; 0, 0, old_width, old_height, old_width,
Brush_width+=2; Brush, // Destination
Brush_height+=2; 1, 1, Brush_width);
width-=2;
height-=2;
// Si on "outline" avec une couleur différente de la Back_color on y va! // Si on "outline" avec une couleur différente de la Back_color on y va!
if (Fore_color!=Back_color) if (Fore_color!=Back_color)
{
// 1er balayage (horizontal)
for (y_pos=1; y_pos<Brush_height-1; y_pos++)
{ {
// 1er balayage (horizontal) state=0;
for (y_pos=1; y_pos<Brush_height-1; y_pos++)
{
state=0;
for (x_pos=1; x_pos<Brush_width-1; x_pos++)
{
if (temp[((y_pos-1)*width)+x_pos-1]==Back_color)
{
if (state != 0)
{
Pixel_in_brush(x_pos,y_pos,Fore_color);
state=0;
}
}
else if (state == 0)
{
Pixel_in_brush(x_pos-1,y_pos,Fore_color);
state=1;
}
}
// Cas du dernier pixel à droite de la ligne
if (state != 0)
Pixel_in_brush(x_pos,y_pos,Fore_color);
}
// 2ème balayage (vertical)
for (x_pos=1; x_pos<Brush_width-1; x_pos++) for (x_pos=1; x_pos<Brush_width-1; x_pos++)
{ {
state=0; if (old_brush[((y_pos-1)*old_width)+x_pos-1]==Back_color)
for (y_pos=1; y_pos<Brush_height-1; y_pos++)
{ {
if (temp[((y_pos-1)*width)+x_pos-1]==Back_color) if (state != 0)
{ {
if (state != 0) Pixel_in_brush(x_pos,y_pos,Fore_color);
{ state=0;
Pixel_in_brush(x_pos,y_pos,Fore_color);
state=0;
}
}
else if (state == 0)
{
Pixel_in_brush(x_pos,y_pos-1,Fore_color);
state=1;
} }
} }
// Cas du dernier pixel en bas de la colonne else if (state == 0)
if (state != 0) {
Pixel_in_brush(x_pos,y_pos,Fore_color); Pixel_in_brush(x_pos-1,y_pos,Fore_color);
state=1;
}
} }
// Cas du dernier pixel à droite de la ligne
if (state != 0)
Pixel_in_brush(x_pos,y_pos,Fore_color);
} }
// On recentre la prise sur la brosse // 2ème balayage (vertical)
Brush_offset_X=(Brush_width>>1); for (x_pos=1; x_pos<Brush_width-1; x_pos++)
Brush_offset_Y=(Brush_height>>1); {
state=0;
free(temp); // Libération de l'ancienne brosse for (y_pos=1; y_pos<Brush_height-1; y_pos++)
temp = NULL; {
if (old_brush[((y_pos-1)*old_width)+x_pos-1]==Back_color)
// Réallocation d'un buffer de Smear {
free(Smear_brush); if (state != 0)
Smear_brush_width=(Brush_width>MAX_PAINTBRUSH_SIZE)?Brush_width:MAX_PAINTBRUSH_SIZE; {
Smear_brush_height=(Brush_height>MAX_PAINTBRUSH_SIZE)?Brush_height:MAX_PAINTBRUSH_SIZE; Pixel_in_brush(x_pos,y_pos,Fore_color);
Smear_brush=(byte *)malloc(((long)Smear_brush_width)*Smear_brush_height); state=0;
}
}
else if (state == 0)
{
Pixel_in_brush(x_pos,y_pos-1,Fore_color);
state=1;
}
}
// Cas du dernier pixel en bas de la colonne
if (state != 0)
Pixel_in_brush(x_pos,y_pos,Fore_color);
}
} }
else // Adopt the current palette.
Error(0); // Pas assez de mémoire! memcpy(Brush_original_palette, Main_palette,sizeof(T_Palette));
memcpy(Brush_original_pixels, Brush, (long)Brush_width*Brush_height);
for (i=0; i<256; i++)
Brush_colormap[i]=i;
//--
// On recentre la prise sur la brosse
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
free(old_brush); // Libération de l'ancienne brosse
} }
@ -1039,112 +1071,105 @@ void Nibble_brush(void)
{ {
long x_pos,y_pos; long x_pos,y_pos;
byte state; byte state;
byte * new_brush; byte * old_brush;
byte * temp; word old_width;
word width; word old_height;
word height; int i;
if ( (Brush_width>2) && (Brush_height>2) ) if ( (Brush_width>2) && (Brush_height>2) )
{ {
width=Brush_width-2; old_width=Brush_width;
height=Brush_height-2; old_height=Brush_height;
new_brush=(byte *)malloc(((long)width)*height);
if (new_brush) SWAP_PBYTES(Brush, Brush_original_pixels);
if (Realloc_brush(Brush_width-2, Brush_height-2, NULL, &old_brush))
{ {
// On copie la brosse courante dans la nouvelle Error(0);
Copy_part_of_image_to_another(Brush, // source SWAP_PBYTES(Brush, Brush_original_pixels);
1, return;
1, }
width, // On copie l'ancienne brosse dans la nouvelle
height, Copy_part_of_image_to_another(old_brush, // source
Brush_width, 1,
new_brush, // Destination 1,
0, old_width-2,
0, old_height-2,
width); old_width,
Brush, // Destination
0,
0,
Brush_width);
// On intervertit la nouvelle et l'ancienne brosse: // 1er balayage (horizontal)
temp=Brush; for (y_pos=0; y_pos<Brush_height; y_pos++)
Brush=new_brush; {
Brush_width-=2; state=(old_brush[(y_pos+1)*old_width]!=Back_color);
Brush_height-=2;
width+=2;
height+=2;
// 1er balayage (horizontal)
for (y_pos=0; y_pos<Brush_height; y_pos++)
{
state=(temp[(y_pos+1)*width]!=Back_color);
for (x_pos=0; x_pos<Brush_width; x_pos++)
{
if (temp[((y_pos+1)*width)+x_pos+1]==Back_color)
{
if (state != 0)
{
if (x_pos>0)
Pixel_in_brush(x_pos-1,y_pos,Back_color);
state=0;
}
}
else
{
if (state == 0)
{
Pixel_in_brush(x_pos,y_pos,Back_color);
state=1;
}
}
}
// Cas du dernier pixel à droite de la ligne
if (temp[((y_pos+1)*width)+x_pos+1]==Back_color)
Pixel_in_brush(x_pos-1,y_pos,Back_color);
}
// 2ème balayage (vertical)
for (x_pos=0; x_pos<Brush_width; x_pos++) for (x_pos=0; x_pos<Brush_width; x_pos++)
{ {
state=(temp[width+x_pos+1]!=Back_color);; if (old_brush[((y_pos+1)*old_width)+x_pos+1]==Back_color)
for (y_pos=0; y_pos<Brush_height; y_pos++)
{ {
if (temp[((y_pos+1)*width)+x_pos+1]==Back_color) if (state != 0)
{ {
if (state) if (x_pos>0)
{ Pixel_in_brush(x_pos-1,y_pos,Back_color);
if (y_pos>0) state=0;
Pixel_in_brush(x_pos,y_pos-1,Back_color); }
state=0; }
} else
} {
else if (state == 0)
{ {
if (state == 0) Pixel_in_brush(x_pos,y_pos,Back_color);
{ state=1;
Pixel_in_brush(x_pos,y_pos,Back_color);
state=1;
}
} }
} }
// Cas du dernier pixel en bas de la colonne
if (temp[((y_pos+1)*width)+x_pos+1]==Back_color)
Pixel_in_brush(x_pos,y_pos-1,Back_color);
} }
// Cas du dernier pixel à droite de la ligne
// On recentre la prise sur la brosse if (old_brush[((y_pos+1)*old_width)+x_pos+1]==Back_color)
Brush_offset_X=(Brush_width>>1); Pixel_in_brush(x_pos-1,y_pos,Back_color);
Brush_offset_Y=(Brush_height>>1);
free(temp); // Libération de l'ancienne brosse
temp = NULL;
// Réallocation d'un buffer de Smear
free(Smear_brush);
Smear_brush_width=(Brush_width>MAX_PAINTBRUSH_SIZE)?Brush_width:MAX_PAINTBRUSH_SIZE;
Smear_brush_height=(Brush_height>MAX_PAINTBRUSH_SIZE)?Brush_height:MAX_PAINTBRUSH_SIZE;
Smear_brush=(byte *)malloc(((long)Smear_brush_width)*Smear_brush_height);
} }
else
Error(0); // Pas assez de mémoire! // 2ème balayage (vertical)
for (x_pos=0; x_pos<Brush_width; x_pos++)
{
state=(old_brush[old_width+x_pos+1]!=Back_color);;
for (y_pos=0; y_pos<Brush_height; y_pos++)
{
if (old_brush[((y_pos+1)*old_width)+x_pos+1]==Back_color)
{
if (state)
{
if (y_pos>0)
Pixel_in_brush(x_pos,y_pos-1,Back_color);
state=0;
}
}
else
{
if (state == 0)
{
Pixel_in_brush(x_pos,y_pos,Back_color);
state=1;
}
}
}
// Cas du dernier pixel en bas de la colonne
if (old_brush[((y_pos+1)*old_width)+x_pos+1]==Back_color)
Pixel_in_brush(x_pos,y_pos-1,Back_color);
}
free(old_brush);
// Adopt the current palette.
memcpy(Brush_original_palette, Main_palette,sizeof(T_Palette));
memcpy(Brush_original_pixels, Brush, (long)Brush_width*Brush_height);
for (i=0; i<256; i++)
Brush_colormap[i]=i;
//--
// On recentre la prise sur la brosse
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
} }
} }
@ -1162,7 +1187,6 @@ void Capture_brush_with_lasso(int vertices, short * points,short clear)
word new_brush_width; word new_brush_width;
word new_brush_height; word new_brush_height;
// On recherche les bornes de la brosse: // On recherche les bornes de la brosse:
for (temp=0; temp<2*vertices; temp+=2) for (temp=0; temp<2*vertices; temp+=2)
{ {
@ -1204,46 +1228,15 @@ void Capture_brush_with_lasso(int vertices, short * points,short clear)
new_brush_width=(end_x-start_x)+1; new_brush_width=(end_x-start_x)+1;
new_brush_height=(end_y-start_y)+1; new_brush_height=(end_y-start_y)+1;
if ( (((long)Brush_height)*Brush_width) != if (Realloc_brush(new_brush_width, new_brush_height, NULL, NULL))
(((long)new_brush_height)*new_brush_width) )
{
free(Brush);
Brush=(byte *)malloc(((long)new_brush_height)*new_brush_width);
if (!Brush)
{
Error(0);
Brush=(byte *)malloc(1*1);
if(Brush==NULL) Error(ERROR_MEMORY);
new_brush_height=new_brush_width=1;
*Brush=Fore_color;
}
}
Brush_width=new_brush_width;
Brush_height=new_brush_height;
free(Smear_brush);
Smear_brush_width=(Brush_width>MAX_PAINTBRUSH_SIZE)?Brush_width:MAX_PAINTBRUSH_SIZE;
Smear_brush_height=(Brush_height>MAX_PAINTBRUSH_SIZE)?Brush_height:MAX_PAINTBRUSH_SIZE;
Smear_brush=(byte *)malloc(((long)Smear_brush_height)*Smear_brush_width);
if (!Smear_brush) // On ne peut même pas allouer la brosse du smear!
{ {
Error(0); Error(0);
return;
free(Brush);
Brush=(byte *)malloc(1*1);
if(Brush==NULL) Error(ERROR_MEMORY);
Brush_height=1;
Brush_width=1;
Smear_brush=(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE);
Smear_brush_height=MAX_PAINTBRUSH_SIZE;
Smear_brush_width=MAX_PAINTBRUSH_SIZE;
} }
Brush_offset_X=start_x; Brush_offset_X=start_x;
Brush_offset_Y=start_y; Brush_offset_Y=start_y;
Pixel_figure=Pixel_figure_in_brush; Pixel_figure=Pixel_figure_in_brush;
memset(Brush,Back_color,(long)Brush_width*Brush_height); memset(Brush,Back_color,(long)Brush_width*Brush_height);
@ -1271,6 +1264,13 @@ void Capture_brush_with_lasso(int vertices, short * points,short clear)
if (clear) if (clear)
Pixel_in_current_screen(x_pos,y_pos,Back_color,0); Pixel_in_current_screen(x_pos,y_pos,Back_color,0);
} }
// Grab palette
memcpy(Brush_original_palette, Main_palette,sizeof(T_Palette));
// Init colormap
for (temp=0; temp<256; temp++)
Brush_colormap[temp]=temp;
// Copy Brush to original
memcpy(Brush_original_pixels, Brush, (long)Brush_width*Brush_height);
// On centre la prise sur la brosse // On centre la prise sur la brosse
Brush_offset_X=(Brush_width>>1); Brush_offset_X=(Brush_width>>1);
@ -1304,50 +1304,27 @@ void Stretch_brush(short x1, short y1, short x2, short y2)
} }
new_brush_height++; new_brush_height++;
// Free some memory new_brush=((byte *)malloc(new_brush_width*new_brush_height));
free(Smear_brush); if (!new_brush)
Smear_brush = NULL;
if ((new_brush=((byte *)malloc(new_brush_width*new_brush_height))))
{ {
Rescale(Brush, Brush_width, Brush_height, new_brush, new_brush_width, new_brush_height, x2<x1, y2<y1);
free(Brush);
Brush=new_brush;
Brush_width=new_brush_width;
Brush_height=new_brush_height;
Smear_brush_width=(Brush_width>MAX_PAINTBRUSH_SIZE)?Brush_width:MAX_PAINTBRUSH_SIZE;
Smear_brush_height=(Brush_height>MAX_PAINTBRUSH_SIZE)?Brush_height:MAX_PAINTBRUSH_SIZE;
Smear_brush=(byte *)malloc(((long)Smear_brush_height)*Smear_brush_width);
if (!Smear_brush) // On ne peut même pas allouer la brosse du smear!
{
Error(0);
free(Brush);
Brush=(byte *)malloc(1*1);
Brush_height=1;
Brush_width=1;
Smear_brush=(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE);
Smear_brush_height=MAX_PAINTBRUSH_SIZE;
Smear_brush_width=MAX_PAINTBRUSH_SIZE;
}
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
}
else
{
// Ici la libération de mémoire n'a pas suffi donc on remet dans l'état
// où c'etait avant. On a juste à réallouer la Smear_brush car il y a
// normalement la place pour elle puisque rien d'autre n'a pu être alloué
// entre temps.
Smear_brush=(byte *)malloc(((long)Smear_brush_height)*Smear_brush_width);
Error(0); Error(0);
return;
} }
Rescale(Brush_original_pixels, Brush_width, Brush_height, new_brush, new_brush_width, new_brush_height, x2<x1, y2<y1);
if (Realloc_brush(new_brush_width, new_brush_height, new_brush, NULL))
{
free(new_brush);
Error(0);
return;
}
// Remap according to the last used remap table
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
} }
@ -1578,9 +1555,6 @@ void Distort_brush(short x1, short y1, short x2, short y2, short x3, short y3, s
short min_x, max_x, min_y, max_y; short min_x, max_x, min_y, max_y;
short width, height; short width, height;
byte * new_brush; byte * new_brush;
byte * new_smear_brush;
short new_smear_brush_width;
short new_smear_brush_height;
// Move all coordinates to start on (0,0) // Move all coordinates to start on (0,0)
min_x=Min4(x1,x2,x3,x4); min_x=Min4(x1,x2,x3,x4);
@ -1601,24 +1575,11 @@ void Distort_brush(short x1, short y1, short x2, short y2, short x3, short y3, s
width=Max(max_x-min_x, 1); width=Max(max_x-min_x, 1);
height=Max(max_y-min_y, 1); height=Max(max_y-min_y, 1);
new_smear_brush_width=(width>MAX_PAINTBRUSH_SIZE)?width:MAX_PAINTBRUSH_SIZE;
new_smear_brush_height=(height>MAX_PAINTBRUSH_SIZE)?height:MAX_PAINTBRUSH_SIZE;
new_smear_brush=(byte *)malloc(((long)new_smear_brush_height)*new_smear_brush_width);
if (! new_smear_brush)
{
// Out of memory while allocating new smear brush
Error(0);
return;
}
new_brush=((byte *)malloc((long)width*height)); new_brush=((byte *)malloc((long)width*height));
if (!new_brush) if (!new_brush)
{ {
// Out of memory while allocating new brush // Out of memory while allocating new brush
Error(0); Error(0);
free(new_smear_brush);
new_smear_brush = NULL;
return; return;
} }
@ -1631,18 +1592,14 @@ void Distort_brush(short x1, short y1, short x2, short y2, short x3, short y3, s
Distort_buffer_width=width; Distort_buffer_width=width;
Draw_brush_linear_distort(0, 0, (Brush_width<<16), (Brush_height<<16), (x1<<16), (y1<<16), (x2<<16), (y2<<16), (x3<<16), (y3<<16), (x4<<16), (y4<<16)); Draw_brush_linear_distort(0, 0, (Brush_width<<16), (Brush_height<<16), (x1<<16), (y1<<16), (x2<<16), (y2<<16), (x3<<16), (y3<<16), (x4<<16), (y4<<16));
// Free old brushes if (Realloc_brush(width, height, new_brush, NULL))
free(Smear_brush); {
free(Brush); free(new_brush);
Error(0);
// Point to the new ones return;
Brush=new_brush; }
Brush_width=width; // Remap according to the last used remap table
Brush_height=height; Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
Smear_brush=new_smear_brush;
Smear_brush_width=new_smear_brush_width;
Smear_brush_height=new_smear_brush_height;
// Re-center brush handle // Re-center brush handle
Brush_offset_X=(Brush_width>>1); Brush_offset_X=(Brush_width>>1);
@ -1867,7 +1824,7 @@ void Compute_quad_texture(int x1,int y1,int xt1,int yt1,
xt=Round((float)(ScanY_Xt[0][y])+(temp*(ScanY_Xt[1][y]-ScanY_Xt[0][y]))); xt=Round((float)(ScanY_Xt[0][y])+(temp*(ScanY_Xt[1][y]-ScanY_Xt[0][y])));
yt=Round((float)(ScanY_Yt[0][y])+(temp*(ScanY_Yt[1][y]-ScanY_Yt[0][y]))); yt=Round((float)(ScanY_Yt[0][y])+(temp*(ScanY_Yt[1][y]-ScanY_Yt[0][y])));
if (xt>=0 && yt>=0) if (xt>=0 && yt>=0)
buffer[x+(y*width)]=Read_pixel_from_brush(xt,yt); buffer[x+(y*width)]=*(Brush_original_pixels + yt * Brush_width + xt);
} }
for (; x<width; x++) for (; x<width; x++)
buffer[x+(y*width)]=Back_color; buffer[x+(y*width)]=Back_color;
@ -1920,54 +1877,32 @@ void Rotate_brush(float angle)
new_brush_width=x_max+1-x_min; new_brush_width=x_max+1-x_min;
new_brush_height=y_max+1-y_min; new_brush_height=y_max+1-y_min;
free(Smear_brush); // On libère un peu de mémoire new_brush=(byte *)malloc(new_brush_width*new_brush_height);
Smear_brush = NULL;
if ((new_brush=((byte *)malloc(new_brush_width*new_brush_height)))) if (!new_brush)
{ {
// Et maintenant on calcule la nouvelle brosse tournée.
Compute_quad_texture(x1,y1, 0, 0,
x2,y2,Brush_width-1, 0,
x3,y3, 0,Brush_height-1,
x4,y4,Brush_width-1,Brush_height-1,
new_brush,new_brush_width,new_brush_height);
free(Brush);
Brush=new_brush;
Brush_width=new_brush_width;
Brush_height=new_brush_height;
Smear_brush_width=(Brush_width>MAX_PAINTBRUSH_SIZE)?Brush_width:MAX_PAINTBRUSH_SIZE;
Smear_brush_height=(Brush_height>MAX_PAINTBRUSH_SIZE)?Brush_height:MAX_PAINTBRUSH_SIZE;
Smear_brush=(byte *)malloc(((long)Smear_brush_height)*Smear_brush_width);
if (!Smear_brush) // On ne peut même pas allouer la brosse du smear!
{
Error(0);
free(Brush);
Brush=(byte *)malloc(1*1);
Brush_height=1;
Brush_width=1;
Smear_brush=(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE);
Smear_brush_height=MAX_PAINTBRUSH_SIZE;
Smear_brush_width=MAX_PAINTBRUSH_SIZE;
}
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
}
else
{
// Ici la libération de mémoire n'a pas suffit donc on remet dans l'état
// où c'etait avant. On a juste à réallouer la Smear_brush car il y a
// normalement la place pour elle puisque rien d'autre n'a pu être alloué
// entre temps.
Smear_brush=(byte *)malloc(((long)Smear_brush_height)*Smear_brush_width);
Error(0); Error(0);
return;
} }
// Et maintenant on calcule la nouvelle brosse tournée.
Compute_quad_texture(x1,y1, 0, 0,
x2,y2,Brush_width-1, 0,
x3,y3, 0,Brush_height-1,
x4,y4,Brush_width-1,Brush_height-1,
new_brush,new_brush_width,new_brush_height);
if (Realloc_brush(new_brush_width, new_brush_height, new_brush, NULL))
{
free(new_brush);
return;
}
// Remap according to the last used remap table
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
// Center offsets
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
} }
@ -2090,3 +2025,25 @@ void Rotate_brush_preview(float angle)
end_y=Max(Max(y1,y2),Max(y3,y4)); end_y=Max(Max(y1,y2),Max(y3,y4));
Update_part_of_screen(start_x,start_y,end_x-start_x+1,end_y-start_y+1); Update_part_of_screen(start_x,start_y,end_x-start_x+1,end_y-start_y+1);
} }
/*
/// Sets brush's original palette and color mapping.
void Brush_set_palette(T_Palette *palette)
{
int i;
byte need_remap;
need_remap=0;
memcpy(Brush_original_palette,palette,sizeof(T_Palette));
for (i=0;i<256;i++)
{
if (Brush_original_palette[i].R!=Main_palette[i].R
|| Brush_original_palette[i].G!=Main_palette[i].G
|| Brush_original_palette[i].B!=Main_palette[i].B)
{
need_remap=1;
}
}
}
*/

View File

@ -111,10 +111,19 @@ void Capture_brush_with_lasso(int vertices, short * points,short clear);
/// ///
/// Changes the Brush size, discarding its previous content. /// Changes the Brush size.
/// @return 0 OK, 1 Failed /// @return 0 on success, non-zero on failure (memory?).
byte Realloc_brush(word new_brush_width, word new_brush_height); /// @param new_brush: Optionally, you can provide an already allocated new
/// brush - otherwise, this function performs the allocation.
/// @param old_brush: If the caller passes NULL, this function will free the old
/// pixel data. If the caller provides the address of a (free) byte
/// pointer, the function will make it point to the original pixel data,
/// in this case it will be the caller's responsibility to free() it
/// (after transferring pixels to Brush, usually).
byte Realloc_brush(word new_brush_width, word new_brush_height, byte *new_brush, byte **old_brush);
/// Sets brush's original palette and color mapping.
void Brush_set_palette(T_Palette *palette);
#endif #endif

View File

@ -38,7 +38,7 @@
#include "sdlscreen.h" #include "sdlscreen.h"
#include "windows.h" #include "windows.h"
#if defined(__VBCC__)||defined(__GP2X__) #if defined(__VBCC__) || defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__)
#define M_PI 3.141592653589793238462643 #define M_PI 3.141592653589793238462643
#endif #endif
@ -251,6 +251,106 @@ void Colorpicker_0_1(void)
Unselect_button(BUTTON_COLORPICKER); Unselect_button(BUTTON_COLORPICKER);
} }
/////////////////////////////////////////////////////////// OPERATION_RMB_COLORPICK
byte Rightclick_colorpick(byte cursor_visible)
{
// Check if the rightclick colorpick should take over:
if (!Config.Right_click_colorpick)
return 0;
if (Mouse_K!=RIGHT_SIDE)
return 0;
// In these modes, the Foreground color is ignored,
// so the RMB should act as normal.
if (Shade_mode||Quick_shade_mode||Tiling_mode)
return 0;
Colorpicker_color=-1;
Colorpicker_X=-1;
Colorpicker_Y=-1;
if (cursor_visible)
Hide_cursor();
Start_operation_stack(OPERATION_RMB_COLORPICK);
Init_start_operation();
// Just an indicator to go to next step
Operation_push(1);
Rightclick_colorpick_2_1();
if (cursor_visible)
Display_cursor();
return 1;
}
void Rightclick_colorpick_2_1(void)
//
// Opération : OPERATION_RMB_COLORPICK
// Click Souris: 2
// Taille_Pile : 1
//
// Souris effacée: Non
//
{
char str[4];
if ( (Colorpicker_X!=Paintbrush_X)
|| (Colorpicker_Y!=Paintbrush_Y) )
{
if ( (Paintbrush_X>=0) && (Paintbrush_Y>=0)
&& (Paintbrush_X<Main_image_width)
&& (Paintbrush_Y<Main_image_height) )
Colorpicker_color=Read_pixel_from_current_screen(Paintbrush_X,Paintbrush_Y);
else
Colorpicker_color=0;
Colorpicker_X=Paintbrush_X;
Colorpicker_Y=Paintbrush_Y;
if (Menu_is_visible)
{
Print_coordinates();
Num2str(Colorpicker_color,str,3);
Print_in_menu(str,20);
Print_general(170*Menu_factor_X,Menu_status_Y," ",0,Colorpicker_color);
}
}
}
void Rightclick_colorpick_0_1(void)
//
// Opération : OPERATION_RMB_COLORPICK
// Click Souris: 0
// Taille_Pile : 1
//
// Souris effacée: Non
//
{
short dummy;
Hide_cursor();
Operation_pop(&dummy);
Set_fore_color(Colorpicker_color);
// Restore previous operation
Start_operation_stack(Operation_before_interrupt);
// Erase the color block which shows the picked color
if (Operation_before_interrupt!=OPERATION_REPLACE)
if ( (Mouse_Y<Menu_Y) && (Menu_is_visible) &&
( (!Main_magnifier_mode) || (Mouse_X<Main_separator_position) || (Mouse_X>=Main_X_zoom) ) )
Print_in_menu("X: Y: ",0);
Print_coordinates();
Display_cursor();
}
////////////////////////////////////////////////////// OPERATION_GRAB_BRUSH ////////////////////////////////////////////////////// OPERATION_GRAB_BRUSH
@ -858,6 +958,10 @@ void Rotate_brush_1_5(void)
Operation_pop(&old_y); Operation_pop(&old_y);
Operation_pop(&old_x); Operation_pop(&old_x);
// On corrige les coordonnées de la ligne si la touche shift est appuyée...
if(SDL_GetModState() & KMOD_SHIFT)
Clamp_coordinates_regular_angle(Brush_rotation_center_X,Brush_rotation_center_Y,&Paintbrush_X,&Paintbrush_Y);
if ( (Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) || (prev_state!=2) ) if ( (Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) || (prev_state!=2) )
{ {
if ( (Brush_rotation_center_X==Paintbrush_X) if ( (Brush_rotation_center_X==Paintbrush_X)
@ -921,6 +1025,10 @@ void Rotate_brush_0_5(void)
Operation_pop(&old_y); Operation_pop(&old_y);
Operation_pop(&old_x); Operation_pop(&old_x);
// On corrige les coordonnées de la ligne si la touche shift est appuyée...
if(SDL_GetModState() & KMOD_SHIFT)
Clamp_coordinates_regular_angle(Brush_rotation_center_X,Brush_rotation_center_Y,&Paintbrush_X,&Paintbrush_Y);
if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) || (prev_state!=3)) if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) || (prev_state!=3))
{ {
if ( (Brush_rotation_center_X==Paintbrush_X) if ( (Brush_rotation_center_X==Paintbrush_X)

File diff suppressed because it is too large Load Diff

View File

@ -670,5 +670,9 @@ void Button_Smear_mode(void);
void Button_Brush_container(void); void Button_Brush_container(void);
byte Store_paintbrush(int index);
void Select_paintbrush(int index);
#endif #endif

View File

@ -40,6 +40,7 @@
#include "sdlscreen.h" #include "sdlscreen.h"
#include "struct.h" #include "struct.h"
#include "windows.h" #include "windows.h"
#include "brush.h"
//---------- Menu dans lequel on tagge des couleurs (genre Stencil) ---------- //---------- Menu dans lequel on tagge des couleurs (genre Stencil) ----------
void Menu_tag_colors(char * window_title, byte * table, byte * mode, byte can_cancel, const char *help_section, word close_shortcut) void Menu_tag_colors(char * window_title, byte * table, byte * mode, byte can_cancel, const char *help_section, word close_shortcut)
@ -279,7 +280,7 @@ void Button_Grid_menu(void)
{ {
case 3 : case 3 :
Num2str(chosen_X,str,2); Num2str(chosen_X,str,2);
Readline(39,26,str,2,1); Readline(39,26,str,2,INPUT_TYPE_INTEGER);
chosen_X=atoi(str); chosen_X=atoi(str);
// On corrige les dimensions // On corrige les dimensions
if ((!chosen_X) || (chosen_X>80)) if ((!chosen_X) || (chosen_X>80))
@ -301,7 +302,7 @@ void Button_Grid_menu(void)
break; break;
case 4 : case 4 :
Num2str(chosen_Y,str,2); Num2str(chosen_Y,str,2);
Readline(39,47,str,2,1); Readline(39,47,str,2,INPUT_TYPE_INTEGER);
chosen_Y=atoi(str); chosen_Y=atoi(str);
// On corrige les dimensions // On corrige les dimensions
if ((!chosen_Y) || (chosen_Y>80)) if ((!chosen_Y) || (chosen_Y>80))
@ -323,7 +324,7 @@ void Button_Grid_menu(void)
break; break;
case 5 : case 5 :
Num2str(dx_selected,str,2); Num2str(dx_selected,str,2);
Readline(97,26,str,2,1); Readline(97,26,str,2,INPUT_TYPE_INTEGER);
dx_selected=atoi(str); dx_selected=atoi(str);
// On corrige les dimensions // On corrige les dimensions
if (dx_selected>79) if (dx_selected>79)
@ -338,7 +339,7 @@ void Button_Grid_menu(void)
break; break;
case 6 : case 6 :
Num2str(dy_selected,str,2); Num2str(dy_selected,str,2);
Readline(97,47,str,2,1); Readline(97,47,str,2,INPUT_TYPE_INTEGER);
dy_selected=atoi(str); dy_selected=atoi(str);
// On corrige les dimensions // On corrige les dimensions
if (dy_selected>79) if (dy_selected>79)
@ -479,7 +480,7 @@ void Button_Smooth_menu(void)
Num2str(chosen_matrix[x][y],str,2); Num2str(chosen_matrix[x][y],str,2);
Readline(matrix_input[x][y]->Pos_X+2, Readline(matrix_input[x][y]->Pos_X+2,
matrix_input[x][y]->Pos_Y+2, matrix_input[x][y]->Pos_Y+2,
str,2,1); str,2,INPUT_TYPE_INTEGER);
chosen_matrix[x][y]=atoi(str); chosen_matrix[x][y]=atoi(str);
Display_cursor(); Display_cursor();
} }
@ -553,6 +554,9 @@ void Button_Colorize_mode(void)
break; break;
case 2 : case 2 :
Effect_function=Effect_substractive_colorize; Effect_function=Effect_substractive_colorize;
break;
case 3 :
Effect_function=Effect_alpha_colorize;
} }
Shade_mode=0; Shade_mode=0;
Quick_shade_mode=0; Quick_shade_mode=0;
@ -572,10 +576,12 @@ void Button_Colorize_display_selection(int mode)
Print_in_window(4,37," ",MC_Black,MC_Light); Print_in_window(4,37," ",MC_Black,MC_Light);
Print_in_window(4,57," ",MC_Black,MC_Light); Print_in_window(4,57," ",MC_Black,MC_Light);
Print_in_window(4,74," ",MC_Black,MC_Light); Print_in_window(4,74," ",MC_Black,MC_Light);
Print_in_window(4,91," ",MC_Black,MC_Light);
// Partie droite // Partie droite
Print_in_window(129,37," ",MC_Black,MC_Light); Print_in_window(129,37," ",MC_Black,MC_Light);
Print_in_window(129,57," ",MC_Black,MC_Light); Print_in_window(129,57," ",MC_Black,MC_Light);
Print_in_window(129,74," ",MC_Black,MC_Light); Print_in_window(129,74," ",MC_Black,MC_Light);
Print_in_window(129,91," ",MC_Black,MC_Light);
// Ensuite, on affiche la flèche là où il le faut: // Ensuite, on affiche la flèche là où il le faut:
switch(mode) switch(mode)
@ -588,6 +594,9 @@ void Button_Colorize_display_selection(int mode)
break; break;
case 2 : // Méthode soustractive case 2 : // Méthode soustractive
y_pos=74; y_pos=74;
break;
case 3 : // Méthode alpha
y_pos=91;
} }
Print_in_window(4,y_pos,"\020",MC_Black,MC_Light); Print_in_window(4,y_pos,"\020",MC_Black,MC_Light);
Print_in_window(129,y_pos,"\021",MC_Black,MC_Light); Print_in_window(129,y_pos,"\021",MC_Black,MC_Light);
@ -600,7 +609,7 @@ void Button_Colorize_menu(void)
short clicked_button; short clicked_button;
char str[4]; char str[4];
Open_window(140,118,"Transparency"); Open_window(140,135,"Transparency");
Print_in_window(16,23,"Opacity:",MC_Dark,MC_Light); Print_in_window(16,23,"Opacity:",MC_Dark,MC_Light);
Window_set_input_button(87,21,3); // 1 Window_set_input_button(87,21,3); // 1
@ -610,9 +619,10 @@ void Button_Colorize_menu(void)
Window_set_normal_button(16,54,108,14,"Additive" ,2,1,SDLK_d); // 3 Window_set_normal_button(16,54,108,14,"Additive" ,2,1,SDLK_d); // 3
Window_set_normal_button(16,71,108,14,"Subtractive",1,1,SDLK_s); // 4 Window_set_normal_button(16,71,108,14,"Subtractive",1,1,SDLK_s); // 4
Window_set_normal_button(16,88,108,14,"Alpha",1,1,SDLK_a); // 4
Window_set_normal_button(16,94, 51,14,"Cancel" ,0,1,KEY_ESC); // 5 Window_set_normal_button(16,111, 51,14,"Cancel" ,0,1,KEY_ESC); // 5
Window_set_normal_button(73,94, 51,14,"OK" ,0,1,SDLK_RETURN); // 6 Window_set_normal_button(73,111, 51,14,"OK" ,0,1,SDLK_RETURN); // 6
Num2str(Colorize_opacity,str,3); Num2str(Colorize_opacity,str,3);
Window_input_content(Window_special_button_list,str); Window_input_content(Window_special_button_list,str);
@ -632,7 +642,7 @@ void Button_Colorize_menu(void)
{ {
case 1: // Zone de saisie de l'opacité case 1: // Zone de saisie de l'opacité
Num2str(chosen_opacity,str,3); Num2str(chosen_opacity,str,3);
Readline(89,23,str,3,1); Readline(89,23,str,3,INPUT_TYPE_INTEGER);
chosen_opacity=atoi(str); chosen_opacity=atoi(str);
// On corrige le pourcentage // On corrige le pourcentage
if (chosen_opacity>100) if (chosen_opacity>100)
@ -643,9 +653,10 @@ void Button_Colorize_menu(void)
} }
Display_cursor(); Display_cursor();
break; break;
case 2: // Méthode interpolée case 2: // Interpolated method
case 3: // Méthode additive case 3: // Additive method
case 4: // Méthode soustractive case 4: // Substractive method
case 5: // Alpha method
selected_mode=clicked_button-2; selected_mode=clicked_button-2;
Hide_cursor(); Hide_cursor();
Button_Colorize_display_selection(selected_mode); Button_Colorize_display_selection(selected_mode);
@ -654,13 +665,13 @@ void Button_Colorize_menu(void)
if (Is_shortcut(Key,0x100+BUTTON_HELP)) if (Is_shortcut(Key,0x100+BUTTON_HELP))
Window_help(BUTTON_EFFECTS, "TRANSPARENCY"); Window_help(BUTTON_EFFECTS, "TRANSPARENCY");
else if (Is_shortcut(Key,SPECIAL_COLORIZE_MENU)) else if (Is_shortcut(Key,SPECIAL_COLORIZE_MENU))
clicked_button=6; clicked_button=7;
} }
while (clicked_button<5); while (clicked_button<6);
Close_window(); Close_window();
if (clicked_button==6) // OK if (clicked_button==7) // OK
{ {
Colorize_opacity =chosen_opacity; Colorize_opacity =chosen_opacity;
Colorize_current_mode=selected_mode; Colorize_current_mode=selected_mode;
@ -724,7 +735,7 @@ void Button_Tiling_menu(void)
if (clicked_button==3) // Zone de saisie du décalage X if (clicked_button==3) // Zone de saisie du décalage X
{ {
Num2str(chosen_offset_x,str,4); Num2str(chosen_offset_x,str,4);
Readline(93,23,str,4,1); Readline(93,23,str,4,INPUT_TYPE_INTEGER);
chosen_offset_x=atoi(str); chosen_offset_x=atoi(str);
// On corrige le décalage en X // On corrige le décalage en X
if (chosen_offset_x>=Brush_width) if (chosen_offset_x>=Brush_width)
@ -739,7 +750,7 @@ void Button_Tiling_menu(void)
if (clicked_button==4) // Zone de saisie du décalage Y if (clicked_button==4) // Zone de saisie du décalage Y
{ {
Num2str(chosen_offset_y,str,4); Num2str(chosen_offset_y,str,4);
Readline(93,37,str,4,1); Readline(93,37,str,4,INPUT_TYPE_INTEGER);
chosen_offset_y=atoi(str); chosen_offset_y=atoi(str);
// On corrige le décalage en Y // On corrige le décalage en Y
if (chosen_offset_y>=Brush_height) if (chosen_offset_y>=Brush_height)
@ -975,8 +986,8 @@ void Button_Sieve_menu(void)
{ {
clicked_button=Window_clicked_button(); clicked_button=Window_clicked_button();
origin_x=Window_pos_X+(Menu_factor_X*Window_special_button_list->Pos_X); origin_x=Window_pos_X+(Menu_factor_X*Window_special_button_list->Pos_X);
origin_y=Window_pos_Y+(Menu_factor_Y*Window_special_button_list->Pos_Y); origin_y=Window_pos_Y+(Menu_factor_Y*Window_special_button_list->Pos_Y);
switch (clicked_button) switch (clicked_button)
@ -1063,15 +1074,22 @@ void Button_Sieve_menu(void)
break; break;
case 7 : // Transfer to brush case 7 : // Transfer to brush
Brush_width=Sieve_width;
Brush_height=Sieve_height; if (Realloc_brush(Sieve_width, Sieve_height, NULL, NULL))
free(Brush); break;
Brush=(byte *)malloc(((long)Brush_height)*Brush_width);
for (y_pos=0; y_pos<Sieve_height; y_pos++) for (y_pos=0; y_pos<Sieve_height; y_pos++)
for (x_pos=0; x_pos<Sieve_width; x_pos++) for (x_pos=0; x_pos<Sieve_width; x_pos++)
Pixel_in_brush(x_pos,y_pos,(Sieve[x_pos][y_pos])?Fore_color:Back_color); *(Brush_original_pixels + y_pos * Brush_width + x_pos) = (Sieve[x_pos][y_pos])?Fore_color:Back_color;
// Grab palette
memcpy(Brush_original_palette, Main_palette,sizeof(T_Palette));
// Remap (no change)
Remap_brush();
Brush_offset_X=(Brush_width>>1); Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1); Brush_offset_Y=(Brush_height>>1);
Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH); Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
break; break;

View File

@ -37,7 +37,6 @@
#define BETA1 98 ///< Version number for gfx2.cfg (3/4) #define BETA1 98 ///< Version number for gfx2.cfg (3/4)
#define BETA2 0 ///< Version number for gfx2.cfg (4/4) #define BETA2 0 ///< Version number for gfx2.cfg (4/4)
#define MAX_VIDEO_MODES 100 ///< Maximum number of video modes Grafx2 can propose. #define MAX_VIDEO_MODES 100 ///< Maximum number of video modes Grafx2 can propose.
#define NB_SHORTCUTS 183 ///< Number of actions that can have a key combination associated to it.
#define NB_ZOOM_FACTORS 15 ///< Number of zoom levels available in the magnifier. #define NB_ZOOM_FACTORS 15 ///< Number of zoom levels available in the magnifier.
#define MENU_WIDTH 254 ///< Width of the menu (not counting the palette) #define MENU_WIDTH 254 ///< Width of the menu (not counting the palette)
#define MENU_HEIGHT 44 ///< Height of the menu. #define MENU_HEIGHT 44 ///< Height of the menu.
@ -45,9 +44,10 @@
#define CURSOR_SPRITE_WIDTH 15 ///< Width of a mouse cursor sprite. #define CURSOR_SPRITE_WIDTH 15 ///< Width of a mouse cursor sprite.
#define CURSOR_SPRITE_HEIGHT 15 ///< Height of a mouse cursor sprite. #define CURSOR_SPRITE_HEIGHT 15 ///< Height of a mouse cursor sprite.
#define NB_EFFECTS_SPRITES 9 ///< Number of effect sprites. #define NB_EFFECTS_SPRITES 9 ///< Number of effect sprites.
#define NB_MENU_SPRITES 20 ///< Number of menu sprites. #define MENU_SPRITE_WIDTH 16 ///< Width of a menu sprite in pixels
#define MENU_SPRITE_WIDTH 14 ///< Width of a menu sprite in pixels #define MENU_SPRITE_HEIGHT 16 ///< Height of a menu sprite in pixels
#define MENU_SPRITE_HEIGHT 14 ///< Height of a menu sprite in pixels #define EFFECT_SPRITE_WIDTH 14 ///< Width of an effect sprite in pixels
#define EFFECT_SPRITE_HEIGHT 14 ///< Height of an effect sprite in pixels
#define LAYER_SPRITE_WIDTH 14 ///< Width of a layer button in pixels #define LAYER_SPRITE_WIDTH 14 ///< Width of a layer button in pixels
#define LAYER_SPRITE_HEIGHT 10 ///< Height of a layer button in pixels #define LAYER_SPRITE_HEIGHT 10 ///< Height of a layer button in pixels
#define PAINTBRUSH_WIDTH 16 ///< Width of a preset paintbrush sprite #define PAINTBRUSH_WIDTH 16 ///< Width of a preset paintbrush sprite
@ -120,6 +120,7 @@ enum FILE_FORMATS
FORMAT_KCF, FORMAT_KCF,
FORMAT_PAL, FORMAT_PAL,
FORMAT_SCR, FORMAT_SCR,
FORMAT_XPM,
FORMAT_MISC, ///< Must be last of enum: others formats recognized by SDL_image FORMAT_MISC, ///< Must be last of enum: others formats recognized by SDL_image
}; };
@ -210,9 +211,17 @@ enum PAINTBRUSH_SHAPES
PAINTBRUSH_SHAPE_DIAMOND, PAINTBRUSH_SHAPE_DIAMOND,
PAINTBRUSH_SHAPE_SIEVE_ROUND, PAINTBRUSH_SHAPE_SIEVE_ROUND,
PAINTBRUSH_SHAPE_SIEVE_SQUARE, PAINTBRUSH_SHAPE_SIEVE_SQUARE,
PAINTBRUSH_SHAPE_RESERVED1, ///< Reserved for future use
PAINTBRUSH_SHAPE_RESERVED2, ///< Reserved for future use
PAINTBRUSH_SHAPE_RESERVED3, ///< Reserved for future use
PAINTBRUSH_SHAPE_RESERVED4, ///< Reserved for future use
PAINTBRUSH_SHAPE_RESERVED5, ///< Reserved for future use
PAINTBRUSH_SHAPE_RESERVED6, ///< Reserved for future use
PAINTBRUSH_SHAPE_RESERVED7, ///< Reserved for future use
PAINTBRUSH_SHAPE_RESERVED8, ///< Reserved for future use
PAINTBRUSH_SHAPE_MISC, ///< A raw monochrome bitmap, can't be resized. This must be the last of the preset paintbrush types. PAINTBRUSH_SHAPE_MISC, ///< A raw monochrome bitmap, can't be resized. This must be the last of the preset paintbrush types.
PAINTBRUSH_SHAPE_POINT, ///< Used to reduce the paintbrush to a single pixel, during operations like floodfill. PAINTBRUSH_SHAPE_POINT, ///< Used to reduce the paintbrush to a single pixel, during operations like floodfill.
PAINTBRUSH_SHAPE_NONE, ///< Used to display no cursor at all (colorpicker) PAINTBRUSH_SHAPE_NONE, ///< Used to display no cursor at all (colorpicker)
PAINTBRUSH_SHAPE_COLOR_BRUSH, ///< User's brush, in color mode PAINTBRUSH_SHAPE_COLOR_BRUSH, ///< User's brush, in color mode
PAINTBRUSH_SHAPE_MONO_BRUSH, ///< User's brush, in mono mode PAINTBRUSH_SHAPE_MONO_BRUSH, ///< User's brush, in mono mode
PAINTBRUSH_SHAPE_MAX ///< Upper limit. PAINTBRUSH_SHAPE_MAX ///< Upper limit.
@ -222,6 +231,8 @@ enum PAINTBRUSH_SHAPES
#define BUTTON_RELEASED 0 #define BUTTON_RELEASED 0
/// State of a menu button that is being pressed. /// State of a menu button that is being pressed.
#define BUTTON_PRESSED 1 #define BUTTON_PRESSED 1
/// State of a button temporarily highligted
#define BUTTON_HIGHLIGHTED 2
/// The different modes of the Shade /// The different modes of the Shade
enum SHADE_MODES enum SHADE_MODES
@ -243,7 +254,9 @@ enum CHUNKS_CFG
CHUNK_SMOOTH = 6, ///< Smooth effect settings CHUNK_SMOOTH = 6, ///< Smooth effect settings
CHUNK_EXCLUDE_COLORS = 7, ///< List of excluded colors CHUNK_EXCLUDE_COLORS = 7, ///< List of excluded colors
CHUNK_QUICK_SHADE = 8, ///< QShade effect settings CHUNK_QUICK_SHADE = 8, ///< QShade effect settings
CHUNK_GRID = 9, CHUNK_GRID = 9, ///< Grid settings
CHUNK_BRUSH =10, ///< Paintbrushes
CHUNK_SCRIPTS =11, ///< Callable scripts
CHUNK_MAX CHUNK_MAX
}; };
@ -257,7 +270,8 @@ enum ICON_TYPES
ICON_NETWORK, ///< "Network" drive ICON_NETWORK, ///< "Network" drive
ICON_STAR, ///< Star (favorite) ICON_STAR, ///< Star (favorite)
ICON_DROPDOWN, ///< Dropdown arrow ICON_DROPDOWN, ///< Dropdown arrow
NB_ICON_SPRITES ///< Number of 8x8 icons NB_ICON_SPRITES, ///< Number of 8x8 icons
ICON_NONE ///< None of the above
}; };
/// Identifiers for the buttons in the menu. /// Identifiers for the buttons in the menu.
@ -316,6 +330,24 @@ enum BUTTON_NUMBERS
NB_BUTTONS ///< Number of buttons in the menu bar. NB_BUTTONS ///< Number of buttons in the menu bar.
}; };
enum MENU_SPRITE
{
MENU_SPRITE_COLOR_BRUSH=0,
MENU_SPRITE_MONO_BRUSH,
MENU_SPRITE_DISCONTINUOUS_DRAW,
MENU_SPRITE_POINT_DRAW,
MENU_SPRITE_CONTOUR_DRAW,
MENU_SPRITE_4_POINTS_CURVE,
MENU_SPRITE_K_LINE,
MENU_SPRITE_CENTERED_LINES,
MENU_SPRITE_ELLIPSES,
MENU_SPRITE_POLYFORM,
MENU_SPRITE_REPLACE,
MENU_SPRITE_GRAD_ELLIPSE,
MENU_SPRITE_VERTICAL_PALETTE_SCROLL,
NB_MENU_SPRITES ///< Number of menu sprites.
};
/// ///
/// Identifiers of special actions that can have a keyboard shortcut. /// Identifiers of special actions that can have a keyboard shortcut.
/// They are special in the sense that there's no button in the menu for them, /// They are special in the sense that there's no button in the menu for them,
@ -364,6 +396,10 @@ enum SPECIAL_ACTIONS
SPECIAL_GET_BRUSH_COLORS, SPECIAL_GET_BRUSH_COLORS,
SPECIAL_RECOLORIZE_BRUSH, SPECIAL_RECOLORIZE_BRUSH,
SPECIAL_ROTATE_ANY_ANGLE, SPECIAL_ROTATE_ANY_ANGLE,
SPECIAL_BRUSH_DOUBLE,
SPECIAL_BRUSH_DOUBLE_WIDTH,
SPECIAL_BRUSH_DOUBLE_HEIGHT,
SPECIAL_BRUSH_HALVE,
SPECIAL_LOAD_BRUSH, SPECIAL_LOAD_BRUSH,
SPECIAL_SAVE_BRUSH, SPECIAL_SAVE_BRUSH,
SPECIAL_INVERT_SIEVE, SPECIAL_INVERT_SIEVE,
@ -435,8 +471,22 @@ enum SPECIAL_ACTIONS
SPECIAL_LAYER7_TOGGLE, SPECIAL_LAYER7_TOGGLE,
SPECIAL_LAYER8_SELECT, SPECIAL_LAYER8_SELECT,
SPECIAL_LAYER8_TOGGLE, SPECIAL_LAYER8_TOGGLE,
SPECIAL_REPEAT_SCRIPT,
SPECIAL_RUN_SCRIPT_1,
SPECIAL_RUN_SCRIPT_2,
SPECIAL_RUN_SCRIPT_3,
SPECIAL_RUN_SCRIPT_4,
SPECIAL_RUN_SCRIPT_5,
SPECIAL_RUN_SCRIPT_6,
SPECIAL_RUN_SCRIPT_7,
SPECIAL_RUN_SCRIPT_8,
SPECIAL_RUN_SCRIPT_9,
SPECIAL_RUN_SCRIPT_10,
SPECIAL_CYCLE_MODE,
SPECIAL_FORMAT_CHECKER, SPECIAL_FORMAT_CHECKER,
SPECIAL_FORMAT_CHECKER_MENU, SPECIAL_FORMAT_CHECKER_MENU,
NB_SPECIAL_SHORTCUTS ///< Number of special shortcuts NB_SPECIAL_SHORTCUTS ///< Number of special shortcuts
}; };
@ -448,7 +498,7 @@ enum OPERATIONS
OPERATION_POINT_DRAW, ///< Freehand point-by-point draw OPERATION_POINT_DRAW, ///< Freehand point-by-point draw
OPERATION_FILLED_CONTOUR, ///< Filled contour OPERATION_FILLED_CONTOUR, ///< Filled contour
OPERATION_LINE, ///< Lines OPERATION_LINE, ///< Lines
OPERATION_K_LIGNE, ///< Linked lines OPERATION_K_LINE, ///< Linked lines
OPERATION_CENTERED_LINES, ///< Centered lines OPERATION_CENTERED_LINES, ///< Centered lines
OPERATION_EMPTY_RECTANGLE, ///< Empty rectangle OPERATION_EMPTY_RECTANGLE, ///< Empty rectangle
OPERATION_FILLED_RECTANGLE, ///< Filled rectangle OPERATION_FILLED_RECTANGLE, ///< Filled rectangle
@ -476,6 +526,7 @@ enum OPERATIONS
OPERATION_STRETCH_BRUSH, ///< Stretch brush OPERATION_STRETCH_BRUSH, ///< Stretch brush
OPERATION_DISTORT_BRUSH, ///< Distort brush OPERATION_DISTORT_BRUSH, ///< Distort brush
OPERATION_GRAD_RECTANGLE, ///< Gradient-filled rectangle OPERATION_GRAD_RECTANGLE, ///< Gradient-filled rectangle
OPERATION_RMB_COLORPICK, ///< Colorpick on right mouse button
NB_OPERATIONS ///< Number of operations handled by the engine NB_OPERATIONS ///< Number of operations handled by the engine
}; };

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,7 @@
#include "struct.h" #include "struct.h"
void Main_handler (void); void Main_handler (void);
void Draw_menu_button_frame(byte btn_number,byte pressed); void Draw_menu_button (byte btn_number,byte pressed);
void Unselect_button (int btn_number); void Unselect_button (int btn_number);
void Select_button (int btn_number,byte click); void Select_button (int btn_number,byte click);
void Open_window (word width,word height, const char * title); void Open_window (word width,word height, const char * title);
@ -40,25 +40,25 @@ void Open_popup (word x_pos, word y_pos, word width, word height);
void Close_popup (void); void Close_popup (void);
void Window_draw_normal_bouton(word x_pos,word y_pos,word width,word height, void Window_draw_normal_bouton(word x_pos,word y_pos,word width,word height,
char * title,byte undersc_letter,byte clickable); const char * title,byte undersc_letter,byte clickable);
void Window_select_normal_button(word x_pos,word y_pos,word width,word height); void Window_select_normal_button(word x_pos,word y_pos,word width,word height);
void Window_unselect_normal_button(word x_pos,word y_pos,word width,word height); void Window_unselect_normal_button(word x_pos,word y_pos,word width,word height);
void Window_draw_palette_bouton(word x_pos,word y_pos); void Window_draw_palette_bouton(word x_pos,word y_pos);
void Compute_slider_cursor_height(T_Scroller_button * button); void Compute_slider_cursor_length(T_Scroller_button * button);
void Window_draw_slider(T_Scroller_button * button); void Window_draw_slider(T_Scroller_button * button);
void Window_draw_scroller_bouton(T_Scroller_button * button); void Window_draw_scroller_button(T_Scroller_button * button);
void Window_input_content(T_Special_button * button, char * content); void Window_input_content(T_Special_button * button, char * content);
void Window_clear_input_button(T_Special_button * button); void Window_clear_input_button(T_Special_button * button);
void Window_draw_input_bouton(word x_pos, word y_pos, word width_in_characters); void Window_draw_input_bouton(word x_pos, word y_pos, word width_in_characters);
T_Normal_button * Window_set_normal_button(word x_pos, word y_pos, T_Normal_button * Window_set_normal_button(word x_pos, word y_pos,
word width, word height, char * title, byte undersc_letter, word width, word height, const char * title, byte undersc_letter,
byte clickable, word shortcut); byte clickable, word shortcut);
T_Normal_button * Window_set_repeatable_button(word x_pos, word y_pos, T_Normal_button * Window_set_repeatable_button(word x_pos, word y_pos,
word width, word height, char * title, byte undersc_letter, word width, word height, const char * title, byte undersc_letter,
byte clickable, word shortcut); byte clickable, word shortcut);
T_Palette_button * Window_set_palette_button(word x_pos, word y_pos); T_Palette_button * Window_set_palette_button(word x_pos, word y_pos);
@ -69,6 +69,10 @@ T_Scroller_button * Window_set_scroller_button(word x_pos, word y_pos,
word height, word nb_elements, word nb_elements_visible, word height, word nb_elements, word nb_elements_visible,
word initial_position); word initial_position);
T_Scroller_button * Window_set_horizontal_scroller_button(word x_pos, word y_pos,
word height, word nb_elements, word nb_elements_visible,
word initial_position);
T_Special_button * Window_set_special_button(word x_pos, word y_pos, word width, T_Special_button * Window_set_special_button(word x_pos, word y_pos, word width,
word height); word height);
@ -111,4 +115,9 @@ void Pixel_background(int x_pos, int y_pos, byte color);
/// Updates the status bar line with a color number. /// Updates the status bar line with a color number.
/// Used when hovering the menu palette. /// Used when hovering the menu palette.
void Status_print_palette_color(byte color); void Status_print_palette_color(byte color);
/// Puts the user in wait mode for the specified time ( in 1/100s),
/// though the mouse still works.
void Delay_with_active_mouse(int delay);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,13 @@
/* vim:expandtab:ts=2 sw=2: /* vim:expandtab:ts=2 sw=2:
*/ */
void Button_Brush_Factory(void); void Button_Brush_Factory(void);
void Repeat_script(void);
/// Lua scripts bound to shortcut keys.
extern char * Bound_script[10];
///
/// Run a lua script linked to a shortcut, 0-9.
/// Before: Cursor hidden
/// After: Cursor shown
void Run_numbered_script(byte index);

View File

@ -2,6 +2,7 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2009 Petter Lindquist Copyright 2009 Petter Lindquist
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet Copyright 2008 Franck Charlet
@ -27,6 +28,19 @@
#ifndef __no_pnglib__ #ifndef __no_pnglib__
#include <png.h> #include <png.h>
#if (PNG_LIBPNG_VER_MAJOR <= 1) && (PNG_LIBPNG_VER_MINOR < 4)
// Compatibility layer to allow us to use libng 1.4 or any older one.
// This function is renamed in 1.4
#define png_set_expand_gray_1_2_4_to_8(x) png_set_gray_1_2_4_to_8(x)
// Wrappers that are mandatory in 1.4. Older version allowed direct access.
#define png_get_rowbytes(png_ptr,info_ptr) ((info_ptr)->rowbytes)
#define png_get_image_width(png_ptr,info_ptr) ((info_ptr)->width)
#define png_get_image_height(png_ptr,info_ptr) ((info_ptr)->height)
#define png_get_bit_depth(png_ptr,info_ptr) ((info_ptr)->bit_depth)
#define png_get_color_type(png_ptr,info_ptr) ((info_ptr)->color_type)
#endif
#endif #endif
#include <stdlib.h> #include <stdlib.h>
@ -59,11 +73,11 @@ void Test_IMG(T_IO_Context * context)
if ((file=fopen(filename, "rb"))) if ((file=fopen(filename, "rb")))
{ {
// Lecture et vérification de la signature // Lecture et vérification de la signature
if (Read_bytes(file,IMG_header.Filler1,sizeof(IMG_header.Filler1)) if (Read_bytes(file,IMG_header.Filler1,6)
&& Read_word_le(file,&(IMG_header.Width)) && Read_word_le(file,&(IMG_header.Width))
&& Read_word_le(file,&(IMG_header.Height)) && Read_word_le(file,&(IMG_header.Height))
&& Read_bytes(file,IMG_header.Filler2,sizeof(IMG_header.Filler2)) && Read_bytes(file,IMG_header.Filler2,118)
&& Read_bytes(file,IMG_header.Palette,sizeof(IMG_header.Palette)) && Read_bytes(file,IMG_header.Palette,sizeof(T_Palette))
) )
{ {
if ( (!memcmp(IMG_header.Filler1,signature,6)) if ( (!memcmp(IMG_header.Filler1,signature,6))
@ -94,11 +108,11 @@ void Load_IMG(T_IO_Context * context)
{ {
file_size=File_length_file(file); file_size=File_length_file(file);
if (Read_bytes(file,IMG_header.Filler1,sizeof(IMG_header.Filler1)) if (Read_bytes(file,IMG_header.Filler1,6)
&& Read_word_le(file,&(IMG_header.Width)) && Read_word_le(file,&(IMG_header.Width))
&& Read_word_le(file,&(IMG_header.Height)) && Read_word_le(file,&(IMG_header.Height))
&& Read_bytes(file,IMG_header.Filler2,sizeof(IMG_header.Filler2)) && Read_bytes(file,IMG_header.Filler2,118)
&& Read_bytes(file,IMG_header.Palette,sizeof(IMG_header.Palette)) && Read_bytes(file,IMG_header.Palette,sizeof(T_Palette))
) )
{ {
@ -167,11 +181,11 @@ void Save_IMG(T_IO_Context * context)
memcpy(IMG_header.Palette,context->Palette,sizeof(T_Palette)); memcpy(IMG_header.Palette,context->Palette,sizeof(T_Palette));
if (Write_bytes(file,IMG_header.Filler1,sizeof(IMG_header.Filler1)) if (Write_bytes(file,IMG_header.Filler1,6)
&& Write_word_le(file,IMG_header.Width) && Write_word_le(file,IMG_header.Width)
&& Write_word_le(file,IMG_header.Height) && Write_word_le(file,IMG_header.Height)
&& Write_bytes(file,IMG_header.Filler2,sizeof(IMG_header.Filler2)) && Write_bytes(file,IMG_header.Filler2,118)
&& Write_bytes(file,IMG_header.Palette,sizeof(IMG_header.Palette)) && Write_bytes(file,IMG_header.Palette,sizeof(T_Palette))
) )
{ {
@ -204,7 +218,6 @@ void Save_IMG(T_IO_Context * context)
//////////////////////////////////// LBM //////////////////////////////////// //////////////////////////////////// LBM ////////////////////////////////////
#pragma pack(1)
typedef struct typedef struct
{ {
word Width; word Width;
@ -221,7 +234,6 @@ typedef struct
word X_screen; word X_screen;
word Y_screen; word Y_screen;
} T_LBM_Header; } T_LBM_Header;
#pragma pack()
byte * LBM_buffer; byte * LBM_buffer;
FILE *LBM_file; FILE *LBM_file;
@ -375,28 +387,42 @@ void Test_LBM(T_IO_Context * context)
} }
} }
// ------------------------- Attendre une section ------------------------- // Inspired by Allegro: storing a 4-character identifier as a 32bit litteral
byte Wait_for(byte * expected_section) #define ID4(a,b,c,d) ((((a)&255)<<24) | (((b)&255)<<16) | (((c)&255)<<8) | (((d)&255)))
{
// Valeur retournée: 1=Section trouvée, 0=Section non trouvée (erreur)
dword Taille_section;
byte section_read[4];
/// Skips the current section in an ILBM file.
/// This function should be called while the file pointer is right
/// after the 4-character code that identifies the section.
int LBM_Skip_section(void)
{
dword size;
if (!Read_dword_be(LBM_file,&size))
return 0;
if (size&1)
size++;
if (fseek(LBM_file,size,SEEK_CUR))
return 0;
return 1;
}
// ------------------------- Attendre une section -------------------------
byte LBM_Wait_for(byte * expected_section)
{
// Valeur retournée: 1=Section trouvée, 0=Section non trouvée (erreur)
byte section_read[4];
if (! Read_bytes(LBM_file,section_read,4))
return 0;
while (memcmp(section_read,expected_section,4)) // Sect. pas encore trouvée
{
if (!LBM_Skip_section())
return 0;
if (! Read_bytes(LBM_file,section_read,4)) if (! Read_bytes(LBM_file,section_read,4))
return 0; return 0;
while (memcmp(section_read,expected_section,4)) // Sect. pas encore trouvée
{
if (!Read_dword_be(LBM_file,&Taille_section))
return 0;
if (Taille_section&1)
Taille_section++;
if (fseek(LBM_file,Taille_section,SEEK_CUR))
return 0;
if (! Read_bytes(LBM_file,section_read,4))
return 0;
}
return 1;
} }
return 1;
}
// Les images ILBM sont stockés en bitplanes donc on doit trifouiller les bits pour // Les images ILBM sont stockés en bitplanes donc on doit trifouiller les bits pour
// en faire du chunky // en faire du chunky
@ -509,7 +535,7 @@ void Load_LBM(T_IO_Context * context)
byte temp_byte; byte temp_byte;
short b256; short b256;
dword nb_colors; dword nb_colors;
dword image_size; dword section_size;
short x_pos; short x_pos;
short y_pos; short y_pos;
short counter; short counter;
@ -531,7 +557,7 @@ void Load_LBM(T_IO_Context * context)
Read_bytes(LBM_file,section,4); Read_bytes(LBM_file,section,4);
Read_dword_be(LBM_file,&dummy); Read_dword_be(LBM_file,&dummy);
Read_bytes(LBM_file,format,4); Read_bytes(LBM_file,format,4);
if (!Wait_for((byte *)"BMHD")) if (!LBM_Wait_for((byte *)"BMHD"))
File_error=1; File_error=1;
Read_dword_be(LBM_file,&dummy); Read_dword_be(LBM_file,&dummy);
@ -551,7 +577,7 @@ void Load_LBM(T_IO_Context * context)
&& (Read_word_be(LBM_file,&header.Y_screen)) && (Read_word_be(LBM_file,&header.Y_screen))
&& header.Width && header.Height) && header.Width && header.Height)
{ {
if ( (header.BitPlanes) && (Wait_for((byte *)"CMAP")) ) if ( (header.BitPlanes) && (LBM_Wait_for((byte *)"CMAP")) )
{ {
Read_dword_be(LBM_file,&nb_colors); Read_dword_be(LBM_file,&nb_colors);
nb_colors/=3; nb_colors/=3;
@ -604,16 +630,73 @@ void Load_LBM(T_IO_Context * context)
if (Read_byte(LBM_file,&temp_byte)) if (Read_byte(LBM_file,&temp_byte))
File_error=2; File_error=2;
if ( (Wait_for((byte *)"BODY")) && (!File_error) ) // Keep reading sections until we find the body
while (1)
{ {
Read_dword_be(LBM_file,&image_size); if (! Read_bytes(LBM_file,section,4))
//swab((char *)&header.Width ,(char *)&context->Width,2); {
//swab((char *)&header.Height,(char *)&context->Height,2); File_error=2;
break;
}
// Found body : stop searching
if (!memcmp(section,"BODY",4))
break;
else if (!memcmp(section,"CRNG",4))
{
// Handle CRNG
// The content of a CRNG is as follows:
word padding;
word rate;
word flags;
byte min_col;
byte max_col;
//
if ( (Read_dword_be(LBM_file,&section_size))
&& (Read_word_be(LBM_file,&padding))
&& (Read_word_be(LBM_file,&rate))
&& (Read_word_be(LBM_file,&flags))
&& (Read_byte(LBM_file,&min_col))
&& (Read_byte(LBM_file,&max_col)))
{
if (section_size == 8 && min_col != max_col)
{
// Valid cycling range
if (max_col<min_col)
SWAP_BYTES(min_col,max_col)
context->Cycle_range[context->Color_cycles].Start=min_col;
context->Cycle_range[context->Color_cycles].End=max_col;
context->Cycle_range[context->Color_cycles].Inverse=(flags&2)?1:0;
context->Cycle_range[context->Color_cycles].Speed=(flags&1) ? rate/78 : 0;
context->Color_cycles++;
}
}
else
{
File_error=2;
break;
}
}
else
{
// ignore any number of unknown sections
if (!LBM_Skip_section())
{
File_error=2;
break;
}
}
}
if ( !File_error )
{
Read_dword_be(LBM_file,&section_size);
context->Width = header.Width; context->Width = header.Width;
context->Height = header.Height; context->Height = header.Height;
//swab((char *)&header.X_screen,(char *)&Original_screen_X,2);
//swab((char *)&header.Y_screen,(char *)&Original_screen_Y,2);
Original_screen_X = header.X_screen; Original_screen_X = header.X_screen;
Original_screen_Y = header.Y_screen; Original_screen_Y = header.Y_screen;
@ -874,6 +957,7 @@ void Save_LBM(T_IO_Context * context)
byte temp_byte; byte temp_byte;
word real_width; word real_width;
int file_size; int file_size;
int i;
File_error=0; File_error=0;
Get_full_filename(filename, context->File_name, context->File_directory); Get_full_filename(filename, context->File_name, context->File_directory);
@ -890,7 +974,6 @@ void Save_LBM(T_IO_Context * context)
// On corrige la largeur de l'image pour qu'elle soit multiple de 2 // On corrige la largeur de l'image pour qu'elle soit multiple de 2
real_width=context->Width+(context->Width&1); real_width=context->Width+(context->Width&1);
//swab((byte *)&real_width,(byte *)&header.Width,2);
header.Width=context->Width; header.Width=context->Width;
header.Height=context->Height; header.Height=context->Height;
header.X_org=0; header.X_org=0;
@ -924,6 +1007,22 @@ void Save_LBM(T_IO_Context * context)
Write_bytes(LBM_file,context->Palette,sizeof(T_Palette)); Write_bytes(LBM_file,context->Palette,sizeof(T_Palette));
for (i=0; i<context->Color_cycles; i++)
{
word flags=0;
flags|= context->Cycle_range[i].Speed?1:0; // Cycling or not
flags|= context->Cycle_range[i].Inverse?2:0; // Inverted
Write_bytes(LBM_file,"CRNG",4);
Write_dword_be(LBM_file,8); // Section size
Write_word_be(LBM_file,0); // Padding
Write_word_be(LBM_file,context->Cycle_range[i].Speed*78); // Rate
Write_word_be(LBM_file,flags); // Flags
Write_byte(LBM_file,context->Cycle_range[i].Start); // Min color
Write_byte(LBM_file,context->Cycle_range[i].End); // Max color
// No padding, size is multiple of 2
}
Write_bytes(LBM_file,"BODY",4); Write_bytes(LBM_file,"BODY",4);
Write_dword_be(LBM_file,0); // On mettra la taille à jour à la fin Write_dword_be(LBM_file,0); // On mettra la taille à jour à la fin
@ -948,8 +1047,8 @@ void Save_LBM(T_IO_Context * context)
file_size=File_length(filename); file_size=File_length(filename);
LBM_file=fopen(filename,"rb+"); LBM_file=fopen(filename,"rb+");
fseek(LBM_file,820,SEEK_SET); fseek(LBM_file,820+context->Color_cycles*16,SEEK_SET);
Write_dword_be(LBM_file,file_size-824); Write_dword_be(LBM_file,file_size-824-context->Color_cycles*16);
if (!File_error) if (!File_error)
{ {
@ -1554,7 +1653,6 @@ void Save_BMP(T_IO_Context * context)
//////////////////////////////////// GIF //////////////////////////////////// //////////////////////////////////// GIF ////////////////////////////////////
#pragma pack(1)
typedef struct typedef struct
{ {
word Width; // Width of the complete image area word Width; // Width of the complete image area
@ -1573,7 +1671,6 @@ typedef struct
byte Indicator; // Misc image information byte Indicator; // Misc image information
byte Nb_bits_pixel; // Nb de bits par pixel byte Nb_bits_pixel; // Nb de bits par pixel
} T_GIF_IDB; // Image Descriptor Block } T_GIF_IDB; // Image Descriptor Block
#pragma pack()
typedef struct typedef struct
{ {
@ -1735,7 +1832,7 @@ void Load_GIF(T_IO_Context * context)
word color_index; // index de traitement d'une couleur word color_index; // index de traitement d'une couleur
byte size_to_read; // Nombre de données à lire (divers) byte size_to_read; // Nombre de données à lire (divers)
byte block_identifier; // Code indicateur du type de bloc en cours byte block_identifier; // Code indicateur du type de bloc en cours
word initial_nb_bits; // Nb de bits au début du traitement LZW byte initial_nb_bits; // Nb de bits au début du traitement LZW
word special_case=0; // Mémoire pour le cas spécial word special_case=0; // Mémoire pour le cas spécial
word old_code=0; // Code précédent word old_code=0; // Code précédent
word byte_read; // Sauvegarde du code en cours de lecture word byte_read; // Sauvegarde du code en cours de lecture
@ -1787,8 +1884,6 @@ void Load_GIF(T_IO_Context * context)
// Ordre de Classement = (LSDB.Aspect and $80) // Ordre de Classement = (LSDB.Aspect and $80)
nb_colors=(1 << ((LSDB.Resol & 0x07)+1)); nb_colors=(1 << ((LSDB.Resol & 0x07)+1));
initial_nb_bits=(LSDB.Resol & 0x07)+2;
if (LSDB.Resol & 0x80) if (LSDB.Resol & 0x80)
{ {
// Palette globale dispo: // Palette globale dispo:
@ -1796,24 +1891,12 @@ void Load_GIF(T_IO_Context * context)
if (Config.Clear_palette) if (Config.Clear_palette)
memset(context->Palette,0,sizeof(T_Palette)); memset(context->Palette,0,sizeof(T_Palette));
// On peut maintenant charger la nouvelle palette: // Load the palette
if (!(LSDB.Aspect & 0x80)) for(color_index=0;color_index<nb_colors;color_index++)
// Palette dans l'ordre:
for(color_index=0;color_index<nb_colors;color_index++)
{
Read_byte(GIF_file,&(context->Palette[color_index].R));
Read_byte(GIF_file,&(context->Palette[color_index].G));
Read_byte(GIF_file,&(context->Palette[color_index].B));
}
else
{ {
// Palette triée par composantes: Read_byte(GIF_file,&(context->Palette[color_index].R));
for (color_index=0;color_index<nb_colors;color_index++) Read_byte(GIF_file,&(context->Palette[color_index].G));
Read_byte(GIF_file,&(context->Palette[color_index].R)); Read_byte(GIF_file,&(context->Palette[color_index].B));
for (color_index=0;color_index<nb_colors;color_index++)
Read_byte(GIF_file,&(context->Palette[color_index].G));
for (color_index=0;color_index<nb_colors;color_index++)
Read_byte(GIF_file,&(context->Palette[color_index].B));
} }
} }
@ -1924,6 +2007,57 @@ void Load_GIF(T_IO_Context * context)
} }
} }
} }
else if (!memcmp(aeb,"CRNG\0\0\0\0" "1.0",0x0B))
{
// Color animation. Similar to a LBM CRNG chunk.
word rate;
word flags;
byte min_col;
byte max_col;
//
Read_byte(GIF_file,&size_to_read);
for(;size_to_read>0 && !File_error;size_to_read-=6)
{
if ( (Read_word_be(GIF_file,&rate))
&& (Read_word_be(GIF_file,&flags))
&& (Read_byte(GIF_file,&min_col))
&& (Read_byte(GIF_file,&max_col)))
{
if (min_col != max_col)
{
// Valid cycling range
if (max_col<min_col)
SWAP_BYTES(min_col,max_col)
context->Cycle_range[context->Color_cycles].Start=min_col;
context->Cycle_range[context->Color_cycles].End=max_col;
context->Cycle_range[context->Color_cycles].Inverse=(flags&2)?1:0;
context->Cycle_range[context->Color_cycles].Speed=(flags&1)?rate/78:0;
context->Color_cycles++;
}
}
else
{
File_error=1;
}
}
// Read end-of-block delimiter
if (!File_error)
Read_byte(GIF_file,&size_to_read);
if (size_to_read!=0)
File_error=1;
}
else
{
// Unknown extension, skip.
Read_byte(GIF_file,&size_to_read);
while (size_to_read!=0 && !File_error)
{
fseek(GIF_file,size_to_read,SEEK_CUR);
Read_byte(GIF_file,&size_to_read);
}
}
} }
else else
{ {
@ -1961,7 +2095,6 @@ void Load_GIF(T_IO_Context * context)
&& Read_word_le(GIF_file,&(IDB.Image_width)) && Read_word_le(GIF_file,&(IDB.Image_width))
&& Read_word_le(GIF_file,&(IDB.Image_height)) && Read_word_le(GIF_file,&(IDB.Image_height))
&& Read_byte(GIF_file,&(IDB.Indicator)) && Read_byte(GIF_file,&(IDB.Indicator))
&& Read_byte(GIF_file,&(IDB.Nb_bits_pixel))
&& IDB.Image_width && IDB.Image_height) && IDB.Image_width && IDB.Image_height)
{ {
@ -1974,42 +2107,38 @@ void Load_GIF(T_IO_Context * context)
{ {
// Palette locale dispo // Palette locale dispo
nb_colors=(1 << ((IDB.Indicator & 0x07)+1)); if (Config.Clear_palette)
initial_nb_bits=(IDB.Indicator & 0x07)+2; memset(context->Palette,0,sizeof(T_Palette));
if (!(IDB.Indicator & 0x40)) nb_colors=(1 << ((IDB.Indicator & 0x07)+1));
// Palette dans l'ordre: // Load the palette
for(color_index=0;color_index<nb_colors;color_index++) for(color_index=0;color_index<nb_colors;color_index++)
{
Read_byte(GIF_file,&(context->Palette[color_index].R));
Read_byte(GIF_file,&(context->Palette[color_index].G));
Read_byte(GIF_file,&(context->Palette[color_index].B));
}
else
{ {
// Palette triée par composantes: Read_byte(GIF_file,&(context->Palette[color_index].R));
for (color_index=0;color_index<nb_colors;color_index++) Read_byte(GIF_file,&(context->Palette[color_index].G));
Read_byte(GIF_file,&(context->Palette[color_index].R)); Read_byte(GIF_file,&(context->Palette[color_index].B));
for (color_index=0;color_index<nb_colors;color_index++)
Read_byte(GIF_file,&(context->Palette[color_index].G));
for (color_index=0;color_index<nb_colors;color_index++)
Read_byte(GIF_file,&(context->Palette[color_index].B));
} }
} }
Palette_loaded(context); Palette_loaded(context);
value_clr =nb_colors+0; File_error=0;
value_eof =nb_colors+1; if (!Read_byte(GIF_file,&(initial_nb_bits)))
alphabet_free=nb_colors+2; File_error=1;
GIF_nb_bits =initial_nb_bits;
value_clr =(1<<initial_nb_bits)+0;
value_eof =(1<<initial_nb_bits)+1;
alphabet_free=(1<<initial_nb_bits)+2;
GIF_nb_bits =initial_nb_bits + 1;
alphabet_max =((1 << GIF_nb_bits)-1); alphabet_max =((1 << GIF_nb_bits)-1);
GIF_interlaced =(IDB.Indicator & 0x40); GIF_interlaced =(IDB.Indicator & 0x40);
GIF_pass =0; GIF_pass =0;
/*Init_lecture();*/ /*Init_lecture();*/
File_error=0;
GIF_finished_interlaced_image=0; GIF_finished_interlaced_image=0;
//////////////////////////////////////////// DECOMPRESSION LZW // //////////////////////////////////////////// DECOMPRESSION LZW //
@ -2057,9 +2186,9 @@ void Load_GIF(T_IO_Context * context)
} }
else // Code Clear rencontré else // Code Clear rencontré
{ {
GIF_nb_bits =initial_nb_bits; GIF_nb_bits =initial_nb_bits + 1;
alphabet_max =((1 << GIF_nb_bits)-1); alphabet_max =((1 << GIF_nb_bits)-1);
alphabet_free =nb_colors+2; alphabet_free =(1<<initial_nb_bits)+2;
special_case =GIF_get_next_code(); special_case =GIF_get_next_code();
old_code =GIF_current_code; old_code =GIF_current_code;
GIF_new_pixel(context, &IDB, GIF_current_code); GIF_new_pixel(context, &IDB, GIF_current_code);
@ -2251,15 +2380,19 @@ void Save_GIF(T_IO_Context * context)
Write_byte(GIF_file,LSDB.Aspect) ) Write_byte(GIF_file,LSDB.Aspect) )
{ {
// Le LSDB a été correctement écrit. // Le LSDB a été correctement écrit.
int i;
// On sauve la palette // On sauve la palette
if (Write_bytes(GIF_file,context->Palette,768)) for(i=0;i<256 && !File_error;i++)
{
if (!Write_byte(GIF_file,context->Palette[i].R)
||!Write_byte(GIF_file,context->Palette[i].G)
||!Write_byte(GIF_file,context->Palette[i].B))
File_error=1;
}
if (!File_error)
{ {
// La palette a été correctement écrite. // La palette a été correctement écrite.
// Le jour où on se servira des blocks d'extensions pour placer
// des commentaires, on le fera ici.
// Ecriture de la transparence // Ecriture de la transparence
//Write_bytes(GIF_file,"\x21\xF9\x04\x01\x00\x00\xNN\x00",8); //Write_bytes(GIF_file,"\x21\xF9\x04\x01\x00\x00\xNN\x00",8);
@ -2275,6 +2408,26 @@ void Save_GIF(T_IO_Context * context)
Write_byte(GIF_file,strlen(context->Comment)); Write_byte(GIF_file,strlen(context->Comment));
Write_bytes(GIF_file,context->Comment,strlen(context->Comment)+1); Write_bytes(GIF_file,context->Comment,strlen(context->Comment)+1);
} }
// Write cycling colors
if (context->Color_cycles)
{
int i;
Write_bytes(GIF_file,"\x21\xff\x0B" "CRNG\0\0\0\0" "1.0",14);
Write_byte(GIF_file,context->Color_cycles*6);
for (i=0; i<context->Color_cycles; i++)
{
word flags=0;
flags|= context->Cycle_range[i].Speed?1:0; // Cycling or not
flags|= context->Cycle_range[i].Inverse?2:0; // Inverted
Write_word_be(GIF_file,context->Cycle_range[i].Speed*78); // Rate
Write_word_be(GIF_file,flags); // Flags
Write_byte(GIF_file,context->Cycle_range[i].Start); // Min color
Write_byte(GIF_file,context->Cycle_range[i].End); // Max color
}
Write_byte(GIF_file,0);
}
// Loop on all layers // Loop on all layers
for (current_layer=0; for (current_layer=0;
@ -2282,7 +2435,7 @@ void Save_GIF(T_IO_Context * context)
current_layer++) current_layer++)
{ {
// Write a Graphic Control Extension // Write a Graphic Control Extension
char GCE_block[] = "\x21\xF9\x04\x04\x05\x00\x00\x00"; byte GCE_block[] = "\x21\xF9\x04\x04\x05\x00\x00\x00";
// 'Default' values: // 'Default' values:
// Disposal method "Do not dispose" // Disposal method "Do not dispose"
// Duration 5/100s (minimum viable value for current web browsers) // Duration 5/100s (minimum viable value for current web browsers)
@ -2542,7 +2695,6 @@ void Save_GIF(T_IO_Context * context)
//////////////////////////////////// PCX //////////////////////////////////// //////////////////////////////////// PCX ////////////////////////////////////
#pragma pack(1)
typedef struct typedef struct
{ {
byte Manufacturer; // |_ Il font chier ces cons! Ils auraient pu byte Manufacturer; // |_ Il font chier ces cons! Ils auraient pu
@ -2564,7 +2716,6 @@ typedef struct
word Screen_Y; // | l'écran d'origine word Screen_Y; // | l'écran d'origine
byte Filler[54]; // Ca... J'adore! byte Filler[54]; // Ca... J'adore!
} T_PCX_Header; } T_PCX_Header;
#pragma pack()
T_PCX_Header PCX_header; T_PCX_Header PCX_header;
@ -3010,14 +3161,14 @@ void Save_PCX(T_IO_Context * context)
Write_word_le(file,PCX_header.Y_max) && Write_word_le(file,PCX_header.Y_max) &&
Write_word_le(file,PCX_header.X_dpi) && Write_word_le(file,PCX_header.X_dpi) &&
Write_word_le(file,PCX_header.Y_dpi) && Write_word_le(file,PCX_header.Y_dpi) &&
Write_bytes(file,&(PCX_header.Palette_16c),sizeof(PCX_header.Palette_16c)) && Write_bytes(file,&(PCX_header.Palette_16c),48) &&
Write_bytes(file,&(PCX_header.Reserved),1) && Write_bytes(file,&(PCX_header.Reserved),1) &&
Write_bytes(file,&(PCX_header.Plane),1) && Write_bytes(file,&(PCX_header.Plane),1) &&
Write_word_le(file,PCX_header.Bytes_per_plane_line) && Write_word_le(file,PCX_header.Bytes_per_plane_line) &&
Write_word_le(file,PCX_header.Palette_info) && Write_word_le(file,PCX_header.Palette_info) &&
Write_word_le(file,PCX_header.Screen_X) && Write_word_le(file,PCX_header.Screen_X) &&
Write_word_le(file,PCX_header.Screen_Y) && Write_word_le(file,PCX_header.Screen_Y) &&
Write_bytes(file,&(PCX_header.Filler),sizeof(PCX_header.Filler)) ) Write_bytes(file,&(PCX_header.Filler),54) )
{ {
line_size=PCX_header.Bytes_per_plane_line*PCX_header.Plane; line_size=PCX_header.Bytes_per_plane_line*PCX_header.Plane;
@ -3102,7 +3253,7 @@ void Test_SCx(T_IO_Context * context)
if ((file=fopen(filename, "rb"))) if ((file=fopen(filename, "rb")))
{ {
// Lecture et vérification de la signature // Lecture et vérification de la signature
if (Read_bytes(file,SCx_header.Filler1,sizeof(SCx_header.Filler1)) if (Read_bytes(file,SCx_header.Filler1,4)
&& Read_word_le(file, &(SCx_header.Width)) && Read_word_le(file, &(SCx_header.Width))
&& Read_word_le(file, &(SCx_header.Height)) && Read_word_le(file, &(SCx_header.Height))
&& Read_byte(file, &(SCx_header.Filler2)) && Read_byte(file, &(SCx_header.Filler2))
@ -3138,7 +3289,7 @@ void Load_SCx(T_IO_Context * context)
{ {
file_size=File_length_file(file); file_size=File_length_file(file);
if (Read_bytes(file,SCx_header.Filler1,sizeof(SCx_header.Filler1)) if (Read_bytes(file,SCx_header.Filler1,4)
&& Read_word_le(file, &(SCx_header.Width)) && Read_word_le(file, &(SCx_header.Width))
&& Read_word_le(file, &(SCx_header.Height)) && Read_word_le(file, &(SCx_header.Height))
&& Read_byte(file, &(SCx_header.Filler2)) && Read_byte(file, &(SCx_header.Filler2))
@ -3259,7 +3410,7 @@ void Save_SCx(T_IO_Context * context)
SCx_header.Filler2=0xAF; SCx_header.Filler2=0xAF;
SCx_header.Planes=0x00; SCx_header.Planes=0x00;
if (Write_bytes(file,SCx_header.Filler1,sizeof(SCx_header.Filler1)) if (Write_bytes(file,SCx_header.Filler1,4)
&& Write_word_le(file, SCx_header.Width) && Write_word_le(file, SCx_header.Width)
&& Write_word_le(file, SCx_header.Height) && Write_word_le(file, SCx_header.Height)
&& Write_byte(file, SCx_header.Filler2) && Write_byte(file, SCx_header.Filler2)
@ -3294,6 +3445,44 @@ void Save_SCx(T_IO_Context * context)
} }
} }
//////////////////////////////////// XPM ////////////////////////////////////
void Save_XPM(T_IO_Context* context)
{
FILE* file;
char filename[MAX_PATH_CHARACTERS];
int i,j;
Get_full_filename(filename, context->File_name, context->File_directory);
File_error = 0;
file = fopen(filename, "w");
if (file == NULL)
{
File_error = 1;
return;
}
fprintf(file, "/* XPM */\nstatic char* pixmap[] = {\n");
fprintf(file, "\"%d %d 256 2\",\n", context->Width, context->Height);
for (i = 0; i < 256; i++)
{
fprintf(file,"\"%2.2X c #%2.2x%2.2x%2.2x\",\n", i, context->Palette[i].R, context->Palette[i].G,
context->Palette[i].B);
}
for (j = 0; j < context->Height; j++)
{
fprintf(file, "\"");
for (i = 0; i < context->Width; i++)
{
fprintf(file, "%2.2X", Get_pixel(context, i, j));
}
fprintf(file,"\"\n");
}
fclose(file);
}
//////////////////////////////////// PNG //////////////////////////////////// //////////////////////////////////// PNG ////////////////////////////////////
@ -3323,6 +3512,70 @@ void Test_PNG(T_IO_Context * context)
} }
} }
/// Used by a callback in Load_PNG
T_IO_Context * PNG_current_context;
int PNG_read_unknown_chunk(__attribute__((unused)) png_structp ptr, png_unknown_chunkp chunk)
{
// png_unknown_chunkp members:
// png_byte name[5];
// png_byte *data;
// png_size_t size;
if (!strcmp((const char *)chunk->name, "crNg"))
{
// Color animation. Similar to a LBM CRNG chunk.
unsigned int i;
byte *chunk_ptr = chunk->data;
// Should be a multiple of 6
if (chunk->size % 6)
return (-1);
for(i=0;i<chunk->size/6 && i<16; i++)
{
word rate;
word flags;
byte min_col;
byte max_col;
// Rate (big-endian word)
rate = *(chunk_ptr++) << 8;
rate |= *(chunk_ptr++);
// Flags (big-endian)
flags = *(chunk_ptr++) << 8;
flags |= *(chunk_ptr++);
// Min color
min_col = *(chunk_ptr++);
// Max color
max_col = *(chunk_ptr++);
// Check validity
if (min_col != max_col)
{
// Valid cycling range
if (max_col<min_col)
SWAP_BYTES(min_col,max_col)
PNG_current_context->Cycle_range[i].Start=min_col;
PNG_current_context->Cycle_range[i].End=max_col;
PNG_current_context->Cycle_range[i].Inverse=(flags&2)?1:0;
PNG_current_context->Cycle_range[i].Speed=(flags&1) ? rate/78 : 0;
PNG_current_context->Color_cycles=i+1;
}
}
return (1); // >0 = success
}
return (0); /* did not recognize */
}
png_bytep * Row_pointers; png_bytep * Row_pointers;
// -- Lire un fichier au format PNG ----------------------------------------- // -- Lire un fichier au format PNG -----------------------------------------
void Load_PNG(T_IO_Context * context) void Load_PNG(T_IO_Context * context)
@ -3360,6 +3613,7 @@ void Load_PNG(T_IO_Context * context)
{ {
png_byte color_type; png_byte color_type;
png_byte bit_depth; png_byte bit_depth;
png_voidp user_chunk_ptr;
// Setup a return point. If a pnglib loading error occurs // Setup a return point. If a pnglib loading error occurs
// in this if(), the else will be executed. // in this if(), the else will be executed.
@ -3369,10 +3623,17 @@ void Load_PNG(T_IO_Context * context)
// Inform pnglib we already loaded the header. // Inform pnglib we already loaded the header.
png_set_sig_bytes(png_ptr, 8); png_set_sig_bytes(png_ptr, 8);
// Hook the handler for unknown chunks
user_chunk_ptr = png_get_user_chunk_ptr(png_ptr);
png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, &PNG_read_unknown_chunk);
// This is a horrid way to pass parameters, but we don't get
// much choice. PNG loader can't be reintrant.
PNG_current_context=context;
// Load file information // Load file information
png_read_info(png_ptr, info_ptr); png_read_info(png_ptr, info_ptr);
color_type = info_ptr->color_type; color_type = png_get_color_type(png_ptr,info_ptr);
bit_depth = info_ptr->bit_depth; bit_depth = png_get_bit_depth(png_ptr,info_ptr);
// If it's any supported file // If it's any supported file
// (Note: As of writing this, this test covers every possible // (Note: As of writing this, this test covers every possible
@ -3425,9 +3686,9 @@ void Load_PNG(T_IO_Context * context)
} }
} }
if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA)
Pre_load(context,info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG,PIXEL_SIMPLE,1); Pre_load(context,png_get_image_width(png_ptr,info_ptr),png_get_image_height(png_ptr,info_ptr),File_length_file(file),FORMAT_PNG,PIXEL_SIMPLE,1);
else else
Pre_load(context, info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG,context->Ratio,0); Pre_load(context,png_get_image_width(png_ptr,info_ptr),png_get_image_height(png_ptr,info_ptr),File_length_file(file),FORMAT_PNG,context->Ratio,0);
if (File_error==0) if (File_error==0)
{ {
@ -3535,8 +3796,8 @@ void Load_PNG(T_IO_Context * context)
} }
} }
context->Width=info_ptr->width; context->Width=png_get_image_width(png_ptr,info_ptr);
context->Height=info_ptr->height; context->Height=png_get_image_height(png_ptr,info_ptr);
png_set_interlace_handling(png_ptr); png_set_interlace_handling(png_ptr);
png_read_update_info(png_ptr, info_ptr); png_read_update_info(png_ptr, info_ptr);
@ -3556,7 +3817,7 @@ void Load_PNG(T_IO_Context * context)
// 8bpp // 8bpp
for (y=0; y<context->Height; y++) for (y=0; y<context->Height; y++)
Row_pointers[y] = (png_byte*) malloc(info_ptr->rowbytes); Row_pointers[y] = (png_byte*) malloc(png_get_rowbytes(png_ptr,info_ptr));
row_pointers_allocated = 1; row_pointers_allocated = 1;
png_read_image(png_ptr, Row_pointers); png_read_image(png_ptr, Row_pointers);
@ -3575,7 +3836,7 @@ void Load_PNG(T_IO_Context * context)
// It's a preview // It's a preview
// Unfortunately we need to allocate loads of memory // Unfortunately we need to allocate loads of memory
for (y=0; y<context->Height; y++) for (y=0; y<context->Height; y++)
Row_pointers[y] = (png_byte*) malloc(info_ptr->rowbytes); Row_pointers[y] = (png_byte*) malloc(png_get_rowbytes(png_ptr,info_ptr));
row_pointers_allocated = 1; row_pointers_allocated = 1;
png_read_image(png_ptr, Row_pointers); png_read_image(png_ptr, Row_pointers);
@ -3646,6 +3907,8 @@ void Save_PNG(T_IO_Context * context)
byte * pixel_ptr; byte * pixel_ptr;
png_structp png_ptr; png_structp png_ptr;
png_infop info_ptr; png_infop info_ptr;
png_unknown_chunk crng_chunk;
byte cycle_data[16*6]; // Storage for color-cycling data, referenced by crng_chunk
Get_full_filename(filename, context->File_name, context->File_directory); Get_full_filename(filename, context->File_name, context->File_directory);
File_error=0; File_error=0;
@ -3674,9 +3937,15 @@ void Save_PNG(T_IO_Context * context)
{ {
// Commentaires texte PNG // Commentaires texte PNG
// Cette partie est optionnelle // Cette partie est optionnelle
#ifdef PNG_iTXt_SUPPORTED
png_text text_ptr[2] = {
{-1, "Software", "Grafx2", 6, 0, NULL, NULL},
{-1, "Title", NULL, 0, 0, NULL, NULL}
#else
png_text text_ptr[2] = { png_text text_ptr[2] = {
{-1, "Software", "Grafx2", 6}, {-1, "Software", "Grafx2", 6},
{-1, "Title", NULL, 0} {-1, "Title", NULL, 0}
#endif
}; };
int nb_text_chunks=1; int nb_text_chunks=1;
if (context->Comment[0]) if (context->Comment[0])
@ -3711,6 +3980,57 @@ void Save_PNG(T_IO_Context * context)
default: default:
break; break;
} }
// Write cycling colors
if (context->Color_cycles)
{
// Save a chunk called 'crNg'
// The case is selected by the following rules from PNG standard:
// char 1: non-mandatory = lowercase
// char 2: private (not standard) = lowercase
// char 3: reserved = always uppercase
// char 4: can be copied by editors = lowercase
// First, turn our nice structure into byte array
// (just to avoid padding in structures)
byte *chunk_ptr = cycle_data;
int i;
for (i=0; i<context->Color_cycles; i++)
{
word flags=0;
flags|= context->Cycle_range[i].Speed?1:0; // Cycling or not
flags|= context->Cycle_range[i].Inverse?2:0; // Inverted
// Big end of Rate
*(chunk_ptr++) = (context->Cycle_range[i].Speed*78) >> 8;
// Low end of Rate
*(chunk_ptr++) = (context->Cycle_range[i].Speed*78) & 0xFF;
// Big end of Flags
*(chunk_ptr++) = (flags) >> 8;
// Low end of Flags
*(chunk_ptr++) = (flags) & 0xFF;
// Min color
*(chunk_ptr++) = context->Cycle_range[i].Start;
// Max color
*(chunk_ptr++) = context->Cycle_range[i].End;
}
// Build one unknown_chuck structure
memcpy(crng_chunk.name, "crNg",5);
crng_chunk.data=cycle_data;
crng_chunk.size=context->Color_cycles*6;
crng_chunk.location=PNG_HAVE_PLTE;
// Give it to libpng
png_set_unknown_chunks(png_ptr, info_ptr, &crng_chunk, 1);
// libpng seems to ignore the location I provided earlier.
png_set_unknown_chunk_location(png_ptr, info_ptr, 0, PNG_HAVE_PLTE);
}
png_write_info(png_ptr, info_ptr); png_write_info(png_ptr, info_ptr);
/* ecriture des pixels de l'image */ /* ecriture des pixels de l'image */

View File

@ -2,6 +2,7 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2009 Franck Charlet Copyright 2009 Franck Charlet
Copyright 2008 Peter Gordon Copyright 2008 Peter Gordon
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud
@ -22,14 +23,22 @@
along with Grafx2; if not, see <http://www.gnu.org/licenses/> along with Grafx2; if not, see <http://www.gnu.org/licenses/>
*/ */
#include <SDL_syswm.h>
#if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__) #if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
#include <proto/dos.h> #include <proto/dos.h>
#include <sys/types.h> #include <sys/types.h>
#include <dirent.h> #include <dirent.h>
#define isHidden(x) (0) #define isHidden(x) (0)
#elif defined (__MINT__)
#include <mint/sysbind.h>
#include <dirent.h>
#define isHidden(x) (0)
#elif defined(__WIN32__) #elif defined(__WIN32__)
#include <dirent.h> #include <dirent.h>
#include <windows.h> #include <windows.h>
#include <commdlg.h>
#define isHidden(x) (GetFileAttributesA((x)->d_name)&FILE_ATTRIBUTE_HIDDEN) #define isHidden(x) (GetFileAttributesA((x)->d_name)&FILE_ATTRIBUTE_HIDDEN)
#else #else
#include <dirent.h> #include <dirent.h>
@ -62,12 +71,66 @@
#include "help.h" #include "help.h"
#include "filesel.h" #include "filesel.h"
#define NORMAL_FILE_COLOR MC_Light // color du texte pour une ligne de fichier non sélectionné #define NORMAL_FILE_COLOR MC_Light // color du texte pour une ligne de
#define NORMAL_DIRECTORY_COLOR MC_Dark // color du texte pour une ligne de répertoire non sélectionné // fichier non sélectionné
#define NORMAL_BACKGROUND_COLOR MC_Black // color du fond pour une ligne non sélectionnée #define NORMAL_DIRECTORY_COLOR MC_Dark // color du texte pour une ligne de
#define SELECTED_FILE_COLOR MC_White // color du texte pour une ligne de fichier sélectionnée // répertoire non sélectionné
#define SELECTED_DIRECTORY_COLOR MC_Light // color du texte pour une ligne de repértoire sélectionnée #define NORMAL_BACKGROUND_COLOR MC_Black // color du fond pour une ligne
#define SELECTED_BACKGROUND_COLOR MC_Dark // color du fond pour une ligne sélectionnée // non sélectionnée
#define SELECTED_FILE_COLOR MC_White // color du texte pour une ligne de
// fichier sélectionnée
#define SELECTED_DIRECTORY_COLOR MC_Light // color du texte pour une ligne de
// repértoire sélectionnée
#define SELECTED_BACKGROUND_COLOR MC_Dark // color du fond pour une ligne
// sélectionnée
// -- Native fileselector for WIN32
// Returns 0 if all ok, something else if failed
byte Native_filesel(byte load)
{
//load = load;
#ifdef __WIN32__
OPENFILENAME ofn;
char szFileName[MAX_PATH] = "";
SDL_SysWMinfo wminfo;
HWND hwnd;
SDL_VERSION(&wminfo.version);
SDL_GetWMInfo(&wminfo);
hwnd = wminfo.window;
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER;
if(load) ofn.Flags |= OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = "txt";
if(load)
{
if (GetOpenFileName(&ofn))
// Do something usefull with the filename stored in szFileName
return 0;
else
// error - check if its just user pressing cancel or something else
return CommDlgExtendedError();
} else if(GetSaveFileName(&ofn)) {
return 0;
} else {
// Check if cancel
return CommDlgExtendedError();
}
#else
return 255; // fail !
#endif
}
// -- "Standard" fileselector for other platforms
// -- Fileselector data // -- Fileselector data
@ -146,30 +209,48 @@ void Free_fileselector_list(T_Fileselector *list)
Recount_files(list); Recount_files(list);
} }
char * Format_filename(const char * fname, int type) char * Format_filename(const char * fname, word max_length, int type)
{ {
static char result[19]; static char result[40];
int c; int c;
int other_cursor; int other_cursor;
int pos_last_dot; int pos_last_dot;
// safety
if (max_length>40)
max_length=40;
if (strcmp(fname,PARENT_DIR)==0) if (strcmp(fname,PARENT_DIR)==0)
{ {
strcpy(result,"<-PARENT DIRECTORY"); strcpy(result,"<-PARENT DIRECTORY");
// Append spaces
for (c=18; c<max_length-1; c++)
result[c]=' ';
result[c]='\0';
} }
else if (fname[0]=='.' || type==1 || type==2) else if (fname[0]=='.' || type==1 || type==2)
{ {
// Files ".something" or drives or directories: Aligned left on 18 chars max // Files ".something" or drives or directories: Aligned left on (max_length-1) chars max
strcpy(result," "); // Initialize as all spaces
for (c=0;fname[c]!='\0' && c < 18;c++) for (c=0; c<max_length-1; c++)
result[c]=' ';
result[c]='\0';
for (c=0;fname[c]!='\0' && c < max_length-1;c++)
result[c]=fname[c]; result[c]=fname[c];
// A special character indicates the filename is truncated // A special character indicates the filename is truncated
if (c >= 18) if (c >= max_length-1)
result[17]=ELLIPSIS_CHARACTER; result[max_length-2]=ELLIPSIS_CHARACTER;
} }
else else
{ {
strcpy(result," . "); // Initialize as all spaces
for (c = 0; c<max_length-1; c++)
result[c]=' ';
result[c]='\0';
result[max_length-5]='.';
// Look for the last dot in filename // Look for the last dot in filename
pos_last_dot = -1; pos_last_dot = -1;
for (c = 0; fname[c]!='\0'; c++) for (c = 0; fname[c]!='\0'; c++)
@ -179,9 +260,9 @@ char * Format_filename(const char * fname, int type)
// Copy the part before the dot // Copy the part before the dot
for (c=0; c!=pos_last_dot && fname[c]!='\0'; c++) for (c=0; c!=pos_last_dot && fname[c]!='\0'; c++)
{ {
if (c > 13) if (c > max_length-6)
{ {
result[13]=ELLIPSIS_CHARACTER; result[max_length-6]=ELLIPSIS_CHARACTER;
break; break;
} }
result[c]=fname[c]; result[c]=fname[c];
@ -190,7 +271,7 @@ char * Format_filename(const char * fname, int type)
// Ensuite on recopie la partie qui suit le point (si nécessaire): // Ensuite on recopie la partie qui suit le point (si nécessaire):
if (pos_last_dot != -1) if (pos_last_dot != -1)
{ {
for (c = pos_last_dot+1,other_cursor=15;fname[c]!='\0' && other_cursor < 18;c++,other_cursor++) for (c = pos_last_dot+1,other_cursor=max_length-4;fname[c]!='\0' && other_cursor < max_length-1;c++,other_cursor++)
result[other_cursor]=fname[c]; result[other_cursor]=fname[c];
} }
} }
@ -199,25 +280,29 @@ char * Format_filename(const char * fname, int type)
// -- Rajouter a la liste des elements de la liste un element --------------- // -- Rajouter a la liste des elements de la liste un element ---------------
void Add_element_to_list(T_Fileselector *list, const char * fname, int type) void Add_element_to_list(T_Fileselector *list, const char * full_name, const char *short_name, int type, byte icon)
// Cette procedure ajoute a la liste chainee un fichier passé en argument. // Cette procedure ajoute a la liste chainee un fichier passé en argument.
{ {
// Pointeur temporaire d'insertion // Working element
T_Fileselector_item * temp_item; T_Fileselector_item * temp_item;
// On alloue de la place pour un nouvel element // Allocate enough room for one struct + the visible label
temp_item=(T_Fileselector_item *)malloc(sizeof(T_Fileselector_item)); temp_item=(T_Fileselector_item *)malloc(sizeof(T_Fileselector_item)+strlen(short_name));
// On met a jour le nouvel emplacement: // Initialize element
strcpy(temp_item->Short_name,Format_filename(fname, type)); strcpy(temp_item->Short_name,short_name);
strcpy(temp_item->Full_name,fname); strcpy(temp_item->Full_name,full_name);
temp_item->Type = type; temp_item->Type = type;
temp_item->Icon = icon;
// Doubly-linked
temp_item->Next =list->First; temp_item->Next =list->First;
temp_item->Previous=NULL; temp_item->Previous=NULL;
if (list->First!=NULL) if (list->First!=NULL)
list->First->Previous=temp_item; list->First->Previous=temp_item;
// Put new element at the beginning
list->First=temp_item; list->First=temp_item;
} }
@ -275,8 +360,25 @@ void Read_list_of_files(T_Fileselector *list, byte selected_format)
// Après effacement, il ne reste ni fichier ni répertoire dans la liste // Après effacement, il ne reste ni fichier ni répertoire dans la liste
// On lit tous les répertoires: // On lit tous les répertoires:
#if defined (__MINT__)
static char path[1024];
static char path2[1024];
path[0]='\0';
path2[0]='\0';
char currentDrive='A';
currentDrive=currentDrive+Dgetdrv();
Dgetpath(path,0);
sprintf(path2,"%c:\%s",currentDrive,path);
strcat(path2,PATH_SEPARATOR);
current_directory=opendir(path2);
#else
current_path=getcwd(NULL,0); current_path=getcwd(NULL,0);
current_directory=opendir(current_path); current_directory=opendir(current_path);
#endif
while ((entry=readdir(current_directory))) while ((entry=readdir(current_directory)))
{ {
// On ignore le répertoire courant // On ignore le répertoire courant
@ -294,7 +396,7 @@ void Read_list_of_files(T_Fileselector *list, byte selected_format)
!isHidden(entry))) !isHidden(entry)))
{ {
// On rajoute le répertoire à la liste // On rajoute le répertoire à la liste
Add_element_to_list(list, entry->d_name, 1); Add_element_to_list(list, entry->d_name, Format_filename(entry->d_name, 19, 1), 1, ICON_NONE);
list->Nb_directories++; list->Nb_directories++;
} }
else if (S_ISREG(Infos_enreg.st_mode) && //Il s'agit d'un fichier else if (S_ISREG(Infos_enreg.st_mode) && //Il s'agit d'un fichier
@ -307,7 +409,7 @@ void Read_list_of_files(T_Fileselector *list, byte selected_format)
if (Check_extension(entry->d_name, ext)) if (Check_extension(entry->d_name, ext))
{ {
// On rajoute le fichier à la liste // On rajoute le fichier à la liste
Add_element_to_list(list, entry->d_name, 0); Add_element_to_list(list, entry->d_name, Format_filename(entry->d_name, 19, 0), 0, ICON_NONE);
list->Nb_files++; list->Nb_files++;
// Stop searching // Stop searching
ext=NULL; ext=NULL;
@ -323,12 +425,35 @@ void Read_list_of_files(T_Fileselector *list, byte selected_format)
} }
#if defined(__MORPHOS__) || defined(__AROS__) || defined (__amigaos4__) || defined(__amigaos__) #if defined(__MORPHOS__) || defined(__AROS__) || defined (__amigaos4__) || defined(__amigaos__)
Add_element_to_list(list, "/",1); // on amiga systems, / means parent. And there is no .. Add_element_to_list(list, "/", Format_filename("/",19,1), 1, ICON_NONE); // on amiga systems, / means parent. And there is no ..
list->Nb_directories ++; list->Nb_directories ++;
#elif defined (__MINT__)
T_Fileselector_item *item=NULL;
// check if ".." exists if not add it
// FreeMinT lists ".." already, but this is not so for TOS
// simply adding it will cause double PARENT_DIR under FreeMiNT
bool bFound= false;
for (item = list->First; (((item != NULL) && (bFound==false))); item = item->Next){
if (item->Type == 1){
if(strncmp(item->Full_name,"..",(sizeof(char)*2))==0) bFound=true;
}
}
if(!bFound){
Add_element_to_list(list, "..",1,Format_filename("/",19,1),ICON_NONE); // add if not present
list->Nb_directories ++;
}
#endif #endif
closedir(current_directory); closedir(current_directory);
#if defined (__MINT__)
#else
free(current_path); free(current_path);
#endif
current_path = NULL; current_path = NULL;
Recount_files(list); Recount_files(list);
@ -375,7 +500,7 @@ void Read_list_of_drives(T_Fileselector *list)
{ {
bstrtostr( dl->dol_Name, tmp, 254 ); bstrtostr( dl->dol_Name, tmp, 254 );
strcat( tmp, ":" ); strcat( tmp, ":" );
Add_element_to_list(list, tmp, 2 ); Add_element_to_list(list, tmp, Format_filename(tmp, 19, 2), 2, ICON_NONE );
list->Nb_directories++; list->Nb_directories++;
} }
UnLockDosList( LDF_VOLUMES | LDF_READ ); UnLockDosList( LDF_VOLUMES | LDF_READ );
@ -387,6 +512,8 @@ void Read_list_of_drives(T_Fileselector *list)
int drive_bits = GetLogicalDrives(); int drive_bits = GetLogicalDrives();
int drive_index; int drive_index;
int bit_index; int bit_index;
byte icon;
// Sous Windows, on a la totale, presque aussi bien que sous DOS: // Sous Windows, on a la totale, presque aussi bien que sous DOS:
drive_index = 0; drive_index = 0;
for (bit_index=0; bit_index<26 && drive_index<23; bit_index++) for (bit_index=0; bit_index<26 && drive_index<23; bit_index++)
@ -395,35 +522,51 @@ void Read_list_of_drives(T_Fileselector *list)
{ {
// On a ce lecteur, il faut maintenant déterminer son type "physique". // On a ce lecteur, il faut maintenant déterminer son type "physique".
// pour profiter des jolies icones de X-man. // pour profiter des jolies icones de X-man.
int drive_type;
char drive_path[]="A:\\"; char drive_path[]="A:\\";
// Cette API Windows est étrange, je dois m'y faire... // Cette API Windows est étrange, je dois m'y faire...
drive_path[0]='A'+bit_index; drive_path[0]='A'+bit_index;
switch (GetDriveType(drive_path)) switch (GetDriveType(drive_path))
{ {
case DRIVE_CDROM: case DRIVE_CDROM:
drive_type=ICON_CDROM; icon=ICON_CDROM;
break; break;
case DRIVE_REMOTE: case DRIVE_REMOTE:
drive_type=ICON_NETWORK; icon=ICON_NETWORK;
break; break;
case DRIVE_REMOVABLE: case DRIVE_REMOVABLE:
drive_type=ICON_FLOPPY_3_5; icon=ICON_FLOPPY_3_5;
break; break;
case DRIVE_FIXED: case DRIVE_FIXED:
drive_type=ICON_HDD; icon=ICON_HDD;
break; break;
default: default:
drive_type=ICON_NETWORK; icon=ICON_NETWORK;
break; break;
} }
drive_name[0]='A'+bit_index; drive_name[0]='A'+bit_index;
Add_element_to_list(list, drive_name,2); Add_element_to_list(list, drive_name, Format_filename(drive_name,18,2), 2, icon);
list->Nb_directories++; list->Nb_directories++;
drive_index++; drive_index++;
} }
} }
} }
#elif defined(__MINT__)
char drive_name[]="A:\\";
unsigned long drive_bits = Drvmap(); //get drive map bitfield
int drive_index;
int bit_index;
drive_index = 0;
for (bit_index=0; bit_index<32; bit_index++)
{
if ( (1 << bit_index) & drive_bits )
{
drive_name[0]='A'+bit_index;
Add_element_to_list(list, drive_name,Format_filename(drive_name,19,2),2,ICON_NONE);
list->Nb_directories++;
drive_index++;
}
}
#else #else
{ {
//Sous les différents unix, on va mettre //Sous les différents unix, on va mettre
@ -440,11 +583,11 @@ void Read_list_of_drives(T_Fileselector *list)
#else #else
char * home_dir = getenv("HOME"); char * home_dir = getenv("HOME");
#endif #endif
Add_element_to_list(list, "/", 2); Add_element_to_list(list, "/", Format_filename("/",19,2), 2, ICON_NONE);
list->Nb_directories++; list->Nb_directories++;
if(home_dir) if(home_dir)
{ {
Add_element_to_list(list, home_dir, 2); Add_element_to_list(list, home_dir, Format_filename(home_dir, 19, 2), 2, ICON_NONE);
list->Nb_directories++; list->Nb_directories++;
} }
@ -454,7 +597,7 @@ void Read_list_of_drives(T_Fileselector *list)
{ {
if(mount_points_list->me_dummy == 0 && strcmp(mount_points_list->me_mountdir,"/") && strcmp(mount_points_list->me_mountdir,"/home")) if(mount_points_list->me_dummy == 0 && strcmp(mount_points_list->me_mountdir,"/") && strcmp(mount_points_list->me_mountdir,"/home"))
{ {
Add_element_to_list(list, mount_points_list->me_mountdir,2); Add_element_to_list(list, mount_points_list->me_mountdir, Format_filename(mount_points_list->me_mountdir, 19, 2), 2, ICON_NONE);
list->Nb_directories++; list->Nb_directories++;
} }
next = mount_points_list -> me_next; next = mount_points_list -> me_next;
@ -473,6 +616,15 @@ void Read_list_of_drives(T_Fileselector *list)
Recount_files(list); Recount_files(list);
} }
// Comparison of file names:
#ifdef WIN32
// case-insensitive
#define FILENAME_COMPARE strcasecmp
#else
// case-sensitive
#define FILENAME_COMPARE strcmp
#endif
// -- Tri de la liste des fichiers et répertoires --------------------------- // -- Tri de la liste des fichiers et répertoires ---------------------------
void Sort_list_of_files(T_Fileselector *list) void Sort_list_of_files(T_Fileselector *list)
@ -514,7 +666,7 @@ void Sort_list_of_files(T_Fileselector *list)
// Si les deux éléments sont de même type et que le nom du suivant // Si les deux éléments sont de même type et que le nom du suivant
// est plus petit que celui du courant -> need_swap // est plus petit que celui du courant -> need_swap
else if ( (current_item->Type==next_item->Type) && else if ( (current_item->Type==next_item->Type) &&
(strcmp(current_item->Full_name,next_item->Full_name)>0) ) (FILENAME_COMPARE(current_item->Full_name,next_item->Full_name)>0) )
need_swap=1; need_swap=1;
@ -640,7 +792,14 @@ void Display_file_list(T_Fileselector *list, short offset_first,short selector_o
} }
// On affiche l'élément // On affiche l'élément
Print_in_window(8,95+index*8,current_item->Short_name,text_color,background_color); if (current_item->Icon != ICON_NONE)
{
// Name preceded by an icon
Print_in_window(16,95+index*8,current_item->Short_name,text_color,background_color);
Window_display_icon_sprite(8,95+index*8,current_item->Icon);
} else
// Name without icon
Print_in_window(8,95+index*8,current_item->Short_name,text_color,background_color);
// On passe à la ligne suivante // On passe à la ligne suivante
selector_offset--; selector_offset--;
@ -889,7 +1048,7 @@ void Prepare_and_display_filelist(short Position, short offset, T_Scroller_butto
{ {
button->Nb_elements=Filelist.Nb_elements; button->Nb_elements=Filelist.Nb_elements;
button->Position=Position; button->Position=Position;
Compute_slider_cursor_height(button); Compute_slider_cursor_length(button);
Window_draw_slider(button); Window_draw_slider(button);
// On efface les anciens noms de fichier: // On efface les anciens noms de fichier:
Window_rectangle(8-1,95-1,144+2,80+2,MC_Black); Window_rectangle(8-1,95-1,144+2,80+2,MC_Black);
@ -984,12 +1143,8 @@ short Find_file_in_fileselector(T_Fileselector *list, const char * fname)
return close_match; return close_match;
} }
void Highlight_file(short index)
void Highlight_file(char * fname)
{ {
short index;
index=Find_file_in_fileselector(&Filelist, fname);
if ((Filelist.Nb_elements<=10) || (index<5)) if ((Filelist.Nb_elements<=10) || (index<5))
{ {
@ -1012,14 +1167,16 @@ void Highlight_file(char * fname)
} }
char * Find_filename_match(T_Fileselector *list, char * fname) short Find_filename_match(T_Fileselector *list, char * fname)
{ {
char * best_name_ptr; short best_match;
T_Fileselector_item * current_item; T_Fileselector_item * current_item;
byte matching_letters=0; short item_number;
byte counter; byte matching_letters=0;
byte counter;
best_name_ptr=NULL; best_match=-1;
item_number=0;
for (current_item=list->First; current_item!=NULL; current_item=current_item->Next) for (current_item=list->First; current_item!=NULL; current_item=current_item->Next)
{ {
@ -1031,12 +1188,96 @@ char * Find_filename_match(T_Fileselector *list, char * fname)
if (counter>matching_letters) if (counter>matching_letters)
{ {
matching_letters=counter; matching_letters=counter;
best_name_ptr=current_item->Full_name; best_match=item_number;
} }
} }
item_number++;
} }
return best_name_ptr; return best_match;
}
// Quicksearch system
char quicksearch_filename[MAX_PATH_CHARACTERS]="";
void Reset_quicksearch(void)
{
quicksearch_filename[0]='\0';
}
short Quicksearch(T_Fileselector *selector)
{
int len;
short most_matching_item;
// Autre => On se place sur le nom de fichier qui correspond
len=strlen(quicksearch_filename);
if (Key_ANSI>= ' ' && Key_ANSI < 255 && len<50)
{
quicksearch_filename[len]=Key_ANSI;
quicksearch_filename[len+1]='\0';
most_matching_item=Find_filename_match(selector, quicksearch_filename);
if ( most_matching_item >= 0 )
{
return most_matching_item;
}
*quicksearch_filename=0;
}
return -1;
}
// Translated from Highlight_file
void Locate_list_item(T_List_button * list, T_Fileselector * selector, short selected_item)
{
// Safety bounds
if (selected_item<0)
selected_item=0;
else if (selected_item>=list->Scroller->Nb_elements)
selected_item=list->Scroller->Nb_elements-1;
if ((list->Scroller->Nb_elements<=list->Scroller->Nb_visibles) || (selected_item<(list->Scroller->Nb_visibles/2)))
{
list->List_start=0;
list->Cursor_position=selected_item;
}
else
{
if (selected_item>=list->Scroller->Nb_elements-(list->Scroller->Nb_visibles/2))
{
list->List_start=list->Scroller->Nb_elements-list->Scroller->Nb_visibles;
list->Cursor_position=selected_item-list->List_start;
}
else
{
list->List_start=selected_item-(list->Scroller->Nb_visibles/2-1);
list->Cursor_position=(list->Scroller->Nb_visibles/2-1);
}
}
}
int Quicksearch_list(T_List_button * list, T_Fileselector * selector)
{
// Try Quicksearch
short selected_item=Quicksearch(selector);
if (selected_item>=0 && selected_item!=list->Cursor_position+list->List_start)
{
Locate_list_item(list, selector, selected_item);
Hide_cursor();
// Mise à jour du scroller
list->Scroller->Position=list->List_start;
Window_draw_slider(list->Scroller);
Window_redraw_list(list);
Display_cursor();
// Store the selected value as attribute2
Window_attribute2=list->List_start + list->Cursor_position;
// Return the control ID of the list.
return list->Number;
}
return 0;
} }
byte Button_Load_or_Save(byte load, T_IO_Context *context) byte Button_Load_or_Save(byte load, T_IO_Context *context)
@ -1048,18 +1289,21 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
T_Dropdown_button * formats_dropdown; T_Dropdown_button * formats_dropdown;
T_Dropdown_button * bookmark_dropdown[4]; T_Dropdown_button * bookmark_dropdown[4];
short temp; short temp;
unsigned int format;
int dummy=0; // Sert à appeler SDL_GetKeyState int dummy=0; // Sert à appeler SDL_GetKeyState
byte save_or_load_image=0; byte save_or_load_image=0;
byte has_clicked_ok=0;// Indique si on a clické sur Load ou Save ou sur byte has_clicked_ok=0;// Indique si on a clické sur Load ou Save ou sur
//un bouton enclenchant Load ou Save juste après. //un bouton enclenchant Load ou Save juste après.
byte initial_back_color; // | fout en l'air (c'te conne). byte initial_back_color; // | fout en l'air (c'te conne).
char previous_directory[MAX_PATH_CHARACTERS]; // Répertoire d'où l'on vient après un CHDIR char previous_directory[MAX_PATH_CHARACTERS]; // Répertoire d'où l'on vient après un CHDIR
char quicksearch_filename[MAX_PATH_CHARACTERS]="";
char save_filename[MAX_PATH_CHARACTERS]; char save_filename[MAX_PATH_CHARACTERS];
char initial_comment[COMMENT_SIZE+1]; char initial_comment[COMMENT_SIZE+1];
char * most_matching_filename;
short window_shortcut; short window_shortcut;
Reset_quicksearch();
// if (Native_filesel(load) != 0); // TODO : handle this
if (context->Type == CONTEXT_MAIN_IMAGE) if (context->Type == CONTEXT_MAIN_IMAGE)
window_shortcut = load?(0x100+BUTTON_LOAD):(0x100+BUTTON_SAVE); window_shortcut = load?(0x100+BUTTON_LOAD):(0x100+BUTTON_SAVE);
else else
@ -1099,7 +1343,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
} }
// Affichage du commentaire // Affichage du commentaire
if (Get_fileformat(Main_format)->Comment) if (Get_fileformat(Main_format)->Comment)
Print_in_window(47,70,context->Comment,MC_Black,MC_Light); Print_in_window(45,70,context->Comment,MC_Black,MC_Light);
} }
Window_set_normal_button(253,180,51,14,"Cancel",0,1,KEY_ESC); // 2 Window_set_normal_button(253,180,51,14,"Cancel",0,1,KEY_ESC); // 2
@ -1124,11 +1368,11 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
Get_fileformat(Main_format)->Label, Get_fileformat(Main_format)->Label,
1,0,1,RIGHT_SIDE|LEFT_SIDE,0); // 6 1,0,1,RIGHT_SIDE|LEFT_SIDE,0); // 6
for (temp=0; temp < NB_KNOWN_FORMATS; temp++) for (format=0; format < Nb_known_formats(); format++)
{ {
if ((load && (File_formats[temp].Identifier <= FORMAT_ALL_FILES || File_formats[temp].Load)) || if ((load && (File_formats[format].Identifier <= FORMAT_ALL_FILES || File_formats[format].Load)) ||
(!load && File_formats[temp].Save)) (!load && File_formats[format].Save))
Window_dropdown_add_item(formats_dropdown,File_formats[temp].Identifier,File_formats[temp].Label); Window_dropdown_add_item(formats_dropdown,File_formats[format].Identifier,File_formats[format].Label);
} }
Print_in_window(70,18,"Format",MC_Dark,MC_Light); Print_in_window(70,18,"Format",MC_Dark,MC_Light);
@ -1161,13 +1405,30 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
// On prend bien soin de passer dans le répertoire courant (le bon qui faut! Oui madame!) // On prend bien soin de passer dans le répertoire courant (le bon qui faut! Oui madame!)
if (load) if (load)
{ {
#if defined(__MINT__)
chdir(Main_current_directory);
static char path[1024]={0};
Dgetpath(path,0);
strcat(path,PATH_SEPARATOR);
strcpy(Main_current_directory,path);
#else
chdir(Main_current_directory); chdir(Main_current_directory);
getcwd(Main_current_directory,256); getcwd(Main_current_directory,256);
#endif
} }
else else
{ {
#if defined(__MINT__)
chdir(context->File_directory); chdir(context->File_directory);
static char path[1024]={0};
Dgetpath(path,0);
strcat(path,PATH_SEPARATOR);
strcpy(Main_current_directory,path);
#else
getcwd(Main_current_directory,256); getcwd(Main_current_directory,256);
#endif
} }
// Affichage des premiers fichiers visibles: // Affichage des premiers fichiers visibles:
@ -1181,7 +1442,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
// On affiche le nouveau nom de fichier // On affiche le nouveau nom de fichier
Print_filename_in_fileselector(); Print_filename_in_fileselector();
Highlight_file(context->File_name); Highlight_file(Find_file_in_fileselector(&Filelist, context->File_name));
Prepare_and_display_filelist(Main_fileselector_position,Main_fileselector_offset,file_scroller); Prepare_and_display_filelist(Main_fileselector_position,Main_fileselector_offset,file_scroller);
} }
@ -1309,7 +1570,8 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
// On vient de changer de nom de fichier, donc on doit s'appreter // On vient de changer de nom de fichier, donc on doit s'appreter
// a rafficher une preview // a rafficher une preview
New_preview_is_needed=1; New_preview_is_needed=1;
*quicksearch_filename=0; Reset_quicksearch();
} }
else else
{ {
@ -1322,7 +1584,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
has_clicked_ok=1; has_clicked_ok=1;
New_preview_is_needed=1; New_preview_is_needed=1;
*quicksearch_filename=0; Reset_quicksearch();
} }
} }
Display_cursor(); Display_cursor();
@ -1340,26 +1602,40 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
Display_file_list(&Filelist, Main_fileselector_position,Main_fileselector_offset); Display_file_list(&Filelist, Main_fileselector_position,Main_fileselector_offset);
Display_cursor(); Display_cursor();
New_preview_is_needed=1; New_preview_is_needed=1;
*quicksearch_filename=0; Reset_quicksearch();
break; break;
case 6 : // Scroller des formats case 6 : // Scroller des formats
Hide_cursor(); // On met à jour le format de browsing du fileselect:
// On met à jour le format de browsing du fileselect: if (Main_format != Window_attribute2) {
Main_format=Window_attribute2; char* savename = (char *)strdup(Selector_filename);
// Comme on change de liste, on se place en début de liste: int nameLength = strlen(savename);
Main_fileselector_position=0; DEBUG(Selector_filename, 42);
Main_fileselector_offset=0; Main_format = Window_attribute2;
// Affichage des premiers fichiers visibles: // Comme on change de liste, on se place en début de liste:
Reload_list_of_files(Main_format,file_scroller); Main_fileselector_position = 0;
Display_cursor(); Main_fileselector_offset = 0;
New_preview_is_needed=1; // Affichage des premiers fichiers visibles:
*quicksearch_filename=0; Hide_cursor();
Reload_list_of_files(Main_format, file_scroller);
New_preview_is_needed = 1;
Reset_quicksearch();
strcpy(Selector_filename, savename);
if (Get_fileformat(Main_format)->Default_extension[0] != '\0' &&
Selector_filename[nameLength - 4] == '.')
{
strcpy(Selector_filename + nameLength - 3,
Get_fileformat(Main_format)->Default_extension);
}
free(savename);
Print_filename_in_fileselector();
Display_cursor();
}
break; break;
case 7 : // Saisie d'un commentaire pour la sauvegarde case 7 : // Saisie d'un commentaire pour la sauvegarde
if ( (!load) && (Get_fileformat(Main_format)->Comment) ) if ( (!load) && (Get_fileformat(Main_format)->Comment) )
{ {
Readline(45,70,context->Comment,32,0); Readline(45, 70, context->Comment, 32, INPUT_TYPE_STRING);
Display_cursor(); Display_cursor();
} }
break; break;
@ -1368,7 +1644,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
// Save the filename // Save the filename
strcpy(save_filename, Selector_filename); strcpy(save_filename, Selector_filename);
if (Readline(82,48,Selector_filename,27,2)) if (Readline(82,48,Selector_filename,27,INPUT_TYPE_FILENAME))
{ {
// On regarde s'il faut rajouter une extension. C'est-à-dire s'il // On regarde s'il faut rajouter une extension. C'est-à-dire s'il
// n'y a pas de '.' dans le nom du fichier. // n'y a pas de '.' dans le nom du fichier.
@ -1382,7 +1658,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
if(!Directory_exists(Selector_filename)) if(!Directory_exists(Selector_filename))
{ {
strcat(Selector_filename, "."); strcat(Selector_filename, ".");
strcat(Selector_filename,Get_fileformat(Main_format)->Default_extension); strcat(Selector_filename, Get_fileformat(Main_format)->Default_extension);
} }
} }
else else
@ -1438,7 +1714,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
Prepare_and_display_filelist(Main_fileselector_position,Main_fileselector_offset,file_scroller); Prepare_and_display_filelist(Main_fileselector_position,Main_fileselector_offset,file_scroller);
Display_cursor(); Display_cursor();
New_preview_is_needed=1; New_preview_is_needed=1;
*quicksearch_filename=0; Reset_quicksearch();
break; break;
default: default:
if (clicked_button>=10 && clicked_button<10+NB_BOOKMARKS) if (clicked_button>=10 && clicked_button<10+NB_BOOKMARKS)
@ -1451,11 +1727,10 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
case -1: // bouton lui-même: aller au répertoire mémorisé case -1: // bouton lui-même: aller au répertoire mémorisé
if (Config.Bookmark_directory[clicked_button-10]) if (Config.Bookmark_directory[clicked_button-10])
{ {
*quicksearch_filename=0;
strcpy(Selector_filename,Config.Bookmark_directory[clicked_button-10]); strcpy(Selector_filename,Config.Bookmark_directory[clicked_button-10]);
Selected_type=1; Selected_type=1;
has_clicked_ok=1; has_clicked_ok=1;
*quicksearch_filename=0; Reset_quicksearch();
} }
break; break;
@ -1490,7 +1765,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
strcpy(bookmark_label, Config.Bookmark_label[clicked_button-10]); strcpy(bookmark_label, Config.Bookmark_label[clicked_button-10]);
if (bookmark_label[7]==ELLIPSIS_CHARACTER) if (bookmark_label[7]==ELLIPSIS_CHARACTER)
bookmark_label[7]='\0'; bookmark_label[7]='\0';
if (Readline_ex(bookmark_dropdown[clicked_button-10]->Pos_X+3+10,bookmark_dropdown[clicked_button-10]->Pos_Y+2,bookmark_label,8,8,0,0)) if (Readline_ex(bookmark_dropdown[clicked_button-10]->Pos_X+3+10,bookmark_dropdown[clicked_button-10]->Pos_Y+2,bookmark_label,8,8,INPUT_TYPE_STRING,0))
strcpy(Config.Bookmark_label[clicked_button-10],bookmark_label); strcpy(Config.Bookmark_label[clicked_button-10],bookmark_label);
Display_bookmark(bookmark_dropdown[clicked_button-10],clicked_button-10); Display_bookmark(bookmark_dropdown[clicked_button-10],clicked_button-10);
Display_cursor(); Display_cursor();
@ -1515,63 +1790,63 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
{ {
case SDLK_UNKNOWN : break; case SDLK_UNKNOWN : break;
case SDLK_DOWN : // Bas case SDLK_DOWN : // Bas
*quicksearch_filename=0; Reset_quicksearch();
Hide_cursor(); Hide_cursor();
Selector_scroll_down(&Main_fileselector_position,&Main_fileselector_offset); Selector_scroll_down(&Main_fileselector_position,&Main_fileselector_offset);
Scroll_fileselector(file_scroller); Scroll_fileselector(file_scroller);
Key=0; Key=0;
break; break;
case SDLK_UP : // Haut case SDLK_UP : // Haut
*quicksearch_filename=0; Reset_quicksearch();
Hide_cursor(); Hide_cursor();
Selector_scroll_up(&Main_fileselector_position,&Main_fileselector_offset); Selector_scroll_up(&Main_fileselector_position,&Main_fileselector_offset);
Scroll_fileselector(file_scroller); Scroll_fileselector(file_scroller);
Key=0; Key=0;
break; break;
case SDLK_PAGEDOWN : // PageDown case SDLK_PAGEDOWN : // PageDown
*quicksearch_filename=0; Reset_quicksearch();
Hide_cursor(); Hide_cursor();
Selector_page_down(&Main_fileselector_position,&Main_fileselector_offset,9); Selector_page_down(&Main_fileselector_position,&Main_fileselector_offset,9);
Scroll_fileselector(file_scroller); Scroll_fileselector(file_scroller);
Key=0; Key=0;
break; break;
case SDLK_PAGEUP : // PageUp case SDLK_PAGEUP : // PageUp
*quicksearch_filename=0; Reset_quicksearch();
Hide_cursor(); Hide_cursor();
Selector_page_up(&Main_fileselector_position,&Main_fileselector_offset,9); Selector_page_up(&Main_fileselector_position,&Main_fileselector_offset,9);
Scroll_fileselector(file_scroller); Scroll_fileselector(file_scroller);
Key=0; Key=0;
break; break;
case SDLK_END : // End case SDLK_END : // End
*quicksearch_filename=0; Reset_quicksearch();
Hide_cursor(); Hide_cursor();
Selector_end(&Main_fileselector_position,&Main_fileselector_offset); Selector_end(&Main_fileselector_position,&Main_fileselector_offset);
Scroll_fileselector(file_scroller); Scroll_fileselector(file_scroller);
Key=0; Key=0;
break; break;
case SDLK_HOME : // Home case SDLK_HOME : // Home
*quicksearch_filename=0; Reset_quicksearch();
Hide_cursor(); Hide_cursor();
Selector_home(&Main_fileselector_position,&Main_fileselector_offset); Selector_home(&Main_fileselector_position,&Main_fileselector_offset);
Scroll_fileselector(file_scroller); Scroll_fileselector(file_scroller);
Key=0; Key=0;
break; break;
case KEY_MOUSEWHEELDOWN : case KEY_MOUSEWHEELDOWN :
*quicksearch_filename=0; Reset_quicksearch();
Hide_cursor(); Hide_cursor();
Selector_page_down(&Main_fileselector_position,&Main_fileselector_offset,3); Selector_page_down(&Main_fileselector_position,&Main_fileselector_offset,3);
Scroll_fileselector(file_scroller); Scroll_fileselector(file_scroller);
Key=0; Key=0;
break; break;
case KEY_MOUSEWHEELUP : case KEY_MOUSEWHEELUP :
*quicksearch_filename=0; Reset_quicksearch();
Hide_cursor(); Hide_cursor();
Selector_page_up(&Main_fileselector_position,&Main_fileselector_offset,3); Selector_page_up(&Main_fileselector_position,&Main_fileselector_offset,3);
Scroll_fileselector(file_scroller); Scroll_fileselector(file_scroller);
Key=0; Key=0;
break; break;
case SDLK_BACKSPACE : // Backspace case SDLK_BACKSPACE : // Backspace
*quicksearch_filename=0; Reset_quicksearch();
// Si le choix ".." est bien en tête des propositions... // Si le choix ".." est bien en tête des propositions...
if (!strcmp(Filelist.First->Full_name,PARENT_DIR)) if (!strcmp(Filelist.First->Full_name,PARENT_DIR))
{ {
@ -1585,6 +1860,8 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
default: default:
if (clicked_button<=0) if (clicked_button<=0)
{ {
short selected_item;
if (Is_shortcut(Key,0x100+BUTTON_HELP)) if (Is_shortcut(Key,0x100+BUTTON_HELP))
{ {
Window_help(load?BUTTON_LOAD:BUTTON_SAVE, NULL); Window_help(load?BUTTON_LOAD:BUTTON_SAVE, NULL);
@ -1595,30 +1872,22 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
clicked_button=2; clicked_button=2;
break; break;
} }
// Autre => On se place sur le nom de fichier qui correspond
temp=strlen(quicksearch_filename); selected_item=Quicksearch(&Filelist);
if (Key_ANSI>= ' ' && Key_ANSI < 255 && temp<50) if (selected_item>=0)
{ {
quicksearch_filename[temp]=Key_ANSI;
quicksearch_filename[temp+1]='\0';
most_matching_filename=Find_filename_match(&Filelist, quicksearch_filename);
if ( (most_matching_filename) )
{
temp=Main_fileselector_position+Main_fileselector_offset; temp=Main_fileselector_position+Main_fileselector_offset;
Hide_cursor(); Hide_cursor();
Highlight_file(most_matching_filename); Highlight_file(selected_item);
Prepare_and_display_filelist(Main_fileselector_position,Main_fileselector_offset,file_scroller); Prepare_and_display_filelist(Main_fileselector_position,Main_fileselector_offset,file_scroller);
Display_cursor(); Display_cursor();
if (temp!=Main_fileselector_position+Main_fileselector_offset) if (temp!=Main_fileselector_position+Main_fileselector_offset)
New_preview_is_needed=1; New_preview_is_needed=1;
}
else
*quicksearch_filename=0;
Key=0;
} }
// Key=0; ?
} }
else else
*quicksearch_filename=0; Reset_quicksearch();
} }
if (has_clicked_ok) if (has_clicked_ok)
@ -1643,13 +1912,20 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
// On doit rentrer dans le répertoire: // On doit rentrer dans le répertoire:
if (!chdir(Selector_filename)) if (!chdir(Selector_filename))
{ {
#if defined (__MINT__)
static char path[1024]={0};
char currentDrive='A';
currentDrive=currentDrive+Dgetdrv();
Dgetpath(path,0);
sprintf(Main_current_directory,"%c:\%s",currentDrive,path);
#else
getcwd(Main_current_directory,256); getcwd(Main_current_directory,256);
#endif
// On lit le nouveau répertoire // On lit le nouveau répertoire
Read_list_of_files(&Filelist, Main_format); Read_list_of_files(&Filelist, Main_format);
Sort_list_of_files(&Filelist); Sort_list_of_files(&Filelist);
// On place la barre de sélection sur le répertoire d'où l'on vient // On place la barre de sélection sur le répertoire d'où l'on vient
Highlight_file(previous_directory); Highlight_file(Find_file_in_fileselector(&Filelist, previous_directory));
} }
else else
Error(0); Error(0);
@ -1659,7 +1935,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
New_preview_is_needed=1; New_preview_is_needed=1;
// On est dans un nouveau répertoire, donc on remet le quicksearch à 0 // On est dans un nouveau répertoire, donc on remet le quicksearch à 0
*quicksearch_filename=0; Reset_quicksearch();
} }
else // Sinon on essaye de charger ou sauver le fichier else // Sinon on essaye de charger ou sauver le fichier
{ {
@ -1681,7 +1957,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
// On efface le commentaire précédent // On efface le commentaire précédent
Window_rectangle(45,70,32*8,8,MC_Light); Window_rectangle(45,70,32*8,8,MC_Light);
// On nettoie la zone où va s'afficher la preview: // On nettoie la zone où va s'afficher la preview:
Window_rectangle(183,95,120,80,MC_Light); Window_rectangle(183,95,PREVIEW_WIDTH,PREVIEW_HEIGHT,MC_Light);
// On efface les dimensions de l'image // On efface les dimensions de l'image
Window_rectangle(143,59,72,8,MC_Light); Window_rectangle(143,59,72,8,MC_Light);
// On efface la taille du fichier // On efface la taille du fichier
@ -1697,7 +1973,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
// Un update pour couvrir les 4 zones: 3 libellés plus le commentaire // Un update pour couvrir les 4 zones: 3 libellés plus le commentaire
Update_window_area(45,48,256,30); Update_window_area(45,48,256,30);
// Zone de preview // Zone de preview
Update_window_area(183,95,120,80); Update_window_area(183,95,PREVIEW_WIDTH,PREVIEW_HEIGHT);
} }
New_preview_is_needed=0; New_preview_is_needed=0;

View File

@ -31,12 +31,12 @@
byte Button_Load_or_Save(byte load, T_IO_Context *context); byte Button_Load_or_Save(byte load, T_IO_Context *context);
void Add_element_to_list(T_Fileselector *list, const char * fname, int type); void Add_element_to_list(T_Fileselector *list, const char * full_name, const char *short_name, int type, byte icon);
/// ///
/// Formats a display name for a file, directory, or similar name (drive, volume). /// Formats a display name for a file, directory, or similar name (drive, volume).
/// The returned value is a pointer to a single static buffer of 19 characters /// The returned value is a pointer to a single static buffer of maximum 40 characters
/// including the '\\0'. /// including the '\\0'.
char * Format_filename(const char * fname, int type); char * Format_filename(const char * fname, word max_length, int type);
void Free_fileselector_list(T_Fileselector *list); void Free_fileselector_list(T_Fileselector *list);
@ -48,4 +48,10 @@ T_Fileselector_item * Get_item_by_index(T_Fileselector *list, short index);
short Find_file_in_fileselector(T_Fileselector *list, const char * fname); short Find_file_in_fileselector(T_Fileselector *list, const char * fname);
void Locate_list_item(T_List_button * list, T_Fileselector * selector, short selected_item);
int Quicksearch_list(T_List_button * list, T_Fileselector * selector);
void Reset_quicksearch(void);
#endif #endif

View File

@ -73,6 +73,12 @@ GFX2_GLOBAL byte MC_Light; ///< Index of color to use as "light grey" in the GUI
GFX2_GLOBAL byte MC_White; ///< Index of color to use as "white" in the GUI menus. GFX2_GLOBAL byte MC_White; ///< Index of color to use as "white" in the GUI menus.
GFX2_GLOBAL byte MC_Trans; ///< Index of color to use as "transparent" while loading the GUI file. GFX2_GLOBAL byte MC_Trans; ///< Index of color to use as "transparent" while loading the GUI file.
GFX2_GLOBAL byte MC_OnBlack; ///< Index of color immediately lighter than "black" in the GUI menus.
GFX2_GLOBAL byte MC_Window; ///< Index of color to use as window background in the GUI menus.
GFX2_GLOBAL byte MC_Lighter; ///< Index of color lighter than window in the GUI menus.
GFX2_GLOBAL byte MC_Darker; ///< Index of color darker than window in the GUI menus.
// Input state // Input state
GFX2_GLOBAL word Mouse_X; ///< Current mouse cursor position. GFX2_GLOBAL word Mouse_X; ///< Current mouse cursor position.
GFX2_GLOBAL word Mouse_Y; ///< Current mouse cursor position. GFX2_GLOBAL word Mouse_Y; ///< Current mouse cursor position.
@ -294,10 +300,6 @@ GFX2_GLOBAL short Main_image_height;
GFX2_GLOBAL short Main_offset_X; GFX2_GLOBAL short Main_offset_X;
/// Y position (in image space) of the pixel to display in the top left corner of screen. /// Y position (in image space) of the pixel to display in the top left corner of screen.
GFX2_GLOBAL short Main_offset_Y; GFX2_GLOBAL short Main_offset_Y;
/// Backup of ::Main_offset_X, used to store it while the magnifier is open.
GFX2_GLOBAL short Old_main_offset_X;
/// Backup of ::Main_offset_Y, used to store it while the magnifier is open.
GFX2_GLOBAL short Old_main_offset_Y;
/// Name of the directory that holds the image currently edited. /// Name of the directory that holds the image currently edited.
GFX2_GLOBAL char Main_file_directory[1024]; GFX2_GLOBAL char Main_file_directory[1024];
/// Filename (without directory) of the image currently edited. /// Filename (without directory) of the image currently edited.
@ -364,10 +366,6 @@ GFX2_GLOBAL short Spare_image_height;
GFX2_GLOBAL short Spare_offset_X; GFX2_GLOBAL short Spare_offset_X;
/// Y position (in image space) of the pixel to display in the top left corner of screen. /// Y position (in image space) of the pixel to display in the top left corner of screen.
GFX2_GLOBAL short Spare_offset_Y; GFX2_GLOBAL short Spare_offset_Y;
/// Backup of ::Main_offset_X, used to store it while the magnifier is open.
GFX2_GLOBAL short Old_spare_offset_X;
/// Backup of ::Main_offset_Y, used to store it while the magnifier is open.
GFX2_GLOBAL short Old_spare_offset_Y;
/// Name of the directory that holds the image currently edited as spare page. /// Name of the directory that holds the image currently edited as spare page.
GFX2_GLOBAL char Spare_file_directory[MAX_PATH_CHARACTERS]; GFX2_GLOBAL char Spare_file_directory[MAX_PATH_CHARACTERS];
/// Filename (without directory) of the image currently edited as spare page. /// Filename (without directory) of the image currently edited as spare page.
@ -432,8 +430,16 @@ GFX2_GLOBAL T_List_of_pages * Spare_backups;
// -- Brush data // -- Brush data
/// Pixel data of the current brush. /// Pixel data of the current brush (remapped).
GFX2_GLOBAL byte * Brush; GFX2_GLOBAL byte * Brush;
/// Pixel data of the current brush (before remap).
GFX2_GLOBAL byte * Brush_original_pixels;
/// Palette of the brush, from when it was grabbed.
GFX2_GLOBAL T_Palette Brush_original_palette;
/// Back_color used when the brush was grabbed
GFX2_GLOBAL byte Brush_original_back_color;
/// Color mapping from ::Brush_original_pixels to ::Brush
GFX2_GLOBAL byte Brush_colormap[256];
/// X coordinate of the brush's "hot spot". It is < ::Brush_width /// X coordinate of the brush's "hot spot". It is < ::Brush_width
GFX2_GLOBAL word Brush_offset_X; GFX2_GLOBAL word Brush_offset_X;
/// Y coordinate of the brush's "hot spot". It is < ::Brush_height /// Y coordinate of the brush's "hot spot". It is < ::Brush_height
@ -492,9 +498,9 @@ GFX2_GLOBAL word Menu_palette_cell_width;
GFX2_GLOBAL T_Menu_Bar Menu_bars[MENUBAR_COUNT] GFX2_GLOBAL T_Menu_Bar Menu_bars[MENUBAR_COUNT]
#ifdef GLOBAL_VARIABLES #ifdef GLOBAL_VARIABLES
= =
{{MENU_WIDTH, 9, 1, 45, NULL, 20, BUTTON_HIDE }, // Status {{MENU_WIDTH, 9, 1, 45, {NULL,NULL,NULL}, 20, BUTTON_HIDE }, // Status
{MENU_WIDTH, 10, 1, 35, NULL, 144, BUTTON_LAYER_SELECT }, // Layers {MENU_WIDTH, 10, 1, 35, {NULL,NULL,NULL}, 144, BUTTON_LAYER_SELECT }, // Layers
{MENU_WIDTH, 35, 1, 0, NULL, 254, BUTTON_CHOOSE_COL }} // Main {MENU_WIDTH, 35, 1, 0, {NULL,NULL,NULL}, 254, BUTTON_CHOOSE_COL }} // Main
#endif #endif
; ;
@ -510,71 +516,59 @@ GFX2_GLOBAL word Menu_Y_before_window;
/// Backup of ::Paintbrush_hidden, used to store it while a window is open. /// Backup of ::Paintbrush_hidden, used to store it while a window is open.
GFX2_GLOBAL byte Paintbrush_hidden_before_window; GFX2_GLOBAL byte Paintbrush_hidden_before_window;
GFX2_GLOBAL word Window_stack_pos_X[8]; /// The global stack of editor screens.
GFX2_GLOBAL T_Window Window_stack[8];
/// Position of the left border of the topmost window (in screen coordinates) /// Position of the left border of the topmost window (in screen coordinates)
#define Window_pos_X Window_stack_pos_X[Windows_open-1] #define Window_pos_X Window_stack[Windows_open-1].Pos_X
GFX2_GLOBAL word Window_stack_pos_Y[8];
/// Position of the top border of the topmost window (in screen coordinates) /// Position of the top border of the topmost window (in screen coordinates)
#define Window_pos_Y Window_stack_pos_Y[Windows_open-1] #define Window_pos_Y Window_stack[Windows_open-1].Pos_Y
GFX2_GLOBAL word Window_stack_width[8];
/// ///
/// Width of the topmost window, in "window pixels" /// Width of the topmost window, in "window pixels"
/// (multiply by ::Menu_factor_X to get screen pixels) /// (multiply by ::Menu_factor_X to get screen pixels)
#define Window_width Window_stack_width[Windows_open-1] #define Window_width Window_stack[Windows_open-1].Width
GFX2_GLOBAL word Window_stack_height[8];
/// ///
/// Height of the topmost window, in "window pixels" /// Height of the topmost window, in "window pixels"
/// (multiply by ::Menu_factor_Y to get screen pixels) /// (multiply by ::Menu_factor_Y to get screen pixels)
#define Window_height Window_stack_height[Windows_open-1] #define Window_height Window_stack[Windows_open-1].Height
GFX2_GLOBAL word Window_stack_nb_buttons[8];
/// Total number of buttons/controls in the topmost window. /// Total number of buttons/controls in the topmost window.
#define Window_nb_buttons Window_stack_nb_buttons[Windows_open-1] #define Window_nb_buttons Window_stack[Windows_open-1].Nb_buttons
GFX2_GLOBAL T_Normal_button * Window_stack_normal_button_list[8];
/// List of normal buttons in the topmost window. /// List of normal buttons in the topmost window.
#define Window_normal_button_list Window_stack_normal_button_list[Windows_open-1] #define Window_normal_button_list Window_stack[Windows_open-1].Normal_button_list
GFX2_GLOBAL T_Palette_button * Window_stack_palette_button_list[8];
/// List of "palette" buttons in the topmost window. /// List of "palette" buttons in the topmost window.
#define Window_palette_button_list Window_stack_palette_button_list[Windows_open-1] #define Window_palette_button_list Window_stack[Windows_open-1].Palette_button_list
GFX2_GLOBAL T_Scroller_button * Window_stack_scroller_button_list[8];
/// List of sliders (scrollers) in the topmost window. /// List of sliders (scrollers) in the topmost window.
#define Window_scroller_button_list Window_stack_scroller_button_list[Windows_open-1] #define Window_scroller_button_list Window_stack[Windows_open-1].Scroller_button_list
GFX2_GLOBAL T_Special_button * Window_stack_special_button_list[8];
/// List of special buttons in the topmost window. /// List of special buttons in the topmost window.
#define Window_special_button_list Window_stack_special_button_list[Windows_open-1] #define Window_special_button_list Window_stack[Windows_open-1].Special_button_list
GFX2_GLOBAL T_Dropdown_button * Window_stack_dropdown_button_list[8];
/// List of dropdown buttons in the topmost window. /// List of dropdown buttons in the topmost window.
#define Window_dropdown_button_list Window_stack_dropdown_button_list[Windows_open-1] #define Window_dropdown_button_list Window_stack[Windows_open-1].Dropdown_button_list
GFX2_GLOBAL T_List_button * Window_stack_list_button_list[8];
/// List of list buttons in the topmost window. /// List of list buttons in the topmost window.
#define Window_list_button_list Window_stack_list_button_list[Windows_open-1] #define Window_list_button_list Window_stack[Windows_open-1].List_button_list
GFX2_GLOBAL int Window_stack_attribute1[8];
/// ///
/// The function ::Window_clicked_button() set this to ::LEFT_SIDE or ::RIGHT_SIDE /// The function ::Window_clicked_button() set this to ::LEFT_SIDE or ::RIGHT_SIDE
/// after a button is activated through left or right mouse click. /// after a button is activated through left or right mouse click.
#define Window_attribute1 Window_stack_attribute1[Windows_open-1] #define Window_attribute1 Window_stack[Windows_open-1].Attribute1
GFX2_GLOBAL int Window_stack_attribute2[8];
/// ///
/// The function ::Window_clicked_button() set this to return extra information: /// The function ::Window_clicked_button() set this to return extra information:
/// - When a scroller was clicked: the scroller position (0-n) /// - When a scroller was clicked: the scroller position (0-n)
/// - When a palette was clicked: the color index (0-255) /// - When a palette was clicked: the color index (0-255)
/// - When a dropdown was used: the selected item's number T_Dropdown_choice::Number /// - When a dropdown was used: the selected item's number T_Dropdown_choice::Number
#define Window_attribute2 Window_stack_attribute2[Windows_open-1] #define Window_attribute2 Window_stack[Windows_open-1].Attribute2
#define Window_draggable Window_stack[Windows_open-1].Draggable
/// Definition of the menu (toolbox) /// Definition of the menu (toolbox)
@ -587,6 +581,7 @@ GFX2_GLOBAL struct
word Height; ///< Button's active heigth word Height; ///< Button's active heigth
byte Pressed; ///< Button is currently pressed byte Pressed; ///< Button is currently pressed
byte Shape; ///< Shape, listed in enum ::BUTTON_SHAPES byte Shape; ///< Shape, listed in enum ::BUTTON_SHAPES
char Icon; ///< Which icon to display: Either the one from the toolbar (-1) or one of ::MENU_SPRITE
// Triggers on mouse/keyboard // Triggers on mouse/keyboard
Func_action Left_action; ///< Action triggered by a left mouseclick on the button Func_action Left_action; ///< Action triggered by a left mouseclick on the button
@ -765,6 +760,8 @@ GFX2_GLOBAL long Gradient_bounds_range;
GFX2_GLOBAL long Gradient_total_range; GFX2_GLOBAL long Gradient_total_range;
/// Amount of randomness to use in gradient (1-256+) /// Amount of randomness to use in gradient (1-256+)
GFX2_GLOBAL long Gradient_random_factor; GFX2_GLOBAL long Gradient_random_factor;
/// Gradient speed of cycling (0-64)
GFX2_GLOBAL byte Gradient_speed;
/// Pointer to a gradient function, depending on the selected method. /// Pointer to a gradient function, depending on the selected method.
GFX2_GLOBAL Func_gradient Gradient_function; GFX2_GLOBAL Func_gradient Gradient_function;
/// ///
@ -772,10 +769,10 @@ GFX2_GLOBAL Func_gradient Gradient_function;
/// either ::Pixel (if the gradient must be drawn on menus only) /// either ::Pixel (if the gradient must be drawn on menus only)
/// or ::Display_pixel (if the gradient must be drawn on the image) /// or ::Display_pixel (if the gradient must be drawn on the image)
GFX2_GLOBAL Func_pixel Gradient_pixel; GFX2_GLOBAL Func_pixel Gradient_pixel;
/// Settings for all gradients
GFX2_GLOBAL T_Gradient_array Gradient_array[16];
/// Index in ::Gradient_array of the currently selected gradient. /// Index in ::Gradient_array of the currently selected gradient.
GFX2_GLOBAL byte Current_gradient; GFX2_GLOBAL byte Current_gradient;
/// Boolean, true when the color cycling is active.
GFX2_GLOBAL byte Cycling_mode;
// -- Airbrush data // -- Airbrush data
@ -823,6 +820,9 @@ GFX2_GLOBAL byte * Menu_font;
/// Pointer to the current active skin. /// Pointer to the current active skin.
GFX2_GLOBAL T_Gui_skin * Gfx; GFX2_GLOBAL T_Gui_skin * Gfx;
/// Pointer to the current active skin.
GFX2_GLOBAL T_Paintbrush Paintbrush[NB_PAINTBRUSH_SPRITES];
// -- Help data // -- Help data
/// Index of the ::Help_section shown by the Help screen. /// Index of the ::Help_section shown by the Help screen.
@ -894,6 +894,7 @@ GFX2_GLOBAL T_Brush_template Brush_container[BRUSH_CONTAINER_COLUMNS*BRUSH_CONTA
CURSOR_SHAPE_XOR_TARGET , // Stretch brush CURSOR_SHAPE_XOR_TARGET , // Stretch brush
CURSOR_SHAPE_TARGET , // Distort brush CURSOR_SHAPE_TARGET , // Distort brush
CURSOR_SHAPE_XOR_TARGET , // Gradient-filled rectangle CURSOR_SHAPE_XOR_TARGET , // Gradient-filled rectangle
CURSOR_SHAPE_COLORPICKER , // Colorpick on right mouse button
}; };
#else #else
/// ::Cursor_shape to use for each operation. /// ::Cursor_shape to use for each operation.
@ -950,34 +951,83 @@ GFX2_GLOBAL SDL_Joystick* Joystick;
/// It was chosen to not conflict with any SDL key number. /// It was chosen to not conflict with any SDL key number.
#define KEY_JOYBUTTON (SDLK_LAST+4) #define KEY_JOYBUTTON (SDLK_LAST+4)
/// Button definitions for the gp2x /// The joystick axis are {X,Y} - on all platforms so far.
#define GP2X_BUTTON_UP (0) /// If there is ever a platform where they are reversed, put
#define GP2X_BUTTON_DOWN (4) /// these lines in each platform "case" below.
#define GP2X_BUTTON_LEFT (2) #define JOYSTICK_AXIS_X (0)
#define GP2X_BUTTON_RIGHT (6) #define JOYSTICK_AXIS_Y (1)
#define GP2X_BUTTON_UPLEFT (1)
#define GP2X_BUTTON_UPRIGHT (7)
#define GP2X_BUTTON_DOWNLEFT (3)
#define GP2X_BUTTON_DOWNRIGHT (5)
#define GP2X_BUTTON_CLICK (18)
#define GP2X_BUTTON_A (12)
#define GP2X_BUTTON_B (13)
#define GP2X_BUTTON_Y (14)
#define GP2X_BUTTON_X (15)
#define GP2X_BUTTON_L (10)
#define GP2X_BUTTON_R (11)
#define GP2X_BUTTON_START (8)
#define GP2X_BUTTON_SELECT (9)
#define GP2X_BUTTON_VOLUP (16)
#define GP2X_BUTTON_VOLDOWN (17)
#ifdef __gp2x__ #ifdef __GP2X__
#define KEY_ESC (KEY_JOYBUTTON+GP2X_BUTTON_X)
#define JOYSTICK_THRESHOLD (4096)
/// Button definitions for the gp2x
#define JOY_BUTTON_UP (0)
#define JOY_BUTTON_DOWN (4)
#define JOY_BUTTON_LEFT (2)
#define JOY_BUTTON_RIGHT (6)
#define JOY_BUTTON_UPLEFT (1)
#define JOY_BUTTON_UPRIGHT (7)
#define JOY_BUTTON_DOWNLEFT (3)
#define JOY_BUTTON_DOWNRIGHT (5)
#define JOY_BUTTON_CLICK (18)
#define JOY_BUTTON_A (12)
#define JOY_BUTTON_B (13)
#define JOY_BUTTON_Y (14)
#define JOY_BUTTON_X (15)
#define JOY_BUTTON_L (10)
#define JOY_BUTTON_R (11)
#define JOY_BUTTON_START (8)
#define JOY_BUTTON_SELECT (9)
#define JOY_BUTTON_VOLUP (16)
#define JOY_BUTTON_VOLDOWN (17)
#define KEY_ESC (KEY_JOYBUTTON+JOY_BUTTON_X)
#elif defined(__WIZ__)
/// Button definitions for the Wiz
#define JOY_BUTTON_UP (0)
#define JOY_BUTTON_DOWN (4)
#define JOY_BUTTON_LEFT (2)
#define JOY_BUTTON_RIGHT (6)
#define JOY_BUTTON_UPLEFT (1)
#define JOY_BUTTON_UPRIGHT (7)
#define JOY_BUTTON_DOWNLEFT (3)
#define JOY_BUTTON_DOWNRIGHT (5)
#define JOY_BUTTON_L (10)
#define JOY_BUTTON_R (11)
#define JOY_BUTTON_A (12)
#define JOY_BUTTON_B (13)
#define JOY_BUTTON_X (14)
#define JOY_BUTTON_Y (15)
#define JOY_BUTTON_MENU (8)
#define JOY_BUTTON_SELECT (9)
#define JOY_BUTTON_VOLUP (16)
#define JOY_BUTTON_VOLDOWN (17)
#define KEY_ESC (KEY_JOYBUTTON+JOY_BUTTON_X)
#elif defined (__CAANOO__)
#define JOYSTICK_THRESHOLD (4096)
/// Button definitions for the Caanoo
#define JOY_BUTTON_A (0)
#define JOY_BUTTON_X (1)
#define JOY_BUTTON_B (2)
#define JOY_BUTTON_Y (3)
#define JOY_BUTTON_L (4)
#define JOY_BUTTON_R (5)
#define JOY_BUTTON_HOME (6)
#define JOY_BUTTON_HOLD (7)
#define JOY_BUTTON_I (8)
#define JOY_BUTTON_II (9)
#define JOY_BUTTON_JOY (10)
#define KEY_ESC (KEY_JOYBUTTON+JOY_BUTTON_HOME)
#else #else
/// ///
/// This is the key identifier for ESC. When hard-coding keyboard shortcuts /// This is the key identifier for ESC. When hard-coding keyboard shortcuts
/// for buttons, etc. we use this instead of SDLK_ESCAPE, /// for buttons, etc. we use this instead of SDLK_ESCAPE,
/// so the GP2X port can get a joybutton equivalent of it. /// so the console ports can get a joybutton equivalent of it.
#define KEY_ESC SDLK_ESCAPE #define KEY_ESC SDLK_ESCAPE
#endif #endif

View File

@ -48,12 +48,13 @@
#include "pxquad.h" #include "pxquad.h"
#include "windows.h" #include "windows.h"
#include "input.h" #include "input.h"
#include "brush.h"
#ifdef __VBCC__ #ifdef __VBCC__
#define __attribute__(x) #define __attribute__(x)
#endif #endif
#if defined(__VBCC__)||defined(__GP2X__) #if defined(__VBCC__) || defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__)
#define M_PI 3.141592653589793238462643 #define M_PI 3.141592653589793238462643
#endif #endif
@ -522,6 +523,8 @@ try_again:
Menu_factor_Y=1; Menu_factor_Y=1;
break; break;
default: // Stay below some reasonable size default: // Stay below some reasonable size
if (factor>Max(Pixel_width,Pixel_height))
factor/=Max(Pixel_width,Pixel_height);
Menu_factor_X=Min(factor,abs(Config.Ratio)); Menu_factor_X=Min(factor,abs(Config.Ratio));
Menu_factor_Y=Min(factor,abs(Config.Ratio)); Menu_factor_Y=Min(factor,abs(Config.Ratio));
} }
@ -617,7 +620,8 @@ void Resize_image(word chosen_width,word chosen_height)
// |B| | C = Nouvelle image // |B| | C = Nouvelle image
// +-+-+ // +-+-+
if (Backup_with_new_dimensions(1,Main_backups->Pages->Nb_layers,chosen_width,chosen_height)) Upload_infos_page_main(Main_backups->Pages);
if (Backup_with_new_dimensions(chosen_width,chosen_height))
{ {
// La nouvelle page a pu être allouée, elle est pour l'instant pleine de // La nouvelle page a pu être allouée, elle est pour l'instant pleine de
// 0s. Elle fait Main_image_width de large. // 0s. Elle fait Main_image_width de large.
@ -672,13 +676,16 @@ void Remap_spare(void)
// ne seront pas utilisées par Remap_general_lowlevel. // ne seront pas utilisées par Remap_general_lowlevel.
for (color=0;color<=255;color++) for (color=0;color<=255;color++)
if (used[color]) if (used[color])
used[color]=Best_color(Spare_palette[color].R,Spare_palette[color].G,Spare_palette[color].B); used[color]=Best_color_perceptual(Spare_palette[color].R,Spare_palette[color].G,Spare_palette[color].B);
// Maintenant qu'on a une super table de conversion qui n'a que le nom // Maintenant qu'on a une super table de conversion qui n'a que le nom
// qui craint un peu, on peut faire l'échange dans la brosse de toutes les // qui craint un peu, on peut faire l'échange dans la brosse de toutes les
// teintes. // teintes.
for (layer=0; layer<Spare_backups->Pages->Nb_layers; layer++) for (layer=0; layer<Spare_backups->Pages->Nb_layers; layer++)
Remap_general_lowlevel(used,Spare_backups->Pages->Image[layer],Spare_image_width,Spare_image_height,Spare_image_width); Remap_general_lowlevel(used,Spare_backups->Pages->Image[layer],Spare_backups->Pages->Image[layer],Spare_image_width,Spare_image_height,Spare_image_width);
// Change transparent color index
Spare_backups->Pages->Transparent_color=used[Spare_backups->Pages->Transparent_color];
} }
@ -687,43 +694,89 @@ void Get_colors_from_brush(void)
{ {
short x_pos; // Variable de balayage de la brosse short x_pos; // Variable de balayage de la brosse
short y_pos; // Variable de balayage de la brosse short y_pos; // Variable de balayage de la brosse
byte used[256]; // Tableau de booléens "La couleur est utilisée" byte brush_used[256]; // Tableau de booléens "La couleur est utilisée"
dword usage[256];
int color; int color;
int image_color;
if (Confirmation_box("Modify current palette ?")) //if (Confirmation_box("Modify current palette ?"))
// Backup with unchanged layers, only palette is modified
Backup_layers(0);
// Init array of new colors
for (color=0;color<=255;color++)
brush_used[color]=0;
// Tag used colors
for (y_pos=0;y_pos<Brush_height;y_pos++)
for (x_pos=0;x_pos<Brush_width;x_pos++)
brush_used[*(Brush_original_pixels + y_pos * Brush_width + x_pos)]=1;
// Check used colors in picture (to know which palette entries are free)
Count_used_colors(usage);
// First pass : omit colors that are already in palette
for (color=0; color<256; color++)
{ {
// Backup with unchanged layers, only palette is modified // For each color used in brush (to add in palette)
Backup_layers(0); if (brush_used[color])
{
// On commence par initialiser le tableau de booléen à faux // Try locate it in current palette
for (color=0;color<=255;color++) for (image_color=0; image_color<256; image_color++)
used[color]=0;
// On calcule la table d'utilisation des couleurs
for (y_pos=0;y_pos<Brush_height;y_pos++)
for (x_pos=0;x_pos<Brush_width;x_pos++)
used[Read_pixel_from_brush(x_pos,y_pos)]=1;
// On recopie dans la palette principale les teintes des couleurs utilisées
// dans la palette du brouillon
for (color=0;color<=255;color++)
if (used[color])
{ {
Main_palette[color].R=Spare_palette[color].R; if (Brush_original_palette[color].R==Main_palette[image_color].R
Main_palette[color].G=Spare_palette[color].G; && Brush_original_palette[color].G==Main_palette[image_color].G
Main_palette[color].B=Spare_palette[color].B; && Brush_original_palette[color].B==Main_palette[image_color].B)
{
// Color already in main palette:
// Tag as used, so that no new color will overwrite it
usage[image_color]=1;
// Tag as non-new, to avoid it in pass 2
brush_used[color]=0;
break;
}
} }
}
Set_palette(Main_palette);
Compute_optimal_menu_colors(Main_palette);
Hide_cursor();
Display_all_screen();
Display_menu();
Display_cursor();
End_of_modification();
Main_image_is_modified=1;
} }
// Second pass : For each color to add, find an empty slot in
// main palette to add it
image_color=0;
for (color=0; color<256 && image_color<256; color++)
{
// For each color used in brush
if (brush_used[color])
{
for (; image_color<256; image_color++)
{
if (!usage[image_color])
{
// Copy from color to image_color
Main_palette[image_color].R=Brush_original_palette[color].R;
Main_palette[image_color].G=Brush_original_palette[color].G;
Main_palette[image_color].B=Brush_original_palette[color].B;
image_color++;
break;
}
}
}
}
Remap_brush();
Set_palette(Main_palette);
Compute_optimal_menu_colors(Main_palette);
Hide_cursor();
Display_all_screen();
Display_menu();
Display_cursor();
End_of_modification();
Main_image_is_modified=1;
} }
@ -1082,6 +1135,7 @@ void Fill_general(byte fill_color)
if (! (Permanent_draw_count&7)) if (! (Permanent_draw_count&7))
{ {
Uint32 now = SDL_GetTicks(); Uint32 now = SDL_GetTicks();
SDL_PumpEvents();
if (now>= Permanent_draw_next_refresh) if (now>= Permanent_draw_next_refresh)
{ {
Permanent_draw_next_refresh = now+100; Permanent_draw_next_refresh = now+100;

View File

@ -2,6 +2,7 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Peter Gordon Copyright 2008 Peter Gordon
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet Copyright 2008 Franck Charlet
@ -31,6 +32,10 @@
#include <sys/mount.h> #include <sys/mount.h>
#elif defined (__linux__) #elif defined (__linux__)
#include <sys/vfs.h> #include <sys/vfs.h>
#elif defined (__MINT__)
#include <mint/sysbind.h>
#include <mint/osbind.h>
#include <mint/ostruct.h>
#endif #endif
#include "const.h" #include "const.h"
@ -92,7 +97,7 @@ void Redefine_control(word *shortcut, int x_pos, int y_pos)
Display_cursor(); Display_cursor();
while (1) while (1)
{ {
while(!Get_input())SDL_Delay(20); Get_input(20);
if (Key==KEY_ESC) if (Key==KEY_ESC)
return; return;
if (Key!=0) if (Key!=0)
@ -231,22 +236,102 @@ void Window_set_shortcut(int action_id)
Display_cursor(); Display_cursor();
} }
// -- Menu d'aide ----------------------------------------------------------- ///
/// Print a line with the 'help' (6x8) font.
void Display_help(void) short Print_help(short x_pos, short y_pos, const char *line, char line_type, short link_position, short link_size)
{ {
short width; // Largeur physique d'une ligne de texte
short x; // Indices d'affichage d'un caractère short x; // Indices d'affichage d'un caractère
short y; short y;
short x_position; // Parcours de remplissage du buffer de ligne short x_position; // Parcours de remplissage du buffer de ligne
short line_index; // 0-15 (16 lignes de textes)
short char_index; // Parcours des caractères d'une ligne short char_index; // Parcours des caractères d'une ligne
short start_line=Help_position; byte * char_pixel;
short repeat_menu_x_factor; short repeat_menu_x_factor;
short repeat_menu_y_factor; short repeat_menu_y_factor;
short real_x_pos; short real_x_pos;
short real_y_pos; short real_y_pos;
byte * char_pixel;
short width; // Largeur physique d'une ligne de texte real_x_pos=ToWinX(x_pos);
real_y_pos=ToWinY(y_pos);
// Calcul de la taille
width=strlen(line);
// Les lignes de titres prennent plus de place
if (line_type == 'T' || line_type == '-')
width = width*2;
// Pour chaque ligne dans la fenêtre:
for (y=0;y<8;y++)
{
x_position=0;
// On crée une nouvelle ligne à splotcher
for (char_index=0;char_index<width;char_index++)
{
// Recherche du caractère dans les fontes de l'aide.
// Ligne titre : Si l'indice est impair on dessine le quart de caractère
// qui va a gauche, sinon celui qui va a droite.
if (line_type=='T')
{
if (line[char_index/2]>'_' || line[char_index/2]<' ')
char_pixel=&(Gfx->Help_font_norm['!'][0][0]); // Caractère pas géré
else if (char_index & 1)
char_pixel=&(Gfx->Help_font_t2[(unsigned char)(line[char_index/2])-' '][0][0]);
else
char_pixel=&(Gfx->Help_font_t1[(unsigned char)(line[char_index/2])-' '][0][0]);
}
else if (line_type=='-')
{
if (line[char_index/2]>'_' || line[char_index/2]<' ')
char_pixel=&(Gfx->Help_font_norm['!'][0][0]); // Caractère pas géré
else if (char_index & 1)
char_pixel=&(Gfx->Help_font_t4[(unsigned char)(line[char_index/2])-' '][0][0]);
else
char_pixel=&(Gfx->Help_font_t3[(unsigned char)(line[char_index/2])-' '][0][0]);
}
else if (line_type=='S')
char_pixel=&(Gfx->Bold_font[(unsigned char)(line[char_index])][0][0]);
else if (line_type=='N' || line_type=='K')
char_pixel=&(Gfx->Help_font_norm[(unsigned char)(line[char_index])][0][0]);
else
char_pixel=&(Gfx->Help_font_norm['!'][0][0]); // Un garde-fou en cas de probleme
for (x=0;x<6;x++)
for (repeat_menu_x_factor=0;repeat_menu_x_factor<Menu_factor_X;repeat_menu_x_factor++)
{
byte color = *(char_pixel+x+y*6);
byte repetition = Pixel_width-1;
// Surlignement pour liens
if (line_type=='K' && char_index>=link_position
&& char_index<(link_position+link_size))
{
if (color == MC_Light)
color=MC_White;
else if (color == MC_Dark)
color=MC_Light;
else if (y<7)
color=MC_Dark;
}
Horizontal_line_buffer[x_position++]=color;
while (repetition--)
Horizontal_line_buffer[x_position++]=color;
}
}
// On la splotche
for (repeat_menu_y_factor=0;repeat_menu_y_factor<Menu_factor_Y;repeat_menu_y_factor++)
Display_line_fast(real_x_pos,real_y_pos++,width*Menu_factor_X*6,Horizontal_line_buffer);
}
return width;
}
// -- Menu d'aide -----------------------------------------------------------
void Display_help(void)
{
short line_index; // 0-15 (16 lignes de textes)
short start_line=Help_position;
const short x_pos=13;
const short y_pos=19;
char line_type; // N: Normale, T: Titre, S: Sous-titre char line_type; // N: Normale, T: Titre, S: Sous-titre
// -: Ligne inférieur de sous-titre // -: Ligne inférieur de sous-titre
const char * line; const char * line;
@ -254,21 +339,19 @@ void Display_help(void)
// raccourcis clavier // raccourcis clavier
short link_position=0; // Position du premier caractère "variable" short link_position=0; // Position du premier caractère "variable"
short link_size=0; // Taille de la partie variable short link_size=0; // Taille de la partie variable
short width;
real_x_pos=Window_pos_X+(13*Menu_factor_X);
real_y_pos=Window_pos_Y+(19*Menu_factor_Y);
for (line_index=0;line_index<16;line_index++) for (line_index=0;line_index<16;line_index++)
{ {
// Shortcut au cas ou la section fait moins de 16 lignes // Shortcut au cas ou la section fait moins de 16 lignes
if (line_index >= Help_section[Current_help_section].Length) if (line_index >= Help_section[Current_help_section].Length)
{ {
Block (real_x_pos, Window_rectangle (x_pos,
real_y_pos, y_pos + line_index*8,
44*6*Menu_factor_X, 44*6,
// 44 = Nb max de char (+1 pour éviter les plantages en mode X // 44 = Nb max de char (+1 pour éviter les plantages en mode X
// causés par une largeur = 0) // causés par une largeur = 0)
(Menu_factor_Y<<3) * (16 - line_index), (16 - line_index)*8,
MC_Black); MC_Black);
break; break;
} }
@ -307,83 +390,16 @@ void Display_help(void)
line = buffer; line = buffer;
} }
// Calcul de la taille width=Print_help(x_pos, y_pos+(line_index<<3), line, line_type, link_position, link_size);
width=strlen(line);
// Les lignes de titres prennent plus de place
if (line_type == 'T' || line_type == '-')
width = width*2;
// Pour chaque ligne dans la fenêtre:
for (y=0;y<8;y++)
{
x_position=0;
// On crée une nouvelle ligne à splotcher
for (char_index=0;char_index<width;char_index++)
{
// Recherche du caractère dans les fontes de l'aide.
// Ligne titre : Si l'indice est impair on dessine le quart de caractère
// qui va a gauche, sinon celui qui va a droite.
if (line_type=='T')
{
if (line[char_index/2]>'_' || line[char_index/2]<' ')
char_pixel=&(Gfx->Help_font_norm['!'][0][0]); // Caractère pas géré
else if (char_index & 1)
char_pixel=&(Gfx->Help_font_t2[(unsigned char)(line[char_index/2])-' '][0][0]);
else
char_pixel=&(Gfx->Help_font_t1[(unsigned char)(line[char_index/2])-' '][0][0]);
}
else if (line_type=='-')
{
if (line[char_index/2]>'_' || line[char_index/2]<' ')
char_pixel=&(Gfx->Help_font_norm['!'][0][0]); // Caractère pas géré
else if (char_index & 1)
char_pixel=&(Gfx->Help_font_t4[(unsigned char)(line[char_index/2])-' '][0][0]);
else
char_pixel=&(Gfx->Help_font_t3[(unsigned char)(line[char_index/2])-' '][0][0]);
}
else if (line_type=='S')
char_pixel=&(Gfx->Bold_font[(unsigned char)(line[char_index])][0][0]);
else if (line_type=='N' || line_type=='K')
char_pixel=&(Gfx->Help_font_norm[(unsigned char)(line[char_index])][0][0]);
else
char_pixel=&(Gfx->Help_font_norm['!'][0][0]); // Un garde-fou en cas de probleme
for (x=0;x<6;x++)
for (repeat_menu_x_factor=0;repeat_menu_x_factor<Menu_factor_X;repeat_menu_x_factor++)
{
byte color = *(char_pixel+x+y*6);
byte repetition = Pixel_width-1;
// Surlignement pour liens
if (line_type=='K' && char_index>=link_position
&& char_index<(link_position+link_size))
{
if (color == MC_Light)
color=MC_White;
else if (color == MC_Dark)
color=MC_Light;
else if (y<7)
color=MC_Dark;
}
Horizontal_line_buffer[x_position++]=color;
while (repetition--)
Horizontal_line_buffer[x_position++]=color;
}
}
// On la splotche
for (repeat_menu_y_factor=0;repeat_menu_y_factor<Menu_factor_Y;repeat_menu_y_factor++)
Display_line_fast(real_x_pos,real_y_pos++,width*Menu_factor_X*6,Horizontal_line_buffer);
}
// On efface la fin de la ligne: // On efface la fin de la ligne:
Block (real_x_pos+width*Menu_factor_X*6, if (width<44)
real_y_pos-(8*Menu_factor_Y), Window_rectangle (x_pos+width*6,
((44*6*Menu_factor_X)-width*Menu_factor_X*6)+1, y_pos+(line_index<<3),
// 44 = Nb max de char (+1 pour éviter les plantages en mode X (44-width)*6,
// causés par une largeur = 0) 8,
Menu_factor_Y<<3,
MC_Black); MC_Black);
} }
Update_rect(Window_pos_X+13*Menu_factor_X,Window_pos_Y+19*Menu_factor_Y,44*6*Menu_factor_X,16*8*Menu_factor_Y); Update_window_area(x_pos,y_pos,44*6,16*8);
} }
@ -391,7 +407,7 @@ void Scroll_help(T_Scroller_button * scroller)
{ {
Hide_cursor(); Hide_cursor();
scroller->Position=Help_position; scroller->Position=Help_position;
Compute_slider_cursor_height(scroller); Compute_slider_cursor_length(scroller);
Window_draw_slider(scroller); Window_draw_slider(scroller);
Display_help(); Display_help();
Display_cursor(); Display_cursor();
@ -510,7 +526,7 @@ void Window_help(int section, const char *sub_section)
nb_lines=Help_section[Current_help_section].Length; nb_lines=Help_section[Current_help_section].Length;
scroller->Position=0; scroller->Position=0;
scroller->Nb_elements=nb_lines; scroller->Nb_elements=nb_lines;
Compute_slider_cursor_height(scroller); Compute_slider_cursor_length(scroller);
Window_draw_slider(scroller); Window_draw_slider(scroller);
} }
else else
@ -627,7 +643,51 @@ void Button_Stats(void)
Print_in_window(10,35,"Build options:",STATS_TITLE_COLOR,MC_Black); Print_in_window(10,35,"Build options:",STATS_TITLE_COLOR,MC_Black);
Print_in_window(146,35,TrueType_is_supported()?"TTF fonts":"no TTF fonts",STATS_DATA_COLOR,MC_Black); Print_in_window(146,35,TrueType_is_supported()?"TTF fonts":"no TTF fonts",STATS_DATA_COLOR,MC_Black);
#if defined (__MINT__)
// Affichage de la mémoire restante
Print_in_window(10,43,"Free memory: ",STATS_TITLE_COLOR,MC_Black);
freeRam=0;
char helpBuf[64];
unsigned long STRAM,TTRAM;
Atari_Memory_free(&STRAM,&TTRAM);
freeRam=STRAM+TTRAM;
buffer[0]='\0';
if(STRAM > (100*1024*1024))
sprintf(helpBuf,"ST:%u Mb ",(unsigned int)(STRAM/(1024*1024)));
else if(freeRam > 100*1024)
sprintf(helpBuf,"ST:%u Kb ",(unsigned int)(STRAM/1024));
else
sprintf(helpBuf,"ST:%u b ",(unsigned int)STRAM);
strncat(buffer,helpBuf,sizeof(char)*37);
if(TTRAM > (100ULL*1024*1024*1024))
sprintf(helpBuf,"TT:%u Gb",(unsigned int)(TTRAM/(1024*1024*1024)));
else if(TTRAM > (100*1024*1024))
sprintf(helpBuf,"TT:%u Mb",(unsigned int)(TTRAM/(1024*1024)));
else if(freeRam > 100*1024)
sprintf(helpBuf,"TT:%u Kb",(unsigned int)(TTRAM/1024));
else
sprintf(helpBuf,"TT:%u b",(unsigned int)TTRAM);
strncat(buffer,helpBuf,sizeof(char)*37);
if(freeRam > (100ULL*1024*1024*1024))
sprintf(helpBuf,"(%u Gb)",(unsigned int)(freeRam/(1024*1024*1024)));
else if(freeRam > (100*1024*1024))
sprintf(helpBuf,"(%u Mb)",(unsigned int)(freeRam/(1024*1024)));
else if(freeRam > 100*1024)
sprintf(helpBuf,"(%u Kb)",(unsigned int)(freeRam/1024));
else
sprintf(helpBuf,"(%u b)",(unsigned int)freeRam);
strncat(buffer,helpBuf,sizeof(char)*37);
Print_in_window(18,51,buffer,STATS_DATA_COLOR,MC_Black);
#else
// Affichage de la mémoire restante // Affichage de la mémoire restante
Print_in_window(10,51,"Free memory: ",STATS_TITLE_COLOR,MC_Black); Print_in_window(10,51,"Free memory: ",STATS_TITLE_COLOR,MC_Black);
@ -641,8 +701,12 @@ void Button_Stats(void)
sprintf(buffer,"%u Kilobytes",(unsigned int)(freeRam/1024)); sprintf(buffer,"%u Kilobytes",(unsigned int)(freeRam/1024));
else else
sprintf(buffer,"%u bytes",(unsigned int)freeRam); sprintf(buffer,"%u bytes",(unsigned int)freeRam);
Print_in_window(114,51,buffer,STATS_DATA_COLOR,MC_Black); Print_in_window(114,51,buffer,STATS_DATA_COLOR,MC_Black);
#endif
// Used memory // Used memory
Print_in_window(10,59,"Used memory pages: ",STATS_TITLE_COLOR,MC_Black); Print_in_window(10,59,"Used memory pages: ",STATS_TITLE_COLOR,MC_Black);
if(Stats_pages_memory > (100LL*1024*1024*1024)) if(Stats_pages_memory > (100LL*1024*1024*1024))
@ -670,6 +734,14 @@ void Button_Stats(void)
statfs(Main_current_directory,&disk_info); statfs(Main_current_directory,&disk_info);
mem_size=(qword) disk_info.f_bfree * (qword) disk_info.f_bsize; mem_size=(qword) disk_info.f_bfree * (qword) disk_info.f_bsize;
} }
#elif defined (__MINT__)
_DISKINFO drvInfo;
mem_size=0;
Dfree(&drvInfo,0);
//number of free clusters*sectors per cluster*bytes per sector;
// reports current drive
mem_size=drvInfo.b_free*drvInfo.b_clsiz*drvInfo.b_secsiz;
#else #else
// Free disk space is only for shows. Other platforms can display 0. // Free disk space is only for shows. Other platforms can display 0.
#warning "Missing code for your platform !!! Check and correct please :)" #warning "Missing code for your platform !!! Check and correct please :)"

View File

@ -46,5 +46,17 @@ void Button_Stats(void);
*/ */
void Window_help(int section, const char * sub_section); void Window_help(int section, const char * sub_section);
/// Opens a window where you can change a shortcut key(s).
void Window_set_shortcut(int action_id);
///
/// Print a line with the 'help' (6x8) font.
short Print_help(short x_pos, short y_pos, const char *line, char line_type, short link_position, short link_size);
// Nom de la touche actuallement assignée à un raccourci d'après son numéro
// de type 0x100+BOUTON_* ou SPECIAL_*
const char * Keyboard_shortcut_value(word shortcut_number);
#endif #endif

View File

@ -62,7 +62,11 @@ static const T_Help_table helptable_about[] =
HELP_BOLD (" \"Dragon's Layers\" Edition") HELP_BOLD (" \"Dragon's Layers\" Edition")
HELP_BOLD (" THE ULTIMATE MULTI-RESOLUTION GFX EDITOR") HELP_BOLD (" THE ULTIMATE MULTI-RESOLUTION GFX EDITOR")
HELP_TEXT (" http://grafx2.googlecode.com") HELP_TEXT (" http://grafx2.googlecode.com")
#if defined(__MINT__)
HELP_TEXT (" atari build ")
#else
HELP_TEXT ("") HELP_TEXT ("")
#endif
HELP_TEXT ("Copyright 2007-2010, the Grafx2 project team") HELP_TEXT ("Copyright 2007-2010, the Grafx2 project team")
HELP_TEXT (" Copyright 1996-2001, SUNSET DESIGN") HELP_TEXT (" Copyright 1996-2001, SUNSET DESIGN")
}; };
@ -156,6 +160,7 @@ static const T_Help_table helptable_help[] =
HELP_LINK ("Filled polyform: %s", 0x200+BUTTON_POLYFILL) HELP_LINK ("Filled polyform: %s", 0x200+BUTTON_POLYFILL)
HELP_LINK ("Gradient rectangle: %s", 0x100+BUTTON_GRADRECT) HELP_LINK ("Gradient rectangle: %s", 0x100+BUTTON_GRADRECT)
HELP_LINK ("Gradation menu: %s", 0x200+BUTTON_GRADRECT) HELP_LINK ("Gradation menu: %s", 0x200+BUTTON_GRADRECT)
HELP_LINK ("Toggle color cycling:%s", SPECIAL_CYCLE_MODE)
HELP_LINK ("Spheres: %s", 0x100+BUTTON_SPHERES) HELP_LINK ("Spheres: %s", 0x100+BUTTON_SPHERES)
HELP_LINK ("Gradient ellipses: %s", 0x200+BUTTON_SPHERES) HELP_LINK ("Gradient ellipses: %s", 0x200+BUTTON_SPHERES)
HELP_LINK ("Adjust picture: %s", 0x100+BUTTON_ADJUST) HELP_LINK ("Adjust picture: %s", 0x100+BUTTON_ADJUST)
@ -204,6 +209,10 @@ static const T_Help_table helptable_help[] =
HELP_LINK ("Distort brush: %s", SPECIAL_DISTORT) HELP_LINK ("Distort brush: %s", SPECIAL_DISTORT)
HELP_LINK ("Outline brush: %s", SPECIAL_OUTLINE) HELP_LINK ("Outline brush: %s", SPECIAL_OUTLINE)
HELP_LINK ("Nibble brush: %s", SPECIAL_NIBBLE) HELP_LINK ("Nibble brush: %s", SPECIAL_NIBBLE)
HELP_LINK ("Double brush size: %s", SPECIAL_BRUSH_DOUBLE)
HELP_LINK ("Halve brush size: %s", SPECIAL_BRUSH_HALVE)
HELP_LINK ("Double brush width: %s", SPECIAL_BRUSH_DOUBLE_WIDTH)
HELP_LINK ("Double brush height: %s", SPECIAL_BRUSH_DOUBLE_HEIGHT)
HELP_LINK ("Get brush colors: %s", SPECIAL_GET_BRUSH_COLORS) HELP_LINK ("Get brush colors: %s", SPECIAL_GET_BRUSH_COLORS)
HELP_LINK ("Recolorize brush: %s", SPECIAL_RECOLORIZE_BRUSH) HELP_LINK ("Recolorize brush: %s", SPECIAL_RECOLORIZE_BRUSH)
HELP_LINK ("Rotate brush: %s", SPECIAL_ROTATE_ANY_ANGLE) HELP_LINK ("Rotate brush: %s", SPECIAL_ROTATE_ANY_ANGLE)
@ -228,6 +237,18 @@ static const T_Help_table helptable_help[] =
HELP_LINK (" 18:1 %s", SPECIAL_ZOOM_18) HELP_LINK (" 18:1 %s", SPECIAL_ZOOM_18)
HELP_LINK (" 20:1 %s", SPECIAL_ZOOM_20) HELP_LINK (" 20:1 %s", SPECIAL_ZOOM_20)
HELP_LINK ("Brush effects menu: %s", 0x100+BUTTON_BRUSH_EFFECTS) HELP_LINK ("Brush effects menu: %s", 0x100+BUTTON_BRUSH_EFFECTS)
HELP_LINK ("Brush factory: %s", 0x200+BUTTON_BRUSH_EFFECTS)
HELP_LINK ("Repeat last script: %s", SPECIAL_REPEAT_SCRIPT)
HELP_LINK ("Run script #1: %s", SPECIAL_RUN_SCRIPT_1)
HELP_LINK ("Run script #2: %s", SPECIAL_RUN_SCRIPT_2)
HELP_LINK ("Run script #3: %s", SPECIAL_RUN_SCRIPT_3)
HELP_LINK ("Run script #4: %s", SPECIAL_RUN_SCRIPT_4)
HELP_LINK ("Run script #5: %s", SPECIAL_RUN_SCRIPT_5)
HELP_LINK ("Run script #6: %s", SPECIAL_RUN_SCRIPT_6)
HELP_LINK ("Run script #7: %s", SPECIAL_RUN_SCRIPT_7)
HELP_LINK ("Run script #8: %s", SPECIAL_RUN_SCRIPT_8)
HELP_LINK ("Run script #9: %s", SPECIAL_RUN_SCRIPT_9)
HELP_LINK ("Run script #10: %s", SPECIAL_RUN_SCRIPT_10)
HELP_LINK ("Text: %s", 0x100+BUTTON_TEXT) HELP_LINK ("Text: %s", 0x100+BUTTON_TEXT)
HELP_LINK ("Resolution menu: %s", 0x100+BUTTON_RESOL) HELP_LINK ("Resolution menu: %s", 0x100+BUTTON_RESOL)
HELP_LINK ("Safety resolution: %s", 0x200+BUTTON_RESOL) HELP_LINK ("Safety resolution: %s", 0x200+BUTTON_RESOL)
@ -424,6 +445,14 @@ static const T_Help_table helptable_credits[] =
HELP_TEXT ("") HELP_TEXT ("")
HELP_TEXT (" Luc Schrijvers (Begasus)") HELP_TEXT (" Luc Schrijvers (Begasus)")
HELP_TEXT ("") HELP_TEXT ("")
HELP_BOLD (" WIZ & CAANOO PORT")
HELP_TEXT ("")
HELP_TEXT (" Alexander Filyanov (PheeL)")
HELP_TEXT ("")
HELP_BOLD (" ATARI PORT")
HELP_TEXT ("")
HELP_TEXT (" Pawel Goralski (Saulot)")
HELP_TEXT ("")
HELP_TEXT ("") HELP_TEXT ("")
HELP_TEXT (" ... made it work on your favourite toaster") HELP_TEXT (" ... made it work on your favourite toaster")
HELP_TEXT ("") HELP_TEXT ("")
@ -432,17 +461,18 @@ static const T_Help_table helptable_credits[] =
//HELP_TEXT ("0----5----0----5----0----5----0----5----0--X") //HELP_TEXT ("0----5----0----5----0----5----0----5----0--X")
HELP_TEXT (" anibiqme blumunkee BDCIron ") HELP_TEXT (" anibiqme blumunkee BDCIron ")
HELP_TEXT (" Ced DawnBringer El Topo ") HELP_TEXT (" Ced DawnBringer El Topo ")
HELP_TEXT (" falenblood fano fogbot121 ") HELP_TEXT (" falenblood fanickbux fano ")
HELP_TEXT (" Frost Grimmy grknsngn ") HELP_TEXT (" fogbot121 Frost Grimmy ")
HELP_TEXT (" Gürkan Sengün Hatch HoraK-FDF ") HELP_TEXT (" Gürkan Sengün Hatch HoraK-FDF ")
HELP_TEXT (" iLKke Iw2evk Jamon ") HELP_TEXT (" iLKke Iw2evk Jamon ")
HELP_TEXT (" keito kusma Lord Graga ") HELP_TEXT (" keito kusma Lord Graga ")
HELP_TEXT (" Lorenzo Gatti MagerValp maymunbeyin ") HELP_TEXT (" Lorenzo Gatti MagerValp maymunbeyin ")
HELP_TEXT (" mind MooZ Pasi Kallinen ") HELP_TEXT (" mind MooZ Pasi Kallinen ")
HELP_TEXT (" the Peach petter richienyhus ") HELP_TEXT (" the Peach petter PheeL ")
HELP_TEXT (" tape.wyrm TeeEmCee tempest ") HELP_TEXT (" richienyhus sm4tik spratek ")
HELP_TEXT (" tape.yrm TeeEmCee tempest ")
HELP_TEXT (" Timo Kurrpa titus^Rab Tobé ") HELP_TEXT (" Timo Kurrpa titus^Rab Tobé ")
HELP_TEXT (" yakumo9275 00ai99") HELP_TEXT (" yakumo2975 00ai99")
HELP_TEXT ("") HELP_TEXT ("")
HELP_TEXT (" ... posted the annoying bug reports.") HELP_TEXT (" ... posted the annoying bug reports.")
HELP_TEXT ("") HELP_TEXT ("")
@ -631,9 +661,25 @@ static const T_Help_table helptable_paintbrush[] =
HELP_TEXT ("brush size by using the keys:") HELP_TEXT ("brush size by using the keys:")
HELP_LINK ("Reduce : %s", SPECIAL_SMALLER_PAINTBRUSH) HELP_LINK ("Reduce : %s", SPECIAL_SMALLER_PAINTBRUSH)
HELP_LINK ("Increase : %s", SPECIAL_BIGGER_PAINTBRUSH) HELP_LINK ("Increase : %s", SPECIAL_BIGGER_PAINTBRUSH)
HELP_TEXT ("The last 3 paintbrushes in the menu belong") HELP_TEXT ("")
HELP_TEXT ("to the \"miscellaneous\" family and their size") HELP_TEXT ("Other brushes are bitmaps, their size can't")
HELP_TEXT ("cannot be modified.") HELP_TEXT ("be adjusted.")
HELP_TEXT ("")
HELP_TEXT ("Click with left mouse button to choose a ")
HELP_TEXT ("paintbrush, and right mouse button to store")
HELP_TEXT ("your current brush in the slot. If your")
HELP_TEXT ("current brush is a grabbed brush, it will")
HELP_TEXT ("store a monochrome version of it, maximum")
HELP_TEXT ("15x15. (See below 'Brush container' to store")
HELP_TEXT ("backups of a big brush)")
HELP_TEXT ("The stored brushes are saved when you exit")
HELP_TEXT ("the program.")
HELP_TEXT ("")
HELP_TEXT ("The 'Preset' button allows you to pick a")
HELP_TEXT ("brush from any family. It's useful if you've")
HELP_TEXT ("overwritten all normal slots with brushes")
HELP_TEXT ("that you use more often.")
HELP_TEXT ("")
HELP_TEXT ("") HELP_TEXT ("")
HELP_BOLD ("BRUSH CONTAINER") HELP_BOLD ("BRUSH CONTAINER")
HELP_TEXT ("") HELP_TEXT ("")
@ -1123,6 +1169,27 @@ static const T_Help_table helptable_grad_rect[] =
HELP_TEXT ("- Index scroller: Defines the current") HELP_TEXT ("- Index scroller: Defines the current")
HELP_TEXT ("gradation among a set of 16 that will be") HELP_TEXT ("gradation among a set of 16 that will be")
HELP_TEXT ("memorised.") HELP_TEXT ("memorised.")
HELP_TEXT ("")
HELP_BOLD ("COLOR CYCLING")
HELP_TEXT ("")
HELP_TEXT ("These options allow you to use animation of")
HELP_TEXT ("colors: Grafx2 will shift palette entries")
HELP_TEXT ("at real-time. Note that only the LBM file")
HELP_TEXT ("format can record these settings, and very")
HELP_TEXT ("few image viewers will play it back.")
HELP_TEXT ("")
HELP_TEXT ("- Cycling: Activates or desactivates the")
HELP_TEXT ("cycling of colors when you're in the editor.")
HELP_LINK ("Key: %s", SPECIAL_CYCLE_MODE)
HELP_TEXT ("")
HELP_TEXT ("- Speed: Sets the speed for the cycling of")
HELP_TEXT ("this range. Zero means this range doesn't")
HELP_TEXT ("cycle. With 1, the range shifts 0.2856 times")
HELP_TEXT ("per second; at speed 64 it's 18.28 times")
HELP_TEXT ("per second. The program activates cycling")
HELP_TEXT ("while you hold the speed slider, so you can")
HELP_TEXT ("preview the speed.")
HELP_TEXT ("")
}; };
static const T_Help_table helptable_spheres[] = static const T_Help_table helptable_spheres[] =
{ {
@ -1253,15 +1320,17 @@ static const T_Help_table helptable_brush_fx[] =
HELP_TEXT ("point at coordinates inferior to the ones of") HELP_TEXT ("point at coordinates inferior to the ones of")
HELP_TEXT ("the first point, the brush will be inverted.") HELP_TEXT ("the first point, the brush will be inverted.")
HELP_TEXT ("Meanwhile, you can press the following keys") HELP_TEXT ("Meanwhile, you can press the following keys")
HELP_TEXT ("whose effects are: 'D' : double the") HELP_TEXT ("whose effects are:")
HELP_TEXT ("brush in X and Y 'H' : reduce the") HELP_TEXT (" 'D' : Double the brush")
HELP_TEXT ("brush by half in X and Y 'X' : double") HELP_TEXT (" 'H' : Reduce the brush by half")
HELP_TEXT ("the brush in X 'Shift+X': reduce the brush") HELP_TEXT (" 'X' : Double the brush in X")
HELP_TEXT ("by half in X 'Y' : double the brush") HELP_TEXT (" 'Shift+X': Reduce the brush by half in X")
HELP_TEXT ("in Y 'Shift+Y': reduce the brush by half") HELP_TEXT (" 'Y' : Double the brush in Y")
HELP_TEXT ("in Y 'N' : restore the normal size of") HELP_TEXT (" 'Shift+Y': Reduce the brush by half in Y")
HELP_TEXT ("the brush (can be useful") HELP_TEXT (" 'N' : Restore the normal size of the")
HELP_TEXT ("because it's the only way for cancelling)") HELP_TEXT (" brush (can be useful because")
HELP_TEXT (" it's the only way for")
HELP_TEXT (" cancelling)")
HELP_TEXT ("") HELP_TEXT ("")
HELP_LINK ("- Distort: (Key:%s)",SPECIAL_DISTORT) HELP_LINK ("- Distort: (Key:%s)",SPECIAL_DISTORT)
HELP_TEXT ("Triggers an interactive operation") HELP_TEXT ("Triggers an interactive operation")
@ -1312,6 +1381,8 @@ static const T_Help_table helptable_brush_fx[] =
HELP_TEXT ("") HELP_TEXT ("")
HELP_TITLE("BRUSH FACTORY") HELP_TITLE("BRUSH FACTORY")
HELP_TEXT ("") HELP_TEXT ("")
HELP_LINK ("(Key:%s)",0x200+BUTTON_BRUSH_EFFECTS)
HELP_TEXT ("")
HELP_TEXT ("This menu allows you to run scripts. Scripts") HELP_TEXT ("This menu allows you to run scripts. Scripts")
HELP_TEXT ("are written in the Lua language, and allow") HELP_TEXT ("are written in the Lua language, and allow")
HELP_TEXT ("you to modify the brush (hence the name") HELP_TEXT ("you to modify the brush (hence the name")
@ -1331,6 +1402,8 @@ static const T_Help_table helptable_brush_fx[] =
HELP_TEXT ("time you open the window. Scripts are loaded") HELP_TEXT ("time you open the window. Scripts are loaded")
HELP_TEXT ("from disk when you run them.") HELP_TEXT ("from disk when you run them.")
HELP_TEXT ("") HELP_TEXT ("")
HELP_LINK ("- Repeat last script: %s", SPECIAL_REPEAT_SCRIPT)
HELP_TEXT ("")
}; };
static const T_Help_table helptable_effects[] = static const T_Help_table helptable_effects[] =
{ {
@ -2273,6 +2346,13 @@ static const T_Help_table helptable_settings_details[] =
HELP_TEXT ("variants of your original palette, resulting") HELP_TEXT ("variants of your original palette, resulting")
HELP_TEXT ("in a pretty grid !") HELP_TEXT ("in a pretty grid !")
HELP_TEXT ("") HELP_TEXT ("")
HELP_BOLD (" Sync views")
HELP_TEXT ("When this mode is active, scrolling the view")
HELP_TEXT ("(and the magnifier view) affects both the")
HELP_TEXT ("main image and the spare page - as long as")
HELP_TEXT ("they have the same dimensions.")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_TEXT ("") HELP_TEXT ("")
HELP_TITLE("INPUT") HELP_TITLE("INPUT")
HELP_TEXT ("") HELP_TEXT ("")
@ -2323,6 +2403,14 @@ static const T_Help_table helptable_settings_details[] =
HELP_TEXT ("GrafX2 to recognize them as a combo.") HELP_TEXT ("GrafX2 to recognize them as a combo.")
HELP_TEXT ("") HELP_TEXT ("")
HELP_TEXT ("") HELP_TEXT ("")
HELP_BOLD (" Swap buttons")
HELP_TEXT ("This setting determines which key inverts")
HELP_TEXT ("the mouse buttons when it's held : A left")
HELP_TEXT ("click is then interpreted as a right-click.")
HELP_TEXT ("It's especially useful for one-button")
HELP_TEXT ("controllers, such as touchscreens and")
HELP_TEXT ("tablets.")
HELP_TEXT ("")
HELP_TITLE("EDITING") HELP_TITLE("EDITING")
HELP_TEXT ("") HELP_TEXT ("")
HELP_TEXT ("") HELP_TEXT ("")
@ -2359,7 +2447,14 @@ static const T_Help_table helptable_settings_details[] =
HELP_TEXT ("window. (Set it to 'no' if you have a slow") HELP_TEXT ("window. (Set it to 'no' if you have a slow")
HELP_TEXT ("computer or if you edit huge pictures)") HELP_TEXT ("computer or if you edit huge pictures)")
HELP_TEXT ("") HELP_TEXT ("")
HELP_TEXT ("") HELP_BOLD (" Right click colorpick")
HELP_TEXT ("This enables a mode where the right mouse")
HELP_TEXT ("buttons acts as a color picker until")
HELP_TEXT ("it's released, and selects Foreground color.")
HELP_TEXT ("This mode prevents you from painting with")
HELP_TEXT ("Background color.")
HELP_TEXT ("This option is ignored when the Shade,")
HELP_TEXT ("Quick-shade, or Tiling mode is used.")
}; };
static const T_Help_table helptable_clear[] = static const T_Help_table helptable_clear[] =
@ -2474,16 +2569,28 @@ static const T_Help_table helptable_palette[] =
HELP_TEXT ("- Gauges: Allow you to modify the") HELP_TEXT ("- Gauges: Allow you to modify the")
HELP_TEXT ("current selection.") HELP_TEXT ("current selection.")
HELP_TEXT ("") HELP_TEXT ("")
HELP_TEXT ("- RGB or HSL above the gauges: Switches")
HELP_TEXT ("between RGB and HSL color spaces. In HSL")
HELP_TEXT ("mode, the three sliders allow you to set the")
HELP_TEXT ("Hue (tint), Saturation (from grayscale to")
HELP_TEXT ("pure color) and Lightness (from black to")
HELP_TEXT ("white).")
HELP_TEXT ("")
HELP_TEXT ("- numbers below the gauges: Allows you to")
HELP_TEXT ("type in a new color in hexadecimal RRGGBB")
HELP_TEXT ("or RGB: ie. to get blue, you can type either")
HELP_TEXT ("0000ff or 00f.")
HELP_TEXT ("")
HELP_TEXT ("- \"+\" and \"-\": Allow you to lighten or") HELP_TEXT ("- \"+\" and \"-\": Allow you to lighten or")
HELP_TEXT ("darken the current selection.") HELP_TEXT ("darken the current selection.")
HELP_TEXT ("") HELP_TEXT ("")
HELP_TEXT ("- Default: Restores the predifined GrafX2") HELP_TEXT ("- Preset: Restores the predefined GrafX2")
HELP_TEXT ("palette.") HELP_TEXT ("palette.")
HELP_TEXT ("") HELP_TEXT ("")
HELP_TEXT ("- Gray: Transforms the current selection") HELP_TEXT ("- Gray: Transforms the current selection")
HELP_TEXT ("into its gray-scaled equivalent.") HELP_TEXT ("into its gray-scaled equivalent.")
HELP_TEXT ("") HELP_TEXT ("")
HELP_TEXT ("- Negative: Transforms the current selection") HELP_TEXT ("- Neg: Transforms the current selection")
HELP_TEXT ("into its reverse video equivalent.") HELP_TEXT ("into its reverse video equivalent.")
HELP_TEXT ("") HELP_TEXT ("")
HELP_TEXT ("- Invert: Swaps the colors of the current") HELP_TEXT ("- Invert: Swaps the colors of the current")
@ -2520,18 +2627,12 @@ static const T_Help_table helptable_palette[] =
HELP_TEXT ("whole palette it will sort this range.") HELP_TEXT ("whole palette it will sort this range.")
HELP_TEXT ("") HELP_TEXT ("")
HELP_TEXT ("- Used: Indicates the number of colors used") HELP_TEXT ("- Used: Indicates the number of colors used")
HELP_TEXT ("in the picture.") HELP_TEXT ("in the picture and opens a histogram screen.")
HELP_TEXT ("") HELP_TEXT ("")
HELP_TEXT ("- Zap unused: Erases the unused colors with") HELP_TEXT ("- Zap unused: Erases the unused colors with")
HELP_TEXT ("copies of the current selection. (The") HELP_TEXT ("copies of the current selection. (The")
HELP_TEXT ("keyboard shortcut for this button is <Del>).") HELP_TEXT ("keyboard shortcut for this button is <Del>).")
HELP_TEXT ("") HELP_TEXT ("")
HELP_TEXT ("- HSL: Switches between RGB and HSL color")
HELP_TEXT ("spaces. In HSL mode, the three sliders")
HELP_TEXT ("allow you to set the Hue (tint), Saturation")
HELP_TEXT ("(from grayscale to pure color) and")
HELP_TEXT ("Lightness (from black to white).")
HELP_TEXT ("")
HELP_TEXT ("- Reduce: Allows you to reduce the palette") HELP_TEXT ("- Reduce: Allows you to reduce the palette")
HELP_TEXT ("to the number of colors you want (and") HELP_TEXT ("to the number of colors you want (and")
HELP_TEXT ("modifies the picture).") HELP_TEXT ("modifies the picture).")

View File

@ -884,7 +884,16 @@ T_Key_config ConfigKey[NB_SHORTCUTS] = {
"", "",
true, true,
SDLK_u, // U SDLK_u, // U
0}, // Secondary shortcut is button I on the Caanoo, L on the Wiz, unset on others
#if defined (__CAANOO__)
(KEY_JOYBUTTON+JOY_BUTTON_I)
#elif defined (__WIZ__)
(KEY_JOYBUTTON+JOY_BUTTON_L)
#else
0
#endif
// --
},
{103, {103,
"Redo", "Redo",
"Redo the last undone action.", "Redo the last undone action.",
@ -892,7 +901,16 @@ T_Key_config ConfigKey[NB_SHORTCUTS] = {
"", "",
true, true,
SDLK_u|MOD_SHIFT, // Shift + U SDLK_u|MOD_SHIFT, // Shift + U
0}, // Secondary shortcut is button II on the Caanoo, R on the Wiz, unset on others
#if defined (__CAANOO__)
(KEY_JOYBUTTON+JOY_BUTTON_II)
#elif defined (__WIZ__)
(KEY_JOYBUTTON+JOY_BUTTON_R)
#else
0
#endif
// --
},
{133, {133,
"Kill", "Kill",
"Kills the current page. It actually", "Kills the current page. It actually",
@ -924,7 +942,17 @@ T_Key_config ConfigKey[NB_SHORTCUTS] = {
"confirmation is asked.", "confirmation is asked.",
false, false,
SDLK_q, // Q (A en AZERTY) SDLK_q, // Q (A en AZERTY)
0}, // Secondary shortcut is button Home on the Caanoo, Menu on the Wiz, unset on others
#if defined (__CAANOO__)
(KEY_JOYBUTTON+JOY_BUTTON_HOME)
#elif defined (__WIZ__)
(KEY_JOYBUTTON+JOY_BUTTON_MENU)
#else
0
#endif
// --
},
{107, {107,
"Palette menu", "Palette menu",
"Opens a menu which allows you to", "Opens a menu which allows you to",
@ -1478,13 +1506,149 @@ T_Key_config ConfigKey[NB_SHORTCUTS] = {
SDLK_HOME|MOD_ALT, // Alt + Home SDLK_HOME|MOD_ALT, // Alt + Home
0}, 0},
{181, {181,
"Brush factory",
"Opens a window where you can run a",
"Lua script.",
"",
true,
0, // No shortcut
0},
{182,
"Repeat script",
"Re-run the last script selected",
"in the Brush factory window.",
"",
true,
0, // No shortcut
0},
{183,
"Double brush size",
"Resizes the current user brush",
"by doubling width and height.",
"",
true,
SDLK_h|MOD_SHIFT, // Shift+H
0},
{184,
"Double brush width",
"Resizes the current user brush",
"by doubling its width.",
"",
true,
SDLK_x|MOD_SHIFT, // Shift+X
0},
{185,
"Double brush height",
"Resizes the current user brush",
"by doubling its height.",
"",
true,
SDLK_y|MOD_SHIFT, // Shift+Y
0},
{186,
"Halve brush size",
"Resizes the current user brush",
"by halving its width and height",
"",
true,
SDLK_h, // H
0},
{187,
"Run script #1",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{188,
"Run script #2",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{189,
"Run script #3",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{190,
"Run script #4",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{191,
"Run script #5",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{192,
"Run script #6",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{193,
"Run script #7",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{194,
"Run script #8",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{195,
"Run script #9",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{196,
"Run script #10",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{197,
"Toggle color cycling",
"Activates or desactivates color",
"cycling, if the current image has",
"cycling colors. (See gradient menu)",
true,
SDLK_BACKQUOTE|MOD_CTRL, // Ctrl + `~
0},
{198,
"Format checker", "Format checker",
"Performs a format check on the", "Performs a format check on the",
"current image.", "current image.",
"", "",
true, true,
0, 0,
0}, 0}
}; };
word Ordering[NB_SHORTCUTS]= word Ordering[NB_SHORTCUTS]=
@ -1670,6 +1834,23 @@ word Ordering[NB_SHORTCUTS]=
0x100+BUTTON_LAYER_UP, 0x100+BUTTON_LAYER_UP,
0x100+BUTTON_LAYER_DOWN, 0x100+BUTTON_LAYER_DOWN,
0x100+BUTTON_LAYER_MENU, 0x100+BUTTON_LAYER_MENU,
0x200+BUTTON_BRUSH_EFFECTS,
SPECIAL_REPEAT_SCRIPT,
SPECIAL_BRUSH_DOUBLE,
SPECIAL_BRUSH_DOUBLE_WIDTH,
SPECIAL_BRUSH_DOUBLE_HEIGHT,
SPECIAL_BRUSH_HALVE,
SPECIAL_RUN_SCRIPT_1,
SPECIAL_RUN_SCRIPT_2,
SPECIAL_RUN_SCRIPT_3,
SPECIAL_RUN_SCRIPT_4,
SPECIAL_RUN_SCRIPT_5,
SPECIAL_RUN_SCRIPT_6,
SPECIAL_RUN_SCRIPT_7,
SPECIAL_RUN_SCRIPT_8,
SPECIAL_RUN_SCRIPT_9,
SPECIAL_RUN_SCRIPT_10,
SPECIAL_CYCLE_MODE,
SPECIAL_FORMAT_CHECKER, SPECIAL_FORMAT_CHECKER,
SPECIAL_FORMAT_CHECKER_MENU, SPECIAL_FORMAT_CHECKER_MENU,
}; };

View File

@ -33,6 +33,8 @@
#endif #endif
#include <SDL.h> #include <SDL.h>
#define NB_SHORTCUTS 199 ///< Number of actions that can have a key combination associated to it.
/*** Types definitions and structs ***/ /*** Types definitions and structs ***/
typedef struct typedef struct

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@
/// Initialization (and some de-initialization) functions. /// Initialization (and some de-initialization) functions.
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
T_Gui_skin *Load_graphics(const char * skin_file); T_Gui_skin *Load_graphics(const char * skin_file, T_Gradient_array *gradients);
void Set_current_skin(const char *skinfile, T_Gui_skin *gfx); void Set_current_skin(const char *skinfile, T_Gui_skin *gfx);
void Init_buttons(void); void Init_buttons(void);
void Init_operations(void); void Init_operations(void);
@ -34,6 +34,10 @@ int Save_CFG(void);
void Set_all_video_modes(void); void Set_all_video_modes(void);
void Set_config_defaults(void); void Set_config_defaults(void);
void Init_sighandler(void); void Init_sighandler(void);
void Init_paintbrushes(void);
/// Set application icon(s)
void Define_icon(void);
extern char Gui_loading_error_message[512]; extern char Gui_loading_error_message[512];

View File

@ -21,6 +21,12 @@
*/ */
#include <SDL.h> #include <SDL.h>
#include <SDL_syswm.h>
#ifdef __WIN32__
#include <windows.h>
#include <ShellApi.h>
#endif
#include "global.h" #include "global.h"
#include "keyboard.h" #include "keyboard.h"
@ -28,7 +34,9 @@
#include "windows.h" #include "windows.h"
#include "errors.h" #include "errors.h"
#include "misc.h" #include "misc.h"
#include "buttons.h"
#include "input.h" #include "input.h"
#include "loadsave.h"
#ifdef __VBCC__ #ifdef __VBCC__
#define __attribute__(x) #define __attribute__(x)
@ -36,6 +44,7 @@
void Handle_window_resize(SDL_ResizeEvent event); void Handle_window_resize(SDL_ResizeEvent event);
void Handle_window_exit(SDL_QuitEvent event); void Handle_window_exit(SDL_QuitEvent event);
int Color_cycling(__attribute__((unused)) void* useless);
// public Globals (available as extern) // public Globals (available as extern)
@ -44,8 +53,11 @@ int Snap_axis = 0;
int Snap_axis_origin_X; int Snap_axis_origin_X;
int Snap_axis_origin_Y; int Snap_axis_origin_Y;
char * Drop_file_name = NULL;
// -- // --
// Digital joystick state
byte Directional_up; byte Directional_up;
byte Directional_up_right; byte Directional_up_right;
byte Directional_right; byte Directional_right;
@ -56,14 +68,22 @@ byte Directional_left;
byte Directional_up_left; byte Directional_up_left;
byte Directional_click; byte Directional_click;
long Directional_delay; // Emulated directional controller.
// This has a distinct state from Directional_, because some joysticks send
// "I'm not moving" SDL events when idle, thus stopping the emulated one.
byte Directional_emulated_up;
byte Directional_emulated_right;
byte Directional_emulated_down;
byte Directional_emulated_left;
long Directional_first_move;
long Directional_last_move; long Directional_last_move;
long Directional_step;
int Mouse_moved; ///< Boolean, Set to true if any cursor movement occurs. int Mouse_moved; ///< Boolean, Set to true if any cursor movement occurs.
word Input_new_mouse_X; word Input_new_mouse_X;
word Input_new_mouse_Y; word Input_new_mouse_Y;
byte Input_new_mouse_K; byte Input_new_mouse_K;
byte Button_inverter=0; // State of the key that swaps mouse buttons.
byte Mouse_mode = 0; ///< Mouse mode = 0:normal, 1:emulated with custom sensitivity. byte Mouse_mode = 0; ///< Mouse mode = 0:normal, 1:emulated with custom sensitivity.
short Mouse_virtual_x_position; short Mouse_virtual_x_position;
@ -71,21 +91,84 @@ short Mouse_virtual_y_position;
short Mouse_virtual_width; short Mouse_virtual_width;
short Mouse_virtual_height; short Mouse_virtual_height;
// TODO: move to config // Joystick/pad configurations for the various console ports.
#ifdef __GP2X__ // See the #else for the documentation of fields.
short Joybutton_shift=GP2X_BUTTON_L; // Button number that serves as a "shift" modifier // TODO: Make these user-settable somehow.
short Joybutton_control=GP2X_BUTTON_R; // Button number that serves as a "ctrl" modifier #if defined(__GP2X__)
short Joybutton_alt=GP2X_BUTTON_CLICK; // Button number that serves as a "alt" modifier
short Joybutton_left_click=GP2X_BUTTON_B; // Button number that serves as left click #define JOYSTICK_THRESHOLD (4096)
short Joybutton_right_click=GP2X_BUTTON_Y; // Button number that serves as right-click short Joybutton_shift= JOY_BUTTON_L;
#else short Joybutton_control= JOY_BUTTON_R;
short Joybutton_shift=-1; // Button number that serves as a "shift" modifier short Joybutton_alt= JOY_BUTTON_CLICK;
short Joybutton_control=-1; // Button number that serves as a "ctrl" modifier short Joybutton_left_click= JOY_BUTTON_B;
short Joybutton_alt=-1; // Button number that serves as a "alt" modifier short Joybutton_right_click=JOY_BUTTON_Y;
short Joybutton_left_click=0; // Button number that serves as left click
short Joybutton_right_click=0; // Button number that serves as right-click #elif defined(__WIZ__)
#define JOYSTICK_THRESHOLD (4096)
short Joybutton_shift= JOY_BUTTON_X;
short Joybutton_control= JOY_BUTTON_SELECT;
short Joybutton_alt= JOY_BUTTON_Y;
short Joybutton_left_click= JOY_BUTTON_A;
short Joybutton_right_click=JOY_BUTTON_B;
#elif defined(__CAANOO__)
#define JOYSTICK_THRESHOLD (4096)
short Joybutton_shift= JOY_BUTTON_L;
short Joybutton_control= JOY_BUTTON_R;
short Joybutton_alt= JOY_BUTTON_Y;
short Joybutton_left_click= JOY_BUTTON_A;
short Joybutton_right_click=JOY_BUTTON_B;
#else // Default : Any joystick on a computer platform
///
/// This is the sensitivity threshold for the directional
/// pad of a cheap digital joypad on the PC. It has been set through
/// trial and error : If value is too large then the movement is
/// randomly interrupted; if the value is too low the cursor will
/// move by itself, controlled by parasits.
/// YR 04/11/2010: I just observed a -8700 when joystick is idle.
#define JOYSTICK_THRESHOLD (10000)
/// A button that is marked as "modifier" will
short Joybutton_shift=-1; ///< Button number that serves as a "shift" modifier; -1 for none
short Joybutton_control=-1; ///< Button number that serves as a "ctrl" modifier; -1 for none
short Joybutton_alt=-1; ///< Button number that serves as a "alt" modifier; -1 for none
short Joybutton_left_click=0; ///< Button number that serves as left click; -1 for none
short Joybutton_right_click=1; ///< Button number that serves as right-click; -1 for none
#endif #endif
int Has_shortcut(word function)
{
if (function == 0xFFFF)
return 0;
if (function & 0x100)
{
if (Buttons_Pool[function&0xFF].Left_shortcut[0]!=KEY_NONE)
return 1;
if (Buttons_Pool[function&0xFF].Left_shortcut[1]!=KEY_NONE)
return 1;
return 0;
}
if (function & 0x200)
{
if (Buttons_Pool[function&0xFF].Right_shortcut[0]!=KEY_NONE)
return 1;
if (Buttons_Pool[function&0xFF].Right_shortcut[1]!=KEY_NONE)
return 1;
return 0;
}
if(Config_Key[function][0]!=KEY_NONE)
return 1;
if(Config_Key[function][1]!=KEY_NONE)
return 1;
return 0;
}
int Is_shortcut(word key, word function) int Is_shortcut(word key, word function)
{ {
if (key == 0 || function == 0xFFFF) if (key == 0 || function == 0xFFFF)
@ -177,16 +260,18 @@ int Move_cursor_with_constraints()
feedback=1; feedback=1;
if (Input_new_mouse_K == 0) if (Input_new_mouse_K == 0)
{
Input_sticky_control = 0; Input_sticky_control = 0;
}
} }
// Hide cursor, because even just a click change needs it // Hide cursor, because even just a click change needs it
if (!Mouse_moved) if (!Mouse_moved)
{ {
Mouse_moved++;
// Hide cursor (erasing icon and brush on screen // Hide cursor (erasing icon and brush on screen
// before changing the coordinates. // before changing the coordinates.
Hide_cursor(); Hide_cursor();
} }
Mouse_moved++;
if (Input_new_mouse_X != Mouse_X || Input_new_mouse_Y != Mouse_Y) if (Input_new_mouse_X != Mouse_X || Input_new_mouse_Y != Mouse_Y)
{ {
Mouse_X=Input_new_mouse_X; Mouse_X=Input_new_mouse_X;
@ -194,8 +279,8 @@ int Move_cursor_with_constraints()
} }
Mouse_K=Input_new_mouse_K; Mouse_K=Input_new_mouse_K;
if (Mouse_moved > Config.Mouse_merge_movement) if (Mouse_moved > Config.Mouse_merge_movement
if (! Operation[Current_operation][Mouse_K_unique] && !Operation[Current_operation][Mouse_K_unique]
[Operation_stack_size].Fast_mouse) [Operation_stack_size].Fast_mouse)
feedback=1; feedback=1;
} }
@ -254,11 +339,19 @@ int Handle_mouse_click(SDL_MouseButtonEvent event)
switch(event.button) switch(event.button)
{ {
case SDL_BUTTON_LEFT: case SDL_BUTTON_LEFT:
Input_new_mouse_K |= 1; if (Button_inverter)
Input_new_mouse_K |= 2;
else
Input_new_mouse_K |= 1;
break;
break; break;
case SDL_BUTTON_RIGHT: case SDL_BUTTON_RIGHT:
Input_new_mouse_K |= 2; if (Button_inverter)
Input_new_mouse_K |= 1;
else
Input_new_mouse_K |= 2;
break;
break; break;
case SDL_BUTTON_MIDDLE: case SDL_BUTTON_MIDDLE:
@ -284,11 +377,17 @@ int Handle_mouse_release(SDL_MouseButtonEvent event)
switch(event.button) switch(event.button)
{ {
case SDL_BUTTON_LEFT: case SDL_BUTTON_LEFT:
Input_new_mouse_K &= ~1; if (Button_inverter)
Input_new_mouse_K &= ~2;
else
Input_new_mouse_K &= ~1;
break; break;
case SDL_BUTTON_RIGHT: case SDL_BUTTON_RIGHT:
Input_new_mouse_K &= ~2; if (Button_inverter)
Input_new_mouse_K &= ~1;
else
Input_new_mouse_K &= ~2;
break; break;
} }
@ -300,27 +399,64 @@ int Handle_mouse_release(SDL_MouseButtonEvent event)
int Handle_key_press(SDL_KeyboardEvent event) int Handle_key_press(SDL_KeyboardEvent event)
{ {
//Appui sur une touche du clavier //Appui sur une touche du clavier
int modifier;
Key = Keysym_to_keycode(event.keysym); Key = Keysym_to_keycode(event.keysym);
Key_ANSI = Keysym_to_ANSI(event.keysym); Key_ANSI = Keysym_to_ANSI(event.keysym);
switch(event.keysym.sym)
{
case SDLK_RSHIFT:
case SDLK_LSHIFT:
modifier=MOD_SHIFT;
break;
case SDLK_RCTRL:
case SDLK_LCTRL:
modifier=MOD_CTRL;
break;
case SDLK_RALT:
case SDLK_LALT:
case SDLK_MODE:
modifier=MOD_ALT;
break;
case SDLK_RMETA:
case SDLK_LMETA:
modifier=MOD_META;
break;
default:
modifier=0;
}
if (Config.Swap_buttons && modifier == Config.Swap_buttons && Button_inverter==0)
{
Button_inverter=1;
if (Input_new_mouse_K)
{
Input_new_mouse_K ^= 3; // Flip bits 0 and 1
return Move_cursor_with_constraints();
}
}
if(Is_shortcut(Key,SPECIAL_MOUSE_UP)) if(Is_shortcut(Key,SPECIAL_MOUSE_UP))
{ {
Directional_up=1; Directional_emulated_up=1;
return 0; return 0;
} }
else if(Is_shortcut(Key,SPECIAL_MOUSE_DOWN)) else if(Is_shortcut(Key,SPECIAL_MOUSE_DOWN))
{ {
Directional_down=1; Directional_emulated_down=1;
return 0; return 0;
} }
else if(Is_shortcut(Key,SPECIAL_MOUSE_LEFT)) else if(Is_shortcut(Key,SPECIAL_MOUSE_LEFT))
{ {
Directional_left=1; Directional_emulated_left=1;
return 0; return 0;
} }
else if(Is_shortcut(Key,SPECIAL_MOUSE_RIGHT)) else if(Is_shortcut(Key,SPECIAL_MOUSE_RIGHT))
{ {
Directional_right=1; Directional_emulated_right=1;
return 0; return 0;
} }
else if(Is_shortcut(Key,SPECIAL_CLICK_LEFT) && Keyboard_click_allowed > 0) else if(Is_shortcut(Key,SPECIAL_CLICK_LEFT) && Keyboard_click_allowed > 0)
@ -349,26 +485,35 @@ int Release_control(int key_code, int modifier)
Snap_axis = 0; Snap_axis = 0;
need_feedback = 1; need_feedback = 1;
} }
if (Config.Swap_buttons && modifier == Config.Swap_buttons && Button_inverter==1)
{
Button_inverter=0;
if (Input_new_mouse_K)
{
Input_new_mouse_K ^= 3; // Flip bits 0 and 1
return Move_cursor_with_constraints();
}
}
if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_UP][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_UP][0]&modifier) || if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_UP][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_UP][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_MOUSE_UP][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_UP][1]&modifier)) (key_code && key_code == (Config_Key[SPECIAL_MOUSE_UP][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_UP][1]&modifier))
{ {
Directional_up=0; Directional_emulated_up=0;
} }
if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_DOWN][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_DOWN][0]&modifier) || if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_DOWN][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_DOWN][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_MOUSE_DOWN][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_DOWN][1]&modifier)) (key_code && key_code == (Config_Key[SPECIAL_MOUSE_DOWN][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_DOWN][1]&modifier))
{ {
Directional_down=0; Directional_emulated_down=0;
} }
if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_LEFT][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_LEFT][0]&modifier) || if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_LEFT][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_LEFT][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_MOUSE_LEFT][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_LEFT][1]&modifier)) (key_code && key_code == (Config_Key[SPECIAL_MOUSE_LEFT][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_LEFT][1]&modifier))
{ {
Directional_left=0; Directional_emulated_left=0;
} }
if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_RIGHT][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_RIGHT][0]&modifier) || if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_RIGHT][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_RIGHT][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_MOUSE_RIGHT][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_RIGHT][1]&modifier)) (key_code && key_code == (Config_Key[SPECIAL_MOUSE_RIGHT][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_RIGHT][1]&modifier))
{ {
Directional_right=0; Directional_emulated_right=0;
} }
if((key_code && key_code == (Config_Key[SPECIAL_CLICK_LEFT][0]&0x0FFF)) || (Config_Key[SPECIAL_CLICK_LEFT][0]&modifier) || if((key_code && key_code == (Config_Key[SPECIAL_CLICK_LEFT][0]&0x0FFF)) || (Config_Key[SPECIAL_CLICK_LEFT][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_CLICK_LEFT][1]&0x0FFF)) || (Config_Key[SPECIAL_CLICK_LEFT][1]&modifier)) (key_code && key_code == (Config_Key[SPECIAL_CLICK_LEFT][1]&0x0FFF)) || (Config_Key[SPECIAL_CLICK_LEFT][1]&modifier))
@ -445,54 +590,88 @@ int Handle_joystick_press(SDL_JoyButtonEvent event)
if (event.button == Joybutton_control) if (event.button == Joybutton_control)
{ {
SDL_SetModState(SDL_GetModState() | KMOD_CTRL); SDL_SetModState(SDL_GetModState() | KMOD_CTRL);
if (Config.Swap_buttons == MOD_CTRL && Button_inverter==0)
{
Button_inverter=1;
if (Input_new_mouse_K)
{
Input_new_mouse_K ^= 3; // Flip bits 0 and 1
return Move_cursor_with_constraints();
}
}
return 0; return 0;
} }
if (event.button == Joybutton_alt) if (event.button == Joybutton_alt)
{ {
SDL_SetModState(SDL_GetModState() | (KMOD_ALT|KMOD_META)); SDL_SetModState(SDL_GetModState() | (KMOD_ALT|KMOD_META));
if (Config.Swap_buttons == MOD_ALT && Button_inverter==0)
{
Button_inverter=1;
if (Input_new_mouse_K)
{
Input_new_mouse_K ^= 3; // Flip bits 0 and 1
return Move_cursor_with_constraints();
}
}
return 0; return 0;
} }
if (event.button == Joybutton_left_click) if (event.button == Joybutton_left_click)
{ {
Input_new_mouse_K=1; Input_new_mouse_K = Button_inverter ? 2 : 1;
return Move_cursor_with_constraints(); return Move_cursor_with_constraints();
} }
if (event.button == Joybutton_right_click) if (event.button == Joybutton_right_click)
{ {
Input_new_mouse_K=2; Input_new_mouse_K = Button_inverter ? 1 : 2;
return Move_cursor_with_constraints(); return Move_cursor_with_constraints();
} }
#ifdef __GP2X__
switch(event.button) switch(event.button)
{ {
case GP2X_BUTTON_UP: #ifdef JOY_BUTTON_UP
case JOY_BUTTON_UP:
Directional_up=1; Directional_up=1;
break; break;
case GP2X_BUTTON_UPRIGHT: #endif
#ifdef JOY_BUTTON_UPRIGHT
case JOY_BUTTON_UPRIGHT:
Directional_up_right=1; Directional_up_right=1;
break; break;
case GP2X_BUTTON_RIGHT: #endif
#ifdef JOY_BUTTON_RIGHT
case JOY_BUTTON_RIGHT:
Directional_right=1; Directional_right=1;
break; break;
case GP2X_BUTTON_DOWNRIGHT: #endif
#ifdef JOY_BUTTON_DOWNRIGHT
case JOY_BUTTON_DOWNRIGHT:
Directional_down_right=1; Directional_down_right=1;
break; break;
case GP2X_BUTTON_DOWN: #endif
#ifdef JOY_BUTTON_DOWN
case JOY_BUTTON_DOWN:
Directional_down=1; Directional_down=1;
break; break;
case GP2X_BUTTON_DOWNLEFT: #endif
#ifdef JOY_BUTTON_DOWNLEFT
case JOY_BUTTON_DOWNLEFT:
Directional_down_left=1; Directional_down_left=1;
break; break;
case GP2X_BUTTON_LEFT: #endif
#ifdef JOY_BUTTON_LEFT
case JOY_BUTTON_LEFT:
Directional_left=1; Directional_left=1;
break; break;
case GP2X_BUTTON_UPLEFT: #endif
#ifdef JOY_BUTTON_UPLEFT
case JOY_BUTTON_UPLEFT:
Directional_up_left=1; Directional_up_left=1;
break; break;
#endif
default: default:
break; break;
} }
#endif
Key = (KEY_JOYBUTTON+event.button)|Key_modifiers(SDL_GetModState()); Key = (KEY_JOYBUTTON+event.button)|Key_modifiers(SDL_GetModState());
// TODO: systeme de répétition // TODO: systeme de répétition
@ -527,58 +706,75 @@ int Handle_joystick_release(SDL_JoyButtonEvent event)
return Move_cursor_with_constraints(); return Move_cursor_with_constraints();
} }
#ifdef __GP2X__
switch(event.button) switch(event.button)
{ {
case GP2X_BUTTON_UP: #ifdef JOY_BUTTON_UP
Directional_up=0; case JOY_BUTTON_UP:
Directional_up=1;
break; break;
case GP2X_BUTTON_UPRIGHT: #endif
Directional_up_right=0; #ifdef JOY_BUTTON_UPRIGHT
case JOY_BUTTON_UPRIGHT:
Directional_up_right=1;
break; break;
case GP2X_BUTTON_RIGHT: #endif
Directional_right=0; #ifdef JOY_BUTTON_RIGHT
case JOY_BUTTON_RIGHT:
Directional_right=1;
break; break;
case GP2X_BUTTON_DOWNRIGHT: #endif
Directional_down_right=0; #ifdef JOY_BUTTON_DOWNRIGHT
case JOY_BUTTON_DOWNRIGHT:
Directional_down_right=1;
break; break;
case GP2X_BUTTON_DOWN: #endif
Directional_down=0; #ifdef JOY_BUTTON_DOWN
case JOY_BUTTON_DOWN:
Directional_down=1;
break; break;
case GP2X_BUTTON_DOWNLEFT: #endif
Directional_down_left=0; #ifdef JOY_BUTTON_DOWNLEFT
case JOY_BUTTON_DOWNLEFT:
Directional_down_left=1;
break; break;
case GP2X_BUTTON_LEFT: #endif
Directional_left=0; #ifdef JOY_BUTTON_LEFT
case JOY_BUTTON_LEFT:
Directional_left=1;
break; break;
case GP2X_BUTTON_UPLEFT: #endif
Directional_up_left=0; #ifdef JOY_BUTTON_UPLEFT
case JOY_BUTTON_UPLEFT:
Directional_up_left=1;
break;
#endif
default:
break; break;
} }
#endif
return Move_cursor_with_constraints(); return Move_cursor_with_constraints();
} }
void Handle_joystick_movement(SDL_JoyAxisEvent event) void Handle_joystick_movement(SDL_JoyAxisEvent event)
{ {
if (event.axis==0) // X if (event.axis==JOYSTICK_AXIS_X)
{ {
Directional_right=Directional_left=0; Directional_right=Directional_left=0;
if (event.value<-1000) if (event.value<-JOYSTICK_THRESHOLD)
{ {
Directional_left=1; Directional_left=1;
} }
else if (event.value>1000) else if (event.value>JOYSTICK_THRESHOLD)
Directional_right=1; Directional_right=1;
} }
else if (event.axis==1) // Y else if (event.axis==JOYSTICK_AXIS_Y)
{ {
Directional_up=Directional_down=0; Directional_up=Directional_down=0;
if (event.value<-1000) if (event.value<-JOYSTICK_THRESHOLD)
{ {
Directional_up=1; Directional_up=1;
} }
else if (event.value>1000) else if (event.value>JOYSTICK_THRESHOLD)
Directional_down=1; Directional_down=1;
} }
} }
@ -616,138 +812,222 @@ int Cursor_displace(short delta_x, short delta_y)
return Move_cursor_with_constraints(); return Move_cursor_with_constraints();
} }
// This function is the acceleration profile for directional (digital) cursor
// controllers.
int Directional_acceleration(int msec)
{
const int initial_delay = 250;
const int linear_factor = 200;
const int accel_factor = 10000;
// At beginning there is 1 pixel move, then nothing for N milliseconds
if (msec<initial_delay)
return 1;
// After that, position over time is generally y = ax²+bx+c
// a = 1/accel_factor
// b = 1/linear_factor
// c = 1
return 1+(msec-initial_delay+linear_factor)/linear_factor+(msec-initial_delay)*(msec-initial_delay)/accel_factor;
}
// Main input handling function // Main input handling function
int Get_input(void) int Get_input(int sleep_time)
{ {
SDL_Event event; SDL_Event event;
int user_feedback_required = 0; // Flag qui indique si on doit arrêter de traiter les évènements ou si on peut enchainer int user_feedback_required = 0; // Flag qui indique si on doit arrêter de traiter les évènements ou si on peut enchainer
// Commit any pending screen update.
// This is done in this function because it's called after reading
// some user input.
Flush_update();
Color_cycling(NULL);
Key_ANSI = 0; Key_ANSI = 0;
Key = 0; Key = 0;
Mouse_moved=0; Mouse_moved=0;
Input_new_mouse_X = Mouse_X; Input_new_mouse_X = Mouse_X;
Input_new_mouse_Y = Mouse_Y; Input_new_mouse_Y = Mouse_Y;
Input_new_mouse_K = Mouse_K;
// Not using SDL_PollEvent() because every call polls the input
// device. In some cases such as high-sensitivity mouse or cheap
// digital joypad, every call will see something subtly different in
// the state of the device, and thus it will enqueue a new event.
// The result is that the queue will never empty !!!
// Get new events from input devices.
SDL_PumpEvents();
// Process as much events as possible without redrawing the screen. // Process as much events as possible without redrawing the screen.
// This mostly allows us to merge mouse events for people with an high // This mostly allows us to merge mouse events for people with an high
// resolution mouse // resolution mouse
while( (!user_feedback_required) && SDL_PollEvent(&event)) // Try to cumulate for a full VBL except if there is a required feedback while(!user_feedback_required && SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_ALLEVENTS)==1)
{ {
switch(event.type) switch(event.type)
{ {
case SDL_VIDEORESIZE: case SDL_VIDEORESIZE:
Handle_window_resize(event.resize); Handle_window_resize(event.resize);
user_feedback_required = 1; user_feedback_required = 1;
break; break;
case SDL_QUIT: case SDL_QUIT:
Handle_window_exit(event.quit); Handle_window_exit(event.quit);
user_feedback_required = 1; user_feedback_required = 1;
break; break;
case SDL_MOUSEMOTION: case SDL_MOUSEMOTION:
user_feedback_required = Handle_mouse_move(event.motion); user_feedback_required = Handle_mouse_move(event.motion);
break; break;
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
Handle_mouse_click(event.button); Handle_mouse_click(event.button);
user_feedback_required = 1; user_feedback_required = 1;
break; break;
case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONUP:
Handle_mouse_release(event.button); Handle_mouse_release(event.button);
user_feedback_required = 1; user_feedback_required = 1;
break; break;
case SDL_KEYDOWN: case SDL_KEYDOWN:
Handle_key_press(event.key); Handle_key_press(event.key);
user_feedback_required = 1; user_feedback_required = 1;
break; break;
case SDL_KEYUP: case SDL_KEYUP:
Handle_key_release(event.key); Handle_key_release(event.key);
break; break;
// Start of Joystik handling // Start of Joystik handling
#ifdef USE_JOYSTICK #ifdef USE_JOYSTICK
case SDL_JOYBUTTONUP: case SDL_JOYBUTTONUP:
Handle_joystick_release(event.jbutton); Handle_joystick_release(event.jbutton);
user_feedback_required = 1; user_feedback_required = 1;
break; break;
case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONDOWN:
Handle_joystick_press(event.jbutton); Handle_joystick_press(event.jbutton);
user_feedback_required = 1; user_feedback_required = 1;
break; break;
case SDL_JOYAXISMOTION: case SDL_JOYAXISMOTION:
Handle_joystick_movement(event.jaxis); Handle_joystick_movement(event.jaxis);
break; break;
#endif #endif
// End of Joystick handling // End of Joystick handling
default: case SDL_SYSWMEVENT:
// DEBUG("Unhandled SDL event number : ",event.type); #ifdef __WIN32__
break; if(event.syswm.msg->msg == WM_DROPFILES)
} {
int file_count;
HDROP hdrop = (HDROP)(event.syswm.msg->wParam);
if((file_count = DragQueryFile(hdrop,(UINT)-1,(LPTSTR) NULL ,(UINT) 0)) > 0)
{
long len;
// Query filename length
len = DragQueryFile(hdrop,0 ,NULL ,0);
if (len)
{
Drop_file_name=calloc(len+1,1);
if (Drop_file_name)
{
if (DragQueryFile(hdrop,0 ,(LPTSTR) Drop_file_name ,(UINT) MAX_PATH))
{
// Success
}
else
{
free(Drop_file_name);
// Don't report name copy error
}
}
else
{
// Don't report alloc error (for a file name? :/ )
}
}
else
{
// Don't report weird Windows error
}
}
else
{
// Drop of zero files. Thanks for the information, Bill.
}
}
#endif
break;
default:
//DEBUG("Unhandled SDL event number : ",event.type);
break;
}
} }
// Directional controller // Directional controller
if (!(Directional_up||Directional_up_right||Directional_right|| if (!(Directional_up||Directional_up_right||Directional_right||
Directional_down_right||Directional_down||Directional_down_left|| Directional_down_right||Directional_down||Directional_down_left||
Directional_left||Directional_up_left)) Directional_left||Directional_up_left||Directional_emulated_up||
Directional_emulated_right||Directional_emulated_down||
Directional_emulated_left))
{ {
Directional_delay=-1; Directional_first_move=0;
Directional_last_move=SDL_GetTicks();
} }
else else
{ {
long time_now; long time_now;
int step=0;
time_now=SDL_GetTicks(); time_now=SDL_GetTicks();
if (time_now>Directional_last_move+Directional_delay) if (Directional_first_move==0)
{ {
// Speed parameters, acceleration etc. are here Directional_first_move=time_now;
if (Directional_delay==-1) step=1;
{ }
Directional_delay=150; else
Directional_step=16; {
} // Compute how much the cursor has moved since last call.
else if (Directional_delay==150) // This tries to make smooth cursor movement
Directional_delay=40; // no matter the frequency of calls to Get_input()
else if (Directional_delay!=0) step =
Directional_delay=Directional_delay*8/10; Directional_acceleration(time_now - Directional_first_move) -
else if (Directional_step<16*4) Directional_acceleration(Directional_last_move - Directional_first_move);
Directional_step++;
Directional_last_move = time_now;
// Clip speed at 3 pixel per visible frame.
if (step > 3)
step=3;
}
Directional_last_move = time_now;
if (step)
{
// Directional controller UP // Directional controller UP
if ((Directional_up||Directional_up_left||Directional_up_right) && if ((Directional_up||Directional_emulated_up||Directional_up_left||Directional_up_right) &&
!(Directional_down_right||Directional_down||Directional_down_left)) !(Directional_down_right||Directional_down||Directional_emulated_down||Directional_down_left))
{ {
Cursor_displace(0, -Directional_step/16); Cursor_displace(0, -step);
} }
// Directional controller RIGHT // Directional controller RIGHT
if ((Directional_up_right||Directional_right||Directional_down_right) && if ((Directional_up_right||Directional_right||Directional_emulated_right||Directional_down_right) &&
!(Directional_down_left||Directional_left||Directional_up_left)) !(Directional_down_left||Directional_left||Directional_emulated_left||Directional_up_left))
{ {
Cursor_displace(Directional_step/16,0); Cursor_displace(step,0);
} }
// Directional controller DOWN // Directional controller DOWN
if ((Directional_down_right||Directional_down||Directional_down_left) && if ((Directional_down_right||Directional_down||Directional_emulated_down||Directional_down_left) &&
!(Directional_up_left||Directional_up||Directional_up_right)) !(Directional_up_left||Directional_up||Directional_emulated_up||Directional_up_right))
{ {
Cursor_displace(0, Directional_step/16); Cursor_displace(0, step);
} }
// Directional controller LEFT // Directional controller LEFT
if ((Directional_down_left||Directional_left||Directional_up_left) && if ((Directional_down_left||Directional_left||Directional_emulated_left||Directional_up_left) &&
!(Directional_up_right||Directional_right||Directional_down_right)) !(Directional_up_right||Directional_right||Directional_emulated_right||Directional_down_right))
{ {
Cursor_displace(-Directional_step/16,0); Cursor_displace(-step,0);
} }
} }
} }
@ -757,14 +1037,15 @@ int Get_input(void)
{ {
Compute_paintbrush_coordinates(); Compute_paintbrush_coordinates();
Display_cursor(); Display_cursor();
return 1;
} }
// Commit any pending screen update. if (user_feedback_required)
// This is done in this function because it's called after reading return 1;
// some user input.
Flush_update();
// Nothing significant happened
return (Mouse_moved!=0) || user_feedback_required; if (sleep_time)
SDL_Delay(sleep_time);
return 0;
} }
void Adjust_mouse_sensitivity(word fullscreen) void Adjust_mouse_sensitivity(word fullscreen)
@ -796,3 +1077,74 @@ void Set_mouse_position(void)
Mouse_virtual_y_position = 12*Mouse_Y*Pixel_height; Mouse_virtual_y_position = 12*Mouse_Y*Pixel_height;
} }
} }
int Color_cycling(__attribute__((unused)) void* useless)
{
static byte offset[16];
int i, color;
static SDL_Color PaletteSDL[256];
int changed; // boolean : true if the palette needs a change in this tick.
long now;
static long start=0;
if (start==0)
{
// First run
start = SDL_GetTicks();
return 1;
}
if (!Allow_colorcycling || !Cycling_mode)
return 1;
now = SDL_GetTicks();
changed=0;
// Check all cycles for a change at this tick
for (i=0; i<16; i++)
{
int len;
len=Main_backups->Pages->Gradients->Range[i].End-Main_backups->Pages->Gradients->Range[i].Start+1;
if (len>1 && Main_backups->Pages->Gradients->Range[i].Speed)
{
int new_offset;
new_offset=(now-start)/(int)(1000.0/(Main_backups->Pages->Gradients->Range[i].Speed*0.2856)) % len;
if (!Main_backups->Pages->Gradients->Range[i].Inverse)
new_offset=len - new_offset;
if (new_offset!=offset[i])
changed=1;
offset[i]=new_offset;
}
}
if (changed)
{
// Initialize the palette
for(color=0;color<256;color++)
{
PaletteSDL[color].r=Main_palette[color].R;
PaletteSDL[color].g=Main_palette[color].G;
PaletteSDL[color].b=Main_palette[color].B;
}
for (i=0; i<16; i++)
{
int len;
len=Main_backups->Pages->Gradients->Range[i].End-Main_backups->Pages->Gradients->Range[i].Start+1;
if (len>1 && Main_backups->Pages->Gradients->Range[i].Speed)
{
for(color=Main_backups->Pages->Gradients->Range[i].Start;color<=Main_backups->Pages->Gradients->Range[i].End;color++)
{
PaletteSDL[color].r=Main_palette[Main_backups->Pages->Gradients->Range[i].Start+((color-Main_backups->Pages->Gradients->Range[i].Start+offset[i])%len)].R;
PaletteSDL[color].g=Main_palette[Main_backups->Pages->Gradients->Range[i].Start+((color-Main_backups->Pages->Gradients->Range[i].Start+offset[i])%len)].G;
PaletteSDL[color].b=Main_palette[Main_backups->Pages->Gradients->Range[i].Start+((color-Main_backups->Pages->Gradients->Range[i].Start+offset[i])%len)].B;
}
}
}
SDL_SetPalette(Screen_SDL, SDL_PHYSPAL | SDL_LOGPAL, PaletteSDL,0,256);
}
return 0;
}

View File

@ -33,11 +33,14 @@
/// The latest input variables are held in ::Key, ::Key_ANSI, ::Mouse_X, ::Mouse_Y, ::Mouse_K. /// The latest input variables are held in ::Key, ::Key_ANSI, ::Mouse_X, ::Mouse_Y, ::Mouse_K.
/// Note that ::Key and ::Key_ANSI are not persistent, they will be reset to 0 /// Note that ::Key and ::Key_ANSI are not persistent, they will be reset to 0
/// on subsequent calls to ::Get_input(). /// on subsequent calls to ::Get_input().
int Get_input(void); int Get_input(int sleep_time);
/// Returns true if the keycode has been set as a keyboard shortcut for the function. /// Returns true if the keycode has been set as a keyboard shortcut for the function.
int Is_shortcut(word key, word function); int Is_shortcut(word key, word function);
/// Returns true if the function has any shortcut key.
int Has_shortcut(word function);
/// Adjust mouse sensitivity (and actual mouse input mode) /// Adjust mouse sensitivity (and actual mouse input mode)
void Adjust_mouse_sensitivity(word fullscreen); void Adjust_mouse_sensitivity(word fullscreen);
@ -56,3 +59,8 @@ extern int Snap_axis;
extern int Snap_axis_origin_X; extern int Snap_axis_origin_X;
/// For the :Snap_axis mode, sets the origin's point (in image coordinates) /// For the :Snap_axis mode, sets the origin's point (in image coordinates)
extern int Snap_axis_origin_Y; extern int Snap_axis_origin_Y;
///
/// This malloced string is set when a drag-and-drop event
/// brings a file to Grafx2's window.
extern char * Drop_file_name;

View File

@ -2,6 +2,7 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
@ -32,14 +33,24 @@
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#if defined(__amigaos4__) #if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
#include <proto/dos.h> #include <proto/dos.h>
#include <sys/types.h>
#include <dirent.h> #include <dirent.h>
#define isHidden(x) (0)
#elif defined(__WIN32__) #elif defined(__WIN32__)
#include <dirent.h> #include <dirent.h>
#include <windows.h> #include <windows.h>
//#include <commdlg.h>
#define isHidden(x) (GetFileAttributesA((x)->d_name)&FILE_ATTRIBUTE_HIDDEN)
#elif defined(__MINT__)
#include <mint/osbind.h>
#include <mint/sysbind.h>
#include <dirent.h>
#define isHidden(x) (0)
#else #else
#include <dirent.h> #include <dirent.h>
#define isHidden(x) ((x)->d_name[0]=='.')
#endif #endif
#include "struct.h" #include "struct.h"
@ -276,6 +287,38 @@ void For_each_file(const char * directory_name, void Callback(const char *))
closedir(current_directory); closedir(current_directory);
} }
/// Scans a directory, calls Callback for each file or directory in it,
void For_each_directory_entry(const char * directory_name, void Callback(const char *, byte is_file, byte is_directory, byte is_hidden))
{
// Pour scan de répertoire
DIR* current_directory; //Répertoire courant
struct dirent* entry; // Structure de lecture des éléments
char full_filename[MAX_PATH_CHARACTERS];
int filename_position;
strcpy(full_filename, directory_name);
current_directory=opendir(directory_name);
if(current_directory == NULL) return; // Répertoire invalide ...
filename_position = strlen(full_filename);
if (filename_position==0 || strcmp(full_filename+filename_position-1,PATH_SEPARATOR))
{
strcat(full_filename, PATH_SEPARATOR);
filename_position = strlen(full_filename);
}
while ((entry=readdir(current_directory)))
{
struct stat Infos_enreg;
strcpy(&full_filename[filename_position], entry->d_name);
stat(full_filename,&Infos_enreg);
Callback(
full_filename,
S_ISREG(Infos_enreg.st_mode),
S_ISDIR(Infos_enreg.st_mode),
isHidden(entry)?1:0);
}
closedir(current_directory);
}
void Get_full_filename(char * output_name, char * file_name, char * directory_name) void Get_full_filename(char * output_name, char * file_name, char * directory_name)
{ {
strcpy(output_name,directory_name); strcpy(output_name,directory_name);
@ -299,7 +342,7 @@ int Lock_file_handle = -1;
byte Create_lock_file(const char *file_directory) byte Create_lock_file(const char *file_directory)
{ {
#ifdef __amigaos__ #if defined (__amigaos__)||(__AROS__)
#warning "Missing code for your platform, please check and correct!" #warning "Missing code for your platform, please check and correct!"
#else #else
char lock_filename[MAX_PATH_CHARACTERS]; char lock_filename[MAX_PATH_CHARACTERS];
@ -336,7 +379,7 @@ byte Create_lock_file(const char *file_directory)
return -1; return -1;
} }
#endif #endif
#endif // __amigaos__ #endif // __amigaos__ or __AROS__
return 0; return 0;
} }

View File

@ -2,6 +2,7 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
@ -71,6 +72,8 @@ char * Find_last_slash(const char * str);
#if defined(__WIN32__) #if defined(__WIN32__)
#define PATH_SEPARATOR "\\" #define PATH_SEPARATOR "\\"
#elif defined(__MINT__)
#define PATH_SEPARATOR "\\"
#else #else
#define PATH_SEPARATOR "/" #define PATH_SEPARATOR "/"
#endif #endif
@ -90,6 +93,10 @@ int Directory_exists(char * directory);
/// Scans a directory, calls Callback for each file in it, /// Scans a directory, calls Callback for each file in it,
void For_each_file(const char * directory_name, void Callback(const char *)); void For_each_file(const char * directory_name, void Callback(const char *));
/// Scans a directory, calls Callback for each file or directory in it,
void For_each_directory_entry(const char * directory_name, void Callback(const char *, byte is_file, byte is_directory, byte is_hidden));
/// ///
/// Creates a fully qualified name from a directory and filename. /// Creates a fully qualified name from a directory and filename.
/// The point is simply to insert a PATH_SEPARATOR when needed. /// The point is simply to insert a PATH_SEPARATOR when needed.

View File

@ -2,6 +2,7 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2010 Alexander Filyanov
Copyright 2009 Franck Charlet Copyright 2009 Franck Charlet
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
@ -465,38 +466,93 @@ const char * Key_name(word key)
key=key & ~(MOD_CTRL|MOD_ALT|MOD_SHIFT); key=key & ~(MOD_CTRL|MOD_ALT|MOD_SHIFT);
if (key>=KEY_JOYBUTTON && key<=KEY_JOYBUTTON+18) // 99 is only a sanity check
if (key>=KEY_JOYBUTTON && key<=KEY_JOYBUTTON+99)
{ {
#ifdef __GP2X__
char *button_name; char *button_name;
switch(key-KEY_JOYBUTTON) switch(key-KEY_JOYBUTTON)
{ {
case GP2X_BUTTON_UP: button_name="[UP]"; break; #ifdef JOY_BUTTON_UP
case GP2X_BUTTON_DOWN: button_name="[DOWN]"; break; case JOY_BUTTON_UP: button_name="[UP]"; break;
case GP2X_BUTTON_LEFT: button_name="[LEFT]"; break; #endif
case GP2X_BUTTON_RIGHT: button_name="[RIGHT]"; break; #ifdef JOY_BUTTON_DOWN
case GP2X_BUTTON_UPLEFT: button_name="[UP-LEFT]"; break; case JOY_BUTTON_DOWN: button_name="[DOWN]"; break;
case GP2X_BUTTON_UPRIGHT: button_name="[UP-RIGHT]"; break; #endif
case GP2X_BUTTON_DOWNLEFT: button_name="[DOWN-LEFT]"; break; #ifdef JOY_BUTTON_LEFT
case GP2X_BUTTON_DOWNRIGHT: button_name="[DOWN-RIGHT]"; break; case JOY_BUTTON_LEFT: button_name="[LEFT]"; break;
case GP2X_BUTTON_CLICK: button_name="[CLICK]"; break; #endif
case GP2X_BUTTON_A: button_name="[A]"; break; #ifdef JOY_BUTTON_RIGHT
case GP2X_BUTTON_B: button_name="[B]"; break; case JOY_BUTTON_RIGHT: button_name="[RIGHT]"; break;
case GP2X_BUTTON_X: button_name="[X]"; break; #endif
case GP2X_BUTTON_Y: button_name="[Y]"; break; #ifdef JOY_BUTTON_UPLEFT
case GP2X_BUTTON_L: button_name="[L]"; break; case JOY_BUTTON_UPLEFT: button_name="[UP-LEFT]"; break;
case GP2X_BUTTON_R: button_name="[R]"; break; #endif
case GP2X_BUTTON_START: button_name="[START]"; break; #ifdef JOY_BUTTON_UPRIGHT
case GP2X_BUTTON_SELECT: button_name="[SELECT]"; break; case JOY_BUTTON_UPRIGHT: button_name="[UP-RIGHT]"; break;
case GP2X_BUTTON_VOLUP: button_name="[VOL UP]"; break; #endif
case GP2X_BUTTON_VOLDOWN: button_name="[VOL DOWN]"; break; #ifdef JOY_BUTTON_DOWNLEFT
default: sprintf(buffer+strlen(buffer), "[B%d]", key);return buffer; case JOY_BUTTON_DOWNLEFT: button_name="[DOWN-LEFT]"; break;
#endif
#ifdef JOY_BUTTON_DOWNRIGHT
case JOY_BUTTON_DOWNRIGHT: button_name="[DOWN-RIGHT]"; break;
#endif
#ifdef JOY_BUTTON_CLICK
case JOY_BUTTON_CLICK: button_name="[CLICK]"; break;
#endif
#ifdef JOY_BUTTON_A
case JOY_BUTTON_A: button_name="[A]"; break;
#endif
#ifdef JOY_BUTTON_B
case JOY_BUTTON_B: button_name="[B]"; break;
#endif
#ifdef JOY_BUTTON_X
case JOY_BUTTON_X: button_name="[X]"; break;
#endif
#ifdef JOY_BUTTON_Y
case JOY_BUTTON_Y: button_name="[Y]"; break;
#endif
#ifdef JOY_BUTTON_L
case JOY_BUTTON_L: button_name="[L]"; break;
#endif
#ifdef JOY_BUTTON_R
case JOY_BUTTON_R: button_name="[R]"; break;
#endif
#ifdef JOY_BUTTON_START
case JOY_BUTTON_START: button_name="[START]"; break;
#endif
#ifdef JOY_BUTTON_SELECT
case JOY_BUTTON_SELECT: button_name="[SELECT]"; break;
#endif
#ifdef JOY_BUTTON_VOLUP
case JOY_BUTTON_VOLUP: button_name="[VOL UP]"; break;
#endif
#ifdef JOY_BUTTON_VOLDOWN
case JOY_BUTTON_VOLDOWN: button_name="[VOL DOWN]"; break;
#endif
#ifdef JOY_BUTTON_MENU
case JOY_BUTTON_MENU: button_name="[MENU]"; break;
#endif
#ifdef JOY_BUTTON_HOME
case JOY_BUTTON_HOME: button_name="[HOME]"; break;
#endif
#ifdef JOY_BUTTON_HOLD
case JOY_BUTTON_HOLD: button_name="[HOLD]"; break;
#endif
#ifdef JOY_BUTTON_I
case JOY_BUTTON_I: button_name="[BUTTON I]"; break;
#endif
#ifdef JOY_BUTTON_II
case JOY_BUTTON_II: button_name="[BUTTON II]"; break;
#endif
#ifdef JOY_BUTTON_JOY
case JOY_BUTTON_JOY: button_name="[THUMB JOY]"; break;
#endif
default: sprintf(buffer+strlen(buffer), "[B%d]", key-KEY_JOYBUTTON);return buffer;
} }
strcat(buffer,button_name); strcat(buffer,button_name);
#else
sprintf(buffer+strlen(buffer), "[B%d]", key-KEY_JOYBUTTON);
#endif
return buffer; return buffer;
} }

View File

@ -2,6 +2,8 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2010 Alexander Filyanov
Copyright 2009 Petter Lindquist Copyright 2009 Petter Lindquist
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet Copyright 2008 Franck Charlet
@ -47,6 +49,8 @@
#include "struct.h" #include "struct.h"
#include "windows.h" #include "windows.h"
#include "engine.h" #include "engine.h"
#include "brush.h"
#include "setup.h"
// -- PKM ------------------------------------------------------------------- // -- PKM -------------------------------------------------------------------
void Test_PKM(T_IO_Context *); void Test_PKM(T_IO_Context *);
@ -121,6 +125,10 @@ void Save_C64(T_IO_Context *);
// -- SCR (Amstrad CPC) // -- SCR (Amstrad CPC)
void Save_SCR(T_IO_Context *); void Save_SCR(T_IO_Context *);
// -- XPM (X PixMap)
// Loading is done through SDL_Image
void Save_XPM(T_IO_Context*);
// -- PNG ------------------------------------------------------------------- // -- PNG -------------------------------------------------------------------
#ifndef __no_pnglib__ #ifndef __no_pnglib__
void Test_PNG(T_IO_Context *); void Test_PNG(T_IO_Context *);
@ -133,7 +141,7 @@ void Save_PNG(T_IO_Context *);
void Load_SDL_Image(T_IO_Context *); void Load_SDL_Image(T_IO_Context *);
// ENUM Name TestFunc LoadFunc SaveFunc PalOnly Comment Layers Ext Exts // ENUM Name TestFunc LoadFunc SaveFunc PalOnly Comment Layers Ext Exts
T_Format File_formats[NB_KNOWN_FORMATS] = { T_Format File_formats[] = {
{FORMAT_ALL_IMAGES, "(all)", NULL, NULL, NULL, 0, 0, 0, "", "gif;png;bmp;pcx;pkm;lbm;iff;img;sci;scq;scf;scn;sco;pi1;pc1;cel;neo;kcf;pal;c64;koa;koala;fli;bml;cdu;prg;tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"}, {FORMAT_ALL_IMAGES, "(all)", NULL, NULL, NULL, 0, 0, 0, "", "gif;png;bmp;pcx;pkm;lbm;iff;img;sci;scq;scf;scn;sco;pi1;pc1;cel;neo;kcf;pal;c64;koa;koala;fli;bml;cdu;prg;tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"},
{FORMAT_ALL_FILES, "(*.*)", NULL, NULL, NULL, 0, 0, 0, "", "*"}, {FORMAT_ALL_FILES, "(*.*)", NULL, NULL, NULL, 0, 0, 0, "", "*"},
{FORMAT_GIF, " gif", Test_GIF, Load_GIF, Save_GIF, 0, 1, 1, "gif", "gif"}, {FORMAT_GIF, " gif", Test_GIF, Load_GIF, Save_GIF, 0, 1, 1, "gif", "gif"},
@ -143,7 +151,7 @@ T_Format File_formats[NB_KNOWN_FORMATS] = {
{FORMAT_BMP, " bmp", Test_BMP, Load_BMP, Save_BMP, 0, 0, 0, "bmp", "bmp"}, {FORMAT_BMP, " bmp", Test_BMP, Load_BMP, Save_BMP, 0, 0, 0, "bmp", "bmp"},
{FORMAT_PCX, " pcx", Test_PCX, Load_PCX, Save_PCX, 0, 0, 0, "pcx", "pcx"}, {FORMAT_PCX, " pcx", Test_PCX, Load_PCX, Save_PCX, 0, 0, 0, "pcx", "pcx"},
{FORMAT_PKM, " pkm", Test_PKM, Load_PKM, Save_PKM, 0, 1, 0, "pkm", "pkm"}, {FORMAT_PKM, " pkm", Test_PKM, Load_PKM, Save_PKM, 0, 1, 0, "pkm", "pkm"},
{FORMAT_LBM, " lbm", Test_LBM, Load_LBM, Save_LBM, 0, 0, 0, "lbm", "lbm;iff"}, {FORMAT_LBM, " lbm", Test_LBM, Load_LBM, Save_LBM, 0, 0, 0, "lbm", "lbm;iff;ilbm"},
{FORMAT_IMG, " img", Test_IMG, Load_IMG, Save_IMG, 0, 0, 0, "img", "img"}, {FORMAT_IMG, " img", Test_IMG, Load_IMG, Save_IMG, 0, 0, 0, "img", "img"},
{FORMAT_SCx, " sc?", Test_SCx, Load_SCx, Save_SCx, 0, 0, 0, "sc?", "sci;scq;scf;scn;sco"}, {FORMAT_SCx, " sc?", Test_SCx, Load_SCx, Save_SCx, 0, 0, 0, "sc?", "sci;scq;scf;scn;sco"},
{FORMAT_PI1, " pi1", Test_PI1, Load_PI1, Save_PI1, 0, 0, 0, "pi1", "pi1"}, {FORMAT_PI1, " pi1", Test_PI1, Load_PI1, Save_PI1, 0, 0, 0, "pi1", "pi1"},
@ -154,9 +162,16 @@ T_Format File_formats[NB_KNOWN_FORMATS] = {
{FORMAT_PAL, " pal", Test_PAL, Load_PAL, Save_PAL, 1, 0, 0, "pal", "pal"}, {FORMAT_PAL, " pal", Test_PAL, Load_PAL, Save_PAL, 1, 0, 0, "pal", "pal"},
{FORMAT_C64, " c64", Test_C64, Load_C64, Save_C64, 0, 1, 0, "c64", "c64;koa;koala;fli;bml;cdu;prg"}, {FORMAT_C64, " c64", Test_C64, Load_C64, Save_C64, 0, 1, 0, "c64", "c64;koa;koala;fli;bml;cdu;prg"},
{FORMAT_SCR, " cpc", NULL, NULL, Save_SCR, 0, 0, 0, "cpc", "cpc;scr"}, {FORMAT_SCR, " cpc", NULL, NULL, Save_SCR, 0, 0, 0, "cpc", "cpc;scr"},
{FORMAT_XPM, " xpm", NULL, NULL, Save_XPM, 0, 0, 0, "xpm", "xpm"},
{FORMAT_MISC,"misc.",NULL, NULL, NULL, 0, 0, 0, "", "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"}, {FORMAT_MISC,"misc.",NULL, NULL, NULL, 0, 0, 0, "", "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"},
}; };
/// Total number of known file formats
unsigned int Nb_known_formats(void)
{
return sizeof(File_formats)/sizeof(File_formats[0]);
}
/// Set the color of a pixel (on load) /// Set the color of a pixel (on load)
void Set_pixel(T_IO_Context *context, short x_pos, short y_pos, byte color) void Set_pixel(T_IO_Context *context, short x_pos, short y_pos, byte color)
{ {
@ -180,38 +195,32 @@ void Set_pixel(T_IO_Context *context, short x_pos, short y_pos, byte color)
// Chargement des pixels dans la preview // Chargement des pixels dans la preview
case CONTEXT_PREVIEW: case CONTEXT_PREVIEW:
// Skip pixels of transparent index if : // Skip pixels of transparent index if :
// - It's the first layer, and image has transparent background. // it's a layer above the first one
// - or it's a layer above the first one if (color == context->Transparent_color && context->Current_layer > 0)
if (color == context->Transparent_color && (context->Current_layer > 0 || context->Background_transparent))
break; break;
if (((x_pos % context->Preview_factor_X)==0) && ((y_pos % context->Preview_factor_Y)==0)) if (((x_pos % context->Preview_factor_X)==0) && ((y_pos % context->Preview_factor_Y)==0))
{ {
// Tag the color as 'used'
context->Preview_usage[color]=1;
// Store pixel
if (context->Ratio == PIXEL_WIDE && if (context->Ratio == PIXEL_WIDE &&
Pixel_ratio != PIXEL_WIDE && Pixel_ratio != PIXEL_WIDE &&
Pixel_ratio != PIXEL_WIDE2) Pixel_ratio != PIXEL_WIDE2)
{ {
Pixel(context->Preview_pos_X+(x_pos/context->Preview_factor_X*2), context->Preview_bitmap[x_pos/context->Preview_factor_X*2 + (y_pos/context->Preview_factor_Y)*PREVIEW_WIDTH*Menu_factor_X]=color;
context->Preview_pos_Y+(y_pos/context->Preview_factor_Y), context->Preview_bitmap[x_pos/context->Preview_factor_X*2+1 + (y_pos/context->Preview_factor_Y)*PREVIEW_WIDTH*Menu_factor_X]=color;
color);
Pixel(context->Preview_pos_X+(x_pos/context->Preview_factor_X*2)+1,
context->Preview_pos_Y+(y_pos/context->Preview_factor_Y),
color);
} }
else if (context->Ratio == PIXEL_TALL && else if (context->Ratio == PIXEL_TALL &&
Pixel_ratio != PIXEL_TALL && Pixel_ratio != PIXEL_TALL &&
Pixel_ratio != PIXEL_TALL2) Pixel_ratio != PIXEL_TALL2)
{ {
Pixel(context->Preview_pos_X+(x_pos/context->Preview_factor_X), context->Preview_bitmap[x_pos/context->Preview_factor_X + (y_pos/context->Preview_factor_Y*2)*PREVIEW_WIDTH*Menu_factor_X]=color;
context->Preview_pos_Y+(y_pos/context->Preview_factor_Y*2), context->Preview_bitmap[x_pos/context->Preview_factor_X + (y_pos/context->Preview_factor_Y*2+1)*PREVIEW_WIDTH*Menu_factor_X]=color;
color);
Pixel(context->Preview_pos_X+(x_pos/context->Preview_factor_X),
context->Preview_pos_Y+(y_pos/context->Preview_factor_Y*2)+1,
color);
} }
else else
Pixel(context->Preview_pos_X+(x_pos/context->Preview_factor_X), context->Preview_bitmap[x_pos/context->Preview_factor_X + (y_pos/context->Preview_factor_Y)*PREVIEW_WIDTH*Menu_factor_X]=color;
context->Preview_pos_Y+(y_pos/context->Preview_factor_Y),
color);
} }
break; break;
@ -234,8 +243,6 @@ void Palette_loaded(T_IO_Context *context)
{ {
case CONTEXT_MAIN_IMAGE: case CONTEXT_MAIN_IMAGE:
case CONTEXT_PREVIEW: case CONTEXT_PREVIEW:
Set_palette(context->Palette);
break;
case CONTEXT_BRUSH: case CONTEXT_BRUSH:
case CONTEXT_SURFACE: case CONTEXT_SURFACE:
break; break;
@ -244,66 +251,6 @@ void Palette_loaded(T_IO_Context *context)
switch (context->Type) switch (context->Type)
{ {
case CONTEXT_PREVIEW: case CONTEXT_PREVIEW:
Compute_optimal_menu_colors(context->Palette);
/*
if(
(
context->Palette[MC_Black].R==context->Palette[MC_Dark].R &&
context->Palette[MC_Black].G==context->Palette[MC_Dark].G &&
context->Palette[MC_Black].B==context->Palette[MC_Dark].B
) ||
(
context->Palette[MC_Light].R==context->Palette[MC_Dark].R &&
context->Palette[MC_Light].G==context->Palette[MC_Dark].G &&
context->Palette[MC_Light].B==context->Palette[MC_Dark].B
) ||
(
context->Palette[MC_White].R==context->Palette[MC_Light].R &&
context->Palette[MC_White].G==context->Palette[MC_Light].G &&
context->Palette[MC_White].B==context->Palette[MC_Light].B
)
)
{
// Si on charge une image monochrome, le fileselect ne sera plus visible. Dans ce cas on force quelques couleurs à des valeurs sures
int black =
Main_palette[MC_Black].R +
Main_palette[MC_Black].G +
Main_palette[MC_Black].B;
int white =
Main_palette[MC_White].R +
Main_palette[MC_White].G +
Main_palette[MC_White].B;
//Set_color(MC_Light,(2*white+black)/9,(2*white+black)/9,(2*white+black)/9);
//Set_color(MC_Dark,(2*black+white)/9,(2*black+white)/9,(2*black+white)/9);
Main_palette[MC_Dark].R=(2*black+white)/9;
Main_palette[MC_Dark].G=(2*black+white)/9;
Main_palette[MC_Dark].B=(2*black+white)/9;
Main_palette[MC_Light].R=(2*white+black)/9;
Main_palette[MC_Light].G=(2*white+black)/9;
Main_palette[MC_Light].B=(2*white+black)/9;
Set_palette(Main_palette);
}
*/
Remap_screen_after_menu_colors_change();
// Preview palette
if (Get_fileformat(context->Format)->Palette_only)
{
short index;
if (context->Type == CONTEXT_PREVIEW)
for (index=0; index<256; index++)
Window_rectangle(183+(index/16)*7,95+(index&15)*5,5,5,index);
Update_window_area(183,95,120,80);
}
break;
case CONTEXT_MAIN_IMAGE: case CONTEXT_MAIN_IMAGE:
case CONTEXT_BRUSH: case CONTEXT_BRUSH:
case CONTEXT_SURFACE: case CONTEXT_SURFACE:
@ -336,17 +283,17 @@ void Set_pixel_24b(T_IO_Context *context, short x_pos, short y_pos, byte r, byte
break; break;
case CONTEXT_PREVIEW: case CONTEXT_PREVIEW:
{
if (((x_pos % context->Preview_factor_X)==0) && ((y_pos % context->Preview_factor_Y)==0)) if (((x_pos % context->Preview_factor_X)==0) && ((y_pos % context->Preview_factor_Y)==0))
{ {
color=((r >> 5) << 5) | color=((r >> 5) << 5) |
((g >> 5) << 2) | ((g >> 5) << 2) |
((b >> 6)); ((b >> 6));
Pixel(context->Preview_pos_X+(x_pos/context->Preview_factor_X),
context->Preview_pos_Y+(y_pos/context->Preview_factor_Y), // Tag the color as 'used'
color); context->Preview_usage[color]=1;
}
context->Preview_bitmap[x_pos/context->Preview_factor_X + (y_pos/context->Preview_factor_Y)*PREVIEW_WIDTH*Menu_factor_X]=color;
} }
break; break;
} }
@ -388,6 +335,11 @@ void Pre_load(T_IO_Context *context, short width, short height, long file_size,
// Preview // Preview
case CONTEXT_PREVIEW: case CONTEXT_PREVIEW:
// Préparation du chargement d'une preview: // Préparation du chargement d'une preview:
context->Preview_bitmap=malloc(PREVIEW_WIDTH*PREVIEW_HEIGHT*Menu_factor_X*Menu_factor_Y);
if (!context->Preview_bitmap)
File_error=1;
// Affichage des données "Image size:" // Affichage des données "Image size:"
if ((width<10000) && (height<10000)) if ((width<10000) && (height<10000))
{ {
@ -430,7 +382,8 @@ void Pre_load(T_IO_Context *context, short width, short height, long file_size,
// On efface le commentaire précédent // On efface le commentaire précédent
Window_rectangle(45,70,32*8,8,MC_Light); Window_rectangle(45,70,32*8,8,MC_Light);
// Affichage du commentaire // Affichage du commentaire
Print_in_window(45,70,context->Comment,MC_Black,MC_Light); if (Get_fileformat(format)->Comment)
Print_in_window(45,70,Main_comment,MC_Black,MC_Light);
// Calcul des données nécessaires à l'affichage de la preview: // Calcul des données nécessaires à l'affichage de la preview:
if (ratio == PIXEL_WIDE && if (ratio == PIXEL_WIDE &&
@ -442,8 +395,8 @@ void Pre_load(T_IO_Context *context, short width, short height, long file_size,
Pixel_ratio != PIXEL_TALL2) Pixel_ratio != PIXEL_TALL2)
height*=2; height*=2;
context->Preview_factor_X=Round_div_max(width,122*Menu_factor_X); context->Preview_factor_X=Round_div_max(width,120*Menu_factor_X);
context->Preview_factor_Y=Round_div_max(height, 82*Menu_factor_Y); context->Preview_factor_Y=Round_div_max(height, 80*Menu_factor_Y);
if ( (!Config.Maximize_preview) && (context->Preview_factor_X!=context->Preview_factor_Y) ) if ( (!Config.Maximize_preview) && (context->Preview_factor_X!=context->Preview_factor_Y) )
{ {
@ -457,17 +410,17 @@ void Pre_load(T_IO_Context *context, short width, short height, long file_size,
context->Preview_pos_Y=Window_pos_Y+ 95*Menu_factor_Y; context->Preview_pos_Y=Window_pos_Y+ 95*Menu_factor_Y;
// On nettoie la zone où va s'afficher la preview: // On nettoie la zone où va s'afficher la preview:
Window_rectangle(183,95,120,80,MC_Light); Window_rectangle(183,95,PREVIEW_WIDTH,PREVIEW_HEIGHT,MC_Light);
// Un update pour couvrir les 4 zones: 3 libellés plus le commentaire // Un update pour couvrir les 4 zones: 3 libellés plus le commentaire
Update_window_area(45,48,256,30); Update_window_area(45,48,256,30);
// Zone de preview // Zone de preview
Update_window_area(183,95,120,80); Update_window_area(183,95,PREVIEW_WIDTH,PREVIEW_HEIGHT);
break; break;
// Other loading // Other loading
case CONTEXT_MAIN_IMAGE: case CONTEXT_MAIN_IMAGE:
if (Backup_with_new_dimensions(0,1,width,height)) if (Backup_new_image(1,width,height))
{ {
// La nouvelle page a pu être allouée, elle est pour l'instant pleine // La nouvelle page a pu être allouée, elle est pour l'instant pleine
// de 0s. Elle fait Main_image_width de large. // de 0s. Elle fait Main_image_width de large.
@ -605,7 +558,10 @@ void Load_image(T_IO_Context *context)
{ {
unsigned int index; // index de balayage des formats unsigned int index; // index de balayage des formats
T_Format *format = &(File_formats[2]); // Format du fichier à charger T_Format *format = &(File_formats[2]); // Format du fichier à charger
int i;
// Not sure it's the best place...
context->Color_cycles=0;
// On place par défaut File_error à vrai au cas où on ne sache pas // On place par défaut File_error à vrai au cas où on ne sache pas
// charger le format du fichier: // charger le format du fichier:
@ -622,7 +578,7 @@ void Load_image(T_IO_Context *context)
{ {
// Sinon, on va devoir scanner les différents formats qu'on connait pour // Sinon, on va devoir scanner les différents formats qu'on connait pour
// savoir à quel format est le fichier: // savoir à quel format est le fichier:
for (index=0; index < NB_KNOWN_FORMATS; index++) for (index=0; index < Nb_known_formats(); index++)
{ {
format = Get_fileformat(index); format = Get_fileformat(index);
// Loadable format // Loadable format
@ -714,7 +670,7 @@ void Load_image(T_IO_Context *context)
case CONTEXT_SURFACE: case CONTEXT_SURFACE:
if (Convert_24b_bitmap_to_256(context->Surface->pixels,context->Buffer_image_24b,context->Width,context->Height,context->Palette)) if (Convert_24b_bitmap_to_256(context->Surface->pixels,context->Buffer_image_24b,context->Width,context->Height,context->Palette))
File_error=1; File_error=1;
break; break;
} }
@ -722,11 +678,34 @@ void Load_image(T_IO_Context *context)
free(context->Buffer_image_24b); free(context->Buffer_image_24b);
context->Buffer_image_24b = NULL; context->Buffer_image_24b = NULL;
} }
else if (context->Type == CONTEXT_MAIN_IMAGE)
{
// Non-24b main image: Add menu colors
if (Config.Safety_colors)
{
dword color_usage[256];
memset(color_usage,0,sizeof(color_usage));
if (Count_used_colors(color_usage)<252)
{
int gui_index=0;
int c;
for (c=255; c>=0 && gui_index<4; c--)
{
if (color_usage[c]==0)
{
context->Palette[c]=*Favorite_GUI_color(gui_index);
gui_index++;
}
}
}
}
}
if (context->Type == CONTEXT_MAIN_IMAGE) if (context->Type == CONTEXT_MAIN_IMAGE)
{ {
if ( File_error!=1) if ( File_error!=1)
{ {
Set_palette(context->Palette);
if (format->Palette_only) if (format->Palette_only)
{ {
// Make a backup step // Make a backup step
@ -773,6 +752,21 @@ void Load_image(T_IO_Context *context)
Main_image_width=1; Main_image_width=1;
if (Main_image_height<1) if (Main_image_height<1)
Main_image_height=1; Main_image_height=1;
// Color cyling ranges:
for (i=0; i<16; i++)
Main_backups->Pages->Gradients->Range[i].Speed=0;
for (i=0; i<context->Color_cycles; i++)
{
Main_backups->Pages->Gradients->Range[i].Start=context->Cycle_range[i].Start;
Main_backups->Pages->Gradients->Range[i].End=context->Cycle_range[i].End;
Main_backups->Pages->Gradients->Range[i].Inverse=context->Cycle_range[i].Inverse;
Main_backups->Pages->Gradients->Range[i].Speed=context->Cycle_range[i].Speed;
}
// Comment
strcpy(Main_comment, context->Comment);
} }
} }
else if (File_error!=1) else if (File_error!=1)
@ -791,19 +785,16 @@ void Load_image(T_IO_Context *context)
} }
else if (context->Type == CONTEXT_BRUSH && File_error==0) else if (context->Type == CONTEXT_BRUSH && File_error==0)
{ {
free(Brush);
Brush=context->Buffer_image;
context->Buffer_image = NULL;
Brush_width=context->Width; if (Realloc_brush(context->Width, context->Height, context->Buffer_image, NULL))
Brush_height=context->Height; {
free(Smear_brush);
Smear_brush_width=(Brush_width>MAX_PAINTBRUSH_SIZE)?Brush_width:MAX_PAINTBRUSH_SIZE;
Smear_brush_height=(Brush_height>MAX_PAINTBRUSH_SIZE)?Brush_height:MAX_PAINTBRUSH_SIZE;
Smear_brush=(byte *)malloc(Smear_brush_width*Smear_brush_height);
if (!Smear_brush)
File_error=3; File_error=3;
free(context->Buffer_image);
}
memcpy(Brush_original_palette, context->Palette, sizeof(T_Palette));
Remap_brush();
context->Buffer_image = NULL;
} }
else if (context->Type == CONTEXT_SURFACE) else if (context->Type == CONTEXT_SURFACE)
{ {
@ -822,6 +813,91 @@ void Load_image(T_IO_Context *context)
SDL_SetColors(context->Surface, colors, 0, 256); SDL_SetColors(context->Surface, colors, 0, 256);
} }
} }
else if (context->Type == CONTEXT_PREVIEW
/*&& !context->Buffer_image_24b*/
/*&& !Get_fileformat(context->Format)->Palette_only*/)
{
// Try to adapt the palette to accomodate the GUI.
int c;
int count_unused;
byte unused_color[4];
count_unused=0;
// Try find 4 unused colors and insert good colors there
for (c=255; c>=0 && count_unused<4; c--)
{
if (!context->Preview_usage[c])
{
unused_color[count_unused]=c;
count_unused++;
}
}
// Found! replace them with some favorites
if (count_unused==4)
{
int gui_index;
for (gui_index=0; gui_index<4; gui_index++)
{
context->Palette[unused_color[gui_index]]=*Favorite_GUI_color(gui_index);
}
}
// All preview display is here
// Update palette and screen first
Compute_optimal_menu_colors(context->Palette);
Remap_screen_after_menu_colors_change();
Set_palette(context->Palette);
// Display palette preview
if (Get_fileformat(context->Format)->Palette_only)
{
short index;
if (context->Type == CONTEXT_PREVIEW)
for (index=0; index<256; index++)
Window_rectangle(183+(index/16)*7,95+(index&15)*5,5,5,index);
}
// Display normal image
else if (context->Preview_bitmap)
{
int x_pos,y_pos;
int width,height;
width=context->Width/context->Preview_factor_X;
height=context->Height/context->Preview_factor_Y;
if (context->Ratio == PIXEL_WIDE &&
Pixel_ratio != PIXEL_WIDE &&
Pixel_ratio != PIXEL_WIDE2)
width*=2;
else if (context->Ratio == PIXEL_TALL &&
Pixel_ratio != PIXEL_TALL &&
Pixel_ratio != PIXEL_TALL2)
height*=2;
for (y_pos=0; y_pos<height;y_pos++)
for (x_pos=0; x_pos<width;x_pos++)
{
byte color=context->Preview_bitmap[x_pos+y_pos*PREVIEW_WIDTH*Menu_factor_X];
// Skip transparent if image has transparent background.
if (color == context->Transparent_color && context->Background_transparent)
color=MC_Window;
Pixel(context->Preview_pos_X+x_pos,
context->Preview_pos_Y+y_pos,
color);
}
}
// Refresh modified part
Update_window_area(183,95,PREVIEW_WIDTH,PREVIEW_HEIGHT);
// Preview comment
Print_in_window(45,70,context->Comment,MC_Black,MC_Light);
//Update_window_area(45,70,32*8,8);
}
} }
@ -916,8 +992,10 @@ void Load_SDL_Image(T_IO_Context *context)
} }
else else
{ {
// Hi/Trucolor {
Pre_load(context, surface->w, surface->h, file_size ,FORMAT_ALL_IMAGES, PIXEL_SIMPLE, 1); // Hi/Trucolor
Pre_load(context, surface->w, surface->h, file_size ,FORMAT_ALL_IMAGES, PIXEL_SIMPLE, 1);
}
for (y_pos=0; y_pos<context->Height; y_pos++) for (y_pos=0; y_pos<context->Height; y_pos++)
{ {
@ -938,8 +1016,10 @@ void Load_SDL_Image(T_IO_Context *context)
SDL_FreeSurface(surface); SDL_FreeSurface(surface);
} }
///
/// Load an arbitrary SDL_Surface. /// Load an arbitrary SDL_Surface.
SDL_Surface * Load_surface(char *full_name) /// @param gradients Pass the address of a target T_Gradient_array if you want the gradients, NULL otherwise
SDL_Surface * Load_surface(char *full_name, T_Gradient_array *gradients)
{ {
SDL_Surface * bmp=NULL; SDL_Surface * bmp=NULL;
T_IO_Context context; T_IO_Context context;
@ -948,8 +1028,23 @@ SDL_Surface * Load_surface(char *full_name)
Load_image(&context); Load_image(&context);
if (context.Surface) if (context.Surface)
{
bmp=context.Surface; bmp=context.Surface;
// Caller wants the gradients:
if (gradients != NULL)
{
int i;
memset(gradients, 0, sizeof(T_Gradient_array));
for (i=0; i<context.Color_cycles; i++)
{
gradients->Range[i].Start=context.Cycle_range[i].Start;
gradients->Range[i].End=context.Cycle_range[i].End;
gradients->Range[i].Inverse=context.Cycle_range[i].Inverse;
gradients->Range[i].Speed=context.Cycle_range[i].Speed;
}
}
}
Destroy_context(&context); Destroy_context(&context);
return bmp; return bmp;
@ -1011,10 +1106,12 @@ void Emergency_backup(const char *fname, byte *source, int width, int height, T_
void Image_emergency_backup() void Image_emergency_backup()
{ {
#ifndef NOLAYERS
if (Main_backups && Main_backups->Pages && Main_backups->Pages->Nb_layers == 1) if (Main_backups && Main_backups->Pages && Main_backups->Pages->Nb_layers == 1)
Emergency_backup("a999999.bkp",Main_screen, Main_image_width, Main_image_height, &Main_palette); Emergency_backup(SAFETYBACKUP_PREFIX_A "999999" BACKUP_FILE_EXTENSION,Main_screen, Main_image_width, Main_image_height, &Main_palette);
if (Spare_backups && Spare_backups->Pages && Spare_backups->Pages->Nb_layers == 1) if (Spare_backups && Spare_backups->Pages && Spare_backups->Pages->Nb_layers == 1)
Emergency_backup("b999999.bkp",Spare_visible_image.Image, Spare_image_width, Spare_image_height, &Spare_palette); Emergency_backup(SAFETYBACKUP_PREFIX_B "999999" BACKUP_FILE_EXTENSION,Spare_visible_image.Image, Spare_image_width, Spare_image_height, &Spare_palette);
#endif
} }
T_Format * Get_fileformat(byte format) T_Format * Get_fileformat(byte format)
@ -1022,7 +1119,7 @@ T_Format * Get_fileformat(byte format)
unsigned int i; unsigned int i;
T_Format * safe_default = File_formats; T_Format * safe_default = File_formats;
for (i=0; i < NB_KNOWN_FORMATS; i++) for (i=0; i < Nb_known_formats(); i++)
{ {
if (File_formats[i].Identifier == format) if (File_formats[i].Identifier == format)
return &(File_formats[i]); return &(File_formats[i]);
@ -1041,11 +1138,12 @@ byte Get_pixel(T_IO_Context *context, short x, short y)
return *(context->Target_address + y*context->Pitch + x); return *(context->Target_address + y*context->Pitch + x);
} }
/// Cleans up resources (currently: the 24bit buffer) /// Cleans up resources
void Destroy_context(T_IO_Context *context) void Destroy_context(T_IO_Context *context)
{ {
free(context->Buffer_image_24b); free(context->Buffer_image_24b);
free(context->Buffer_image); free(context->Buffer_image);
free(context->Preview_bitmap);
memset(context, 0, sizeof(T_IO_Context)); memset(context, 0, sizeof(T_IO_Context));
} }
@ -1069,6 +1167,8 @@ void Init_context_backup_image(T_IO_Context * context, char *file_name, char *fi
/// Setup for loading/saving the current main image /// Setup for loading/saving the current main image
void Init_context_layered_image(T_IO_Context * context, char *file_name, char *file_directory) void Init_context_layered_image(T_IO_Context * context, char *file_name, char *file_directory)
{ {
int i;
memset(context, 0, sizeof(T_IO_Context)); memset(context, 0, sizeof(T_IO_Context));
context->Type = CONTEXT_MAIN_IMAGE; context->Type = CONTEXT_MAIN_IMAGE;
@ -1091,6 +1191,18 @@ void Init_context_layered_image(T_IO_Context * context, char *file_name, char *f
context->Target_address=Main_backups->Pages->Image[0]; context->Target_address=Main_backups->Pages->Image[0];
context->Pitch=Main_image_width; context->Pitch=Main_image_width;
// Color cyling ranges:
for (i=0; i<16; i++)
{
if (Main_backups->Pages->Gradients->Range[i].Start!=Main_backups->Pages->Gradients->Range[i].End)
{
context->Cycle_range[context->Color_cycles].Start=Main_backups->Pages->Gradients->Range[i].Start;
context->Cycle_range[context->Color_cycles].End=Main_backups->Pages->Gradients->Range[i].End;
context->Cycle_range[context->Color_cycles].Inverse=Main_backups->Pages->Gradients->Range[i].Inverse;
context->Cycle_range[context->Color_cycles].Speed=Main_backups->Pages->Gradients->Range[i].Speed;
context->Color_cycles++;
}
}
} }
/// Setup for loading/saving the flattened version of current main image /// Setup for loading/saving the flattened version of current main image
@ -1332,8 +1444,13 @@ int Check_recovery(void)
int restored_main; int restored_main;
// First check if can write backups // First check if can write backups
if (Create_lock_file(Config_directory)) #if defined (__MINT__)
//TODO: enable file lock under Freemint only
return 0;
#else
if (Create_lock_file(Config_directory))
return -1; return -1;
#endif
Safety_backup_active=1; Safety_backup_active=1;
@ -1389,7 +1506,7 @@ void Rotate_safety_backups(void)
{ {
// Clear a previous save (rotating saves) // Clear a previous save (rotating saves)
sprintf(deleted_file, "%s%c%6.6d.bkp", sprintf(deleted_file, "%s%c%6.6d" BACKUP_FILE_EXTENSION,
Config_directory, Config_directory,
Main_safety_backup_prefix, Main_safety_backup_prefix,
(Uint32)(Main_safety_number + 1000000l - Rotation_safety_backup) % (Uint32)1000000l); (Uint32)(Main_safety_number + 1000000l - Rotation_safety_backup) % (Uint32)1000000l);
@ -1400,7 +1517,7 @@ void Rotate_safety_backups(void)
Main_time_of_safety_backup=now; Main_time_of_safety_backup=now;
// Create a new file name and save // Create a new file name and save
sprintf(file_name, "%c%6.6d.bkp", sprintf(file_name, "%c%6.6d" BACKUP_FILE_EXTENSION,
Main_safety_backup_prefix, Main_safety_backup_prefix,
(Uint32)Main_safety_number); (Uint32)Main_safety_number);
Init_context_backup_image(&context, file_name, Config_directory); Init_context_backup_image(&context, file_name, Config_directory);
@ -1442,6 +1559,10 @@ void Delete_safety_backups(void)
} }
// Release lock file // Release lock file
#if defined (__MINT__)
//TODO: release file lock under Freemint only
#else
Release_lock_file(Config_directory); Release_lock_file(Config_directory);
#endif
} }

View File

@ -37,6 +37,14 @@ enum CONTEXT_TYPE {
CONTEXT_SURFACE, CONTEXT_SURFACE,
}; };
/// Data for a cycling color series. Heavily cloned from T_Gradient_array.
typedef struct
{
byte Start; ///< First color
byte End; ///< Last color
byte Inverse; ///< Boolean, true if the gradient goes in descending order
byte Speed; ///< Frequency of cycling, from 1 (slow) to 64 (fast)
} T_Color_cycle;
typedef struct typedef struct
{ {
@ -71,6 +79,9 @@ typedef struct
/// Original file directory, stored in GIF file /// Original file directory, stored in GIF file
char * Original_file_directory; char * Original_file_directory;
byte Color_cycles;
T_Color_cycle Cycle_range[16];
/// Internal: during load, marks which layer is being loaded. /// Internal: during load, marks which layer is being loaded.
short Current_layer; short Current_layer;
@ -87,12 +98,17 @@ typedef struct
short Preview_factor_Y; short Preview_factor_Y;
short Preview_pos_X; short Preview_pos_X;
short Preview_pos_Y; short Preview_pos_Y;
byte *Preview_bitmap;
byte Preview_usage[256];
// Internal: returned surface for SDL_Surface case // Internal: returned surface for SDL_Surface case
SDL_Surface * Surface; SDL_Surface * Surface;
} T_IO_Context; } T_IO_Context;
#define PREVIEW_WIDTH 120
#define PREVIEW_HEIGHT 80
/// Type of a function that can be called for a T_IO_Context. Kind of a method. /// Type of a function that can be called for a T_IO_Context. Kind of a method.
typedef void (* Func_IO) (T_IO_Context *); typedef void (* Func_IO) (T_IO_Context *);
@ -165,8 +181,10 @@ extern T_Format File_formats[];
/// is too high. /// is too high.
void Image_emergency_backup(void); void Image_emergency_backup(void);
///
/// Load an arbitrary SDL_Surface. /// Load an arbitrary SDL_Surface.
SDL_Surface * Load_surface(char *full_name); /// @param gradients Pass the address of a target T_Gradient_array if you want the gradients, NULL otherwise
SDL_Surface * Load_surface(char *full_name, T_Gradient_array *gradients);
/* /*
@ -178,12 +196,8 @@ T_Format * Get_fileformat(byte format);
// -- File formats // -- File formats
#ifndef __no_pnglib__ /// Total number of known file formats
#define NB_KNOWN_FORMATS 19 ///< Total number of known file formats. unsigned int Nb_known_formats(void);
#else
// Without pnglib
#define NB_KNOWN_FORMATS 18 ///< Total number of known file formats.
#endif
// Internal use // Internal use
@ -210,7 +224,6 @@ void Set_layer(T_IO_Context *context, byte layer);
// ================================================================= // =================================================================
// This is here and not in fileformats.c because the emergency save uses it... // This is here and not in fileformats.c because the emergency save uses it...
#pragma pack(1)
typedef struct typedef struct
{ {
byte Filler1[6]; byte Filler1[6];
@ -219,7 +232,6 @@ typedef struct
byte Filler2[118]; byte Filler2[118];
T_Palette Palette; T_Palette Palette;
} T_IMG_Header; } T_IMG_Header;
#pragma pack()
// Data for 24bit loading // Data for 24bit loading

View File

@ -2,6 +2,7 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2009 Pasi Kallinen Copyright 2009 Pasi Kallinen
Copyright 2008 Peter Gordon Copyright 2008 Peter Gordon
Copyright 2008 Franck Charlet Copyright 2008 Franck Charlet
@ -40,7 +41,7 @@
// There is no WM on the GP2X... // There is no WM on the GP2X...
#ifndef __GP2X__ #if !defined(__GP2X__) && !defined(__WIZ__) && !defined(__CAANOO__)
#include <SDL_syswm.h> #include <SDL_syswm.h>
#endif #endif
@ -65,11 +66,14 @@
#include "brush.h" #include "brush.h"
#include "palette.h" #include "palette.h"
#include "realpath.h" #include "realpath.h"
#include "input.h"
#if defined(__WIN32__) #if defined(__WIN32__)
#include <windows.h> #include <windows.h>
#include <shlwapi.h> #include <shlwapi.h>
#define chdir(dir) SetCurrentDirectory(dir) #define chdir(dir) SetCurrentDirectory(dir)
#elif defined (__MINT__)
#include <mint/osbind.h>
#elif defined(__macosx__) #elif defined(__macosx__)
#import <corefoundation/corefoundation.h> #import <corefoundation/corefoundation.h>
#import <sys/param.h> #import <sys/param.h>
@ -85,6 +89,8 @@
extern DECLSPEC int SDLCALL SDL_putenv(const char *variable); extern DECLSPEC int SDLCALL SDL_putenv(const char *variable);
#endif #endif
extern char Program_version[]; // generated in pversion.c
//--- Affichage de la syntaxe, et de la liste des modes vidéos disponibles --- //--- Affichage de la syntaxe, et de la liste des modes vidéos disponibles ---
void Display_syntax(void) void Display_syntax(void)
{ {
@ -139,7 +145,7 @@ void Error_function(int error_code, const char *filename, int line_number, const
for (index=0;index<=255;index++) for (index=0;index<=255;index++)
temp_palette[index].R=255; temp_palette[index].R=255;
Set_palette(temp_palette); Set_palette(temp_palette);
SDL_Delay(500); Delay_with_active_mouse(50); // Half a second of red flash
Set_palette(Main_palette); Set_palette(Main_palette);
} }
else else
@ -400,6 +406,17 @@ int Analyze_command_line(int argc, char * argv[], char *main_filename, char *mai
return file_in_command_line; return file_in_command_line;
} }
// Compile-time assertions:
#define CT_ASSERT(e) extern char (*ct_assert(void)) [sizeof(char[1 - 2*!(e)])]
// This line will raise an error at compile time
// when sizeof(T_Components) is not 3.
CT_ASSERT(sizeof(T_Components)==3);
// This line will raise an error at compile time
// when sizeof(T_Palette) is not 768.
CT_ASSERT(sizeof(T_Palette)==768);
// ------------------------ Initialiser le programme ------------------------- // ------------------------ Initialiser le programme -------------------------
// Returns 0 on fail // Returns 0 on fail
int Init_program(int argc,char * argv[]) int Init_program(int argc,char * argv[])
@ -409,12 +426,18 @@ int Init_program(int argc,char * argv[])
static char program_directory[MAX_PATH_CHARACTERS]; static char program_directory[MAX_PATH_CHARACTERS];
T_Gui_skin *gfx; T_Gui_skin *gfx;
int file_in_command_line; int file_in_command_line;
T_Gradient_array initial_gradients;
static char main_filename [MAX_PATH_CHARACTERS]; static char main_filename [MAX_PATH_CHARACTERS];
static char main_directory[MAX_PATH_CHARACTERS]; static char main_directory[MAX_PATH_CHARACTERS];
static char spare_filename [MAX_PATH_CHARACTERS]; static char spare_filename [MAX_PATH_CHARACTERS];
static char spare_directory[MAX_PATH_CHARACTERS]; static char spare_directory[MAX_PATH_CHARACTERS];
#if defined(__MINT__)
printf("===============================\n");
printf(" /|\\ GrafX2 %.19s\n", Program_version);
printf(" compilation date: %.16s\n", __DATE__);
printf("===============================\n");
#endif
// On crée dès maintenant les descripteurs des listes de pages pour la page // On crée dès maintenant les descripteurs des listes de pages pour la page
// principale et la page de brouillon afin que leurs champs ne soient pas // principale et la page de brouillon afin que leurs champs ne soient pas
@ -431,9 +454,12 @@ int Init_program(int argc,char * argv[])
Set_data_directory(program_directory,Data_directory); Set_data_directory(program_directory,Data_directory);
// Choose directory for settings (read/write) // Choose directory for settings (read/write)
Set_config_directory(program_directory,Config_directory); Set_config_directory(program_directory,Config_directory);
#if defined(__MINT__)
// On détermine le répertoire courant: strcpy(Main_current_directory,program_directory);
#else
// On détermine le répertoire courant:
getcwd(Main_current_directory,256); getcwd(Main_current_directory,256);
#endif
// On en profite pour le mémoriser dans le répertoire principal: // On en profite pour le mémoriser dans le répertoire principal:
strcpy(Initial_directory,Main_current_directory); strcpy(Initial_directory,Main_current_directory);
@ -473,8 +499,6 @@ int Init_program(int argc,char * argv[])
// On initialise d'ot' trucs // On initialise d'ot' trucs
Main_offset_X=0; Main_offset_X=0;
Main_offset_Y=0; Main_offset_Y=0;
Old_main_offset_X=0;
Old_main_offset_Y=0;
Main_separator_position=0; Main_separator_position=0;
Main_X_zoom=0; Main_X_zoom=0;
Main_separator_proportion=INITIAL_SEPARATOR_PROPORTION; Main_separator_proportion=INITIAL_SEPARATOR_PROPORTION;
@ -486,8 +510,6 @@ int Init_program(int argc,char * argv[])
Main_magnifier_offset_Y=0; Main_magnifier_offset_Y=0;
Spare_offset_X=0; Spare_offset_X=0;
Spare_offset_Y=0; Spare_offset_Y=0;
Old_spare_offset_X=0;
Old_spare_offset_Y=0;
Spare_separator_position=0; Spare_separator_position=0;
Spare_X_zoom=0; Spare_X_zoom=0;
Spare_separator_proportion=INITIAL_SEPARATOR_PROPORTION; Spare_separator_proportion=INITIAL_SEPARATOR_PROPORTION;
@ -497,16 +519,16 @@ int Init_program(int argc,char * argv[])
Spare_magnifier_width=0; Spare_magnifier_width=0;
Spare_magnifier_offset_X=0; Spare_magnifier_offset_X=0;
Spare_magnifier_offset_Y=0; Spare_magnifier_offset_Y=0;
Keyboard_click_allowed = 0; Keyboard_click_allowed = 1;
Main_safety_backup_prefix = 'a'; Main_safety_backup_prefix = SAFETYBACKUP_PREFIX_A[0];
Spare_safety_backup_prefix = 'b'; Spare_safety_backup_prefix = SAFETYBACKUP_PREFIX_B[0];
Main_time_of_safety_backup = 0; Main_time_of_safety_backup = 0;
Spare_time_of_safety_backup = 0; Spare_time_of_safety_backup = 0;
// SDL // SDL
if(SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0) if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0)
{ {
// The program can't continue without that anyway // The program can't continue without that anyway
printf("Couldn't initialize SDL.\n"); printf("Couldn't initialize SDL.\n");
@ -517,42 +539,7 @@ int Init_program(int argc,char * argv[])
SDL_EnableKeyRepeat(250, 32); SDL_EnableKeyRepeat(250, 32);
SDL_EnableUNICODE(SDL_ENABLE); SDL_EnableUNICODE(SDL_ENABLE);
SDL_WM_SetCaption("GrafX2","GrafX2"); SDL_WM_SetCaption("GrafX2","GrafX2");
Define_icon();
{
// Routine pour définir l'icone.
char icon_path[MAX_PATH_CHARACTERS];
SDL_Surface * icon;
sprintf(icon_path, "%s%s", Data_directory, "gfx2.gif");
icon = IMG_Load(icon_path);
if (icon && icon->w == 32 && icon->h == 32)
{
Uint32 pink;
pink = SDL_MapRGB(icon->format, 255, 0, 255);
if (icon->format->BitsPerPixel == 8)
{
SDL_SetColorKey(icon, SDL_SRCCOLORKEY, pink);
SDL_WM_SetIcon(icon,NULL);
}
else
{
byte *icon_mask;
int x,y;
icon_mask=malloc(128);
memset(icon_mask,0,128);
for (y=0;y<32;y++)
for (x=0;x<32;x++)
if (Get_SDL_pixel_hicolor(icon, x, y) != pink)
icon_mask[(y*32+x)/8] |=0x80>>(x&7);
SDL_WM_SetIcon(icon,icon_mask);
free(icon_mask);
icon_mask = NULL;
}
SDL_FreeSurface(icon);
}
}
// Texte // Texte
Init_text(); Init_text();
@ -574,7 +561,6 @@ int Init_program(int argc,char * argv[])
// Données sur le pinceau: // Données sur le pinceau:
Paintbrush_X=0; Paintbrush_X=0;
Paintbrush_Y=0; Paintbrush_Y=0;
Paintbrush_shape=PAINTBRUSH_SHAPE_ROUND;
Paintbrush_hidden=0; Paintbrush_hidden=0;
// On initialise tout ce qui concerne les opérations et les effets // On initialise tout ce qui concerne les opérations et les effets
@ -634,6 +620,25 @@ int Init_program(int argc,char * argv[])
Windows_open=0; Windows_open=0;
// Paintbrush
if (!(Paintbrush_sprite=(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE))) Error(ERROR_MEMORY);
// Load preset paintbrushes (uses Paintbrush_ variables)
Init_paintbrushes();
// Set a valid paintbrush afterwards
*Paintbrush_sprite=1;
Paintbrush_width=1;
Paintbrush_height=1;
Paintbrush_offset_X=0;
Paintbrush_offset_Y=0;
Paintbrush_shape=PAINTBRUSH_SHAPE_ROUND;
#if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__)
// Prefer cycling active by default
Cycling_mode=1;
#endif
// Charger la configuration des touches // Charger la configuration des touches
Set_config_defaults(); Set_config_defaults();
@ -662,10 +667,10 @@ int Init_program(int argc,char * argv[])
Help_position=0; Help_position=0;
// Load sprites, palette etc. // Load sprites, palette etc.
gfx = Load_graphics(Config.Skin_file); gfx = Load_graphics(Config.Skin_file, &initial_gradients);
if (gfx == NULL) if (gfx == NULL)
{ {
gfx = Load_graphics("skin_DPaint.png"); gfx = Load_graphics(DEFAULT_SKIN_FILENAME, &initial_gradients);
if (gfx == NULL) if (gfx == NULL)
{ {
printf("%s", Gui_loading_error_message); printf("%s", Gui_loading_error_message);
@ -678,7 +683,10 @@ int Init_program(int argc,char * argv[])
// Gfx->Default_palette[MC_Dark] =Config.Fav_menu_colors[1]; // Gfx->Default_palette[MC_Dark] =Config.Fav_menu_colors[1];
// Gfx->Default_palette[MC_Light]=Config.Fav_menu_colors[2]; // Gfx->Default_palette[MC_Light]=Config.Fav_menu_colors[2];
// Gfx->Default_palette[MC_White]=Config.Fav_menu_colors[3]; // Gfx->Default_palette[MC_White]=Config.Fav_menu_colors[3];
// Compute_optimal_menu_colors(Gfx->Default_palette);
// Even when using the skin's palette, if RGB range is small
// the colors will be unusable.
Compute_optimal_menu_colors(Gfx->Default_palette);
// Infos sur les trames (Sieve) // Infos sur les trames (Sieve)
Sieve_mode=0; Sieve_mode=0;
@ -686,9 +694,9 @@ int Init_program(int argc,char * argv[])
// Font // Font
if (!(Menu_font=Load_font(Config.Font_file))) if (!(Menu_font=Load_font(Config.Font_file)))
if (!(Menu_font=Load_font("font_DPaint.png"))) if (!(Menu_font=Load_font(DEFAULT_FONT_FILENAME)))
{ {
printf("Unable to open the default font file: %s\n", "font_Classic.png"); printf("Unable to open the default font file: %s\n", DEFAULT_FONT_FILENAME);
Error(ERROR_GUI_MISSING); Error(ERROR_GUI_MISSING);
} }
@ -701,11 +709,6 @@ int Init_program(int argc,char * argv[])
if (!(Brush =(byte *)malloc( 1* 1))) Error(ERROR_MEMORY); if (!(Brush =(byte *)malloc( 1* 1))) Error(ERROR_MEMORY);
if (!(Smear_brush =(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE))) Error(ERROR_MEMORY); if (!(Smear_brush =(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE))) Error(ERROR_MEMORY);
// Pinceau
if (!(Paintbrush_sprite=(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE))) Error(ERROR_MEMORY);
*Paintbrush_sprite=1;
Paintbrush_width=1;
Paintbrush_height=1;
starting_videomode=Current_resolution; starting_videomode=Current_resolution;
Horizontal_line_buffer=NULL; Horizontal_line_buffer=NULL;
@ -731,6 +734,9 @@ int Init_program(int argc,char * argv[])
SetWindowPos(pInfo.window, 0, Config.Window_pos_x, Config.Window_pos_y, 0, 0, SWP_NOSIZE); SetWindowPos(pInfo.window, 0, Config.Window_pos_x, Config.Window_pos_y, 0, 0, SWP_NOSIZE);
} }
} }
// Open a console for debugging...
//ActivateConsole();
#endif #endif
Main_image_width=Screen_width/Pixel_width; Main_image_width=Screen_width/Pixel_width;
@ -745,15 +751,29 @@ int Init_program(int argc,char * argv[])
// Nettoyage de l'écran virtuel (les autres recevront celui-ci par copie) // Nettoyage de l'écran virtuel (les autres recevront celui-ci par copie)
memset(Main_screen,0,Main_image_width*Main_image_height); memset(Main_screen,0,Main_image_width*Main_image_height);
// Now that the backup system is there, we can store the gradients.
memcpy(Main_backups->Pages->Gradients->Range, initial_gradients.Range, sizeof(initial_gradients.Range));
memcpy(Spare_backups->Pages->Gradients->Range, initial_gradients.Range, sizeof(initial_gradients.Range));
Gradient_function=Gradient_basic;
Gradient_lower_bound=0;
Gradient_upper_bound=0;
Gradient_random_factor=1;
Gradient_bounds_range=1;
Current_gradient=0;
// Initialisation de diverses variables par calcul: // Initialisation de diverses variables par calcul:
Compute_magnifier_data(); Compute_magnifier_data();
Compute_limits(); Compute_limits();
Compute_paintbrush_coordinates(); Compute_paintbrush_coordinates();
// On affiche le menu: // On affiche le menu:
Display_menu();
Display_paintbrush_in_menu(); Display_paintbrush_in_menu();
Display_sprite_in_menu(BUTTON_PAL_LEFT,18+(Config.Palette_vertical!=0)); Display_sprite_in_menu(BUTTON_PAL_LEFT,Config.Palette_vertical?MENU_SPRITE_VERTICAL_PALETTE_SCROLL:-1);
Display_menu();
Draw_menu_button(BUTTON_PAL_LEFT,BUTTON_RELEASED);
Draw_menu_button(BUTTON_PAL_RIGHT,BUTTON_RELEASED);
// On affiche le curseur pour débutter correctement l'état du programme: // On affiche le curseur pour débutter correctement l'état du programme:
Display_cursor(); Display_cursor();
@ -770,8 +790,11 @@ int Init_program(int argc,char * argv[])
// On initialise la brosse initiale à 1 pixel blanc: // On initialise la brosse initiale à 1 pixel blanc:
Brush_width=1; Brush_width=1;
Brush_height=1; Brush_height=1;
for (temp=0;temp<256;temp++)
Brush_colormap[temp]=temp;
Capture_brush(0,0,0,0,0); Capture_brush(0,0,0,0,0);
*Brush=MC_White; *Brush=MC_White;
*Brush_original_pixels=MC_White;
// Test de recuperation de fichiers sauvés // Test de recuperation de fichiers sauvés
switch (Check_recovery()) switch (Check_recovery())
@ -843,6 +866,9 @@ int Init_program(int argc,char * argv[])
break; break;
} }
} }
Allow_drag_and_drop(1);
return(1); return(1);
} }
@ -908,6 +934,12 @@ void Program_shutdown(void)
Error(ERROR_MISSING_DIRECTORY); Error(ERROR_MISSING_DIRECTORY);
SDL_Quit(); SDL_Quit();
#if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__)
chdir("/usr/gp2x");
execl("/usr/gp2x/gp2xmenu", "/usr/gp2x/gp2xmenu", NULL);
#endif
} }

View File

@ -2,6 +2,7 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues
@ -177,7 +178,8 @@ void Wait_end_of_click(void)
{ {
// On désactive tous les raccourcis clavier // On désactive tous les raccourcis clavier
while(Mouse_K) if(!Get_input()) SDL_Delay(20); while(Mouse_K)
Get_input(20);
} }
void Clear_current_image_with_stencil(byte color, byte * stencil) void Clear_current_image_with_stencil(byte color, byte * stencil)
@ -339,7 +341,7 @@ void Rotate_270_deg_lowlevel(byte * source, byte * dest, short width, short heig
// Replace une couleur par une autre dans un buffer // Replace une couleur par une autre dans un buffer
void Remap_general_lowlevel(byte * conversion_table,byte * buffer,short width,short height,short buffer_width) void Remap_general_lowlevel(byte * conversion_table,byte * in_buffer, byte *out_buffer,short width,short height,short buffer_width)
{ {
int dx,cx; int dx,cx;
@ -349,17 +351,19 @@ void Remap_general_lowlevel(byte * conversion_table,byte * buffer,short width,sh
// Pour chaque pixel // Pour chaque pixel
for(cx=width;cx>0;cx--) for(cx=width;cx>0;cx--)
{ {
*buffer = conversion_table[*buffer]; *out_buffer = conversion_table[*in_buffer];
buffer++; in_buffer++;
out_buffer++;
} }
buffer += buffer_width-width; in_buffer += buffer_width-width;
out_buffer += buffer_width-width;
} }
} }
void Copy_image_to_brush(short start_x,short start_y,short Brush_width,short Brush_height,word image_width) void Copy_image_to_brush(short start_x,short start_y,short Brush_width,short Brush_height,word image_width)
{ {
byte* src=start_y*image_width+start_x+Main_backups->Pages->Image[Main_current_layer]; //Adr départ image (ESI) byte* src=start_y*image_width+start_x+Main_backups->Pages->Image[Main_current_layer]; //Adr départ image (ESI)
byte* dest=Brush; //Adr dest brosse (EDI) byte* dest=Brush_original_pixels; //Adr dest brosse (EDI)
int dx; int dx;
for (dx=Brush_height;dx!=0;dx--) for (dx=Brush_height;dx!=0;dx--)
@ -499,6 +503,22 @@ byte Effect_substractive_colorize(word x,word y,byte color)
blue<blue_under?blue:blue_under); blue<blue_under?blue:blue_under);
} }
byte Effect_alpha_colorize (word x,word y,byte color)
{
byte color_under = Read_pixel_from_feedback_screen(x,y);
byte blue_under=Main_palette[color_under].B;
byte green_under=Main_palette[color_under].G;
byte red_under=Main_palette[color_under].R;
int factor=(Main_palette[color].R*76 +
Main_palette[color].G*151 +
Main_palette[color].B*28)/255;
return Best_color(
(Main_palette[Fore_color].R*factor + red_under*(255-factor))/255,
(Main_palette[Fore_color].G*factor + green_under*(255-factor))/255,
(Main_palette[Fore_color].B*factor + blue_under*(255-factor))/255);
}
void Check_timer(void) void Check_timer(void)
{ {
if((SDL_GetTicks()/55)-Timer_delay>Timer_start) Timer_state=1; if((SDL_GetTicks()/55)-Timer_delay>Timer_start) Timer_state=1;
@ -659,17 +679,6 @@ void Rescale(byte *src_buffer, short src_width, short src_height, byte *dst_buff
} }
} }
void Slider_timer(byte speed)
//Boucle d'attente pour faire bouger les scrollbars à une vitesse correcte
{
Uint32 end;
byte original_mouse_k = Mouse_K;
end = SDL_GetTicks() + speed*10;
do
{
if (!Get_input()) SDL_Delay(20);
} while (Mouse_K == original_mouse_k && SDL_GetTicks()<end);
}
void Scroll_picture(byte * main_src, byte * main_dest, short x_offset,short y_offset) void Scroll_picture(byte * main_src, byte * main_dest, short x_offset,short y_offset)
{ {
@ -732,13 +741,26 @@ void Zoom_a_line(byte* original_line, byte* zoomed_line,
// sysinfo not implemented // sysinfo not implemented
#elif defined(__AROS__) || defined(__amigaos4__) || defined(__MORPHOS__) || defined(__amigaos__) #elif defined(__AROS__) || defined(__amigaos4__) || defined(__MORPHOS__) || defined(__amigaos__)
#include <proto/exec.h> #include <proto/exec.h>
#elif defined(__MINT__)
#include <mint/osbind.h>
#include <mint/sysbind.h>
#elif defined(__SKYOS__) #elif defined(__SKYOS__)
#include <skyos/sysinfo.h> #include <skyos/sysinfo.h>
#else #else
#include <sys/sysinfo.h> // sysinfo() for free RAM #include <sys/sysinfo.h> // sysinfo() for free RAM
#endif #endif
#if defined (__MINT__)
// atari have two kinds of memory
// standard and fast ram
void Atari_Memory_free(unsigned long *stRam,unsigned long *ttRam){
//TODO: return STRAM/TT-RAM
unsigned long mem=0;
*stRam=Mxalloc(-1L,0);
*ttRam = Mxalloc(-1L,1);
}
#else
// Indique quelle est la mémoire disponible // Indique quelle est la mémoire disponible
unsigned long Memory_free(void) unsigned long Memory_free(void)
{ {
@ -778,6 +800,8 @@ unsigned long Memory_free(void)
return info.freeram*info.mem_unit; return info.freeram*info.mem_unit;
#endif #endif
} }
#endif
// Arrondir un nombre réel à la valeur entière la plus proche // Arrondir un nombre réel à la valeur entière la plus proche

View File

@ -33,7 +33,7 @@
#define SWAP_PBYTES(a,b) { byte * c=a; a=b; b=c;} #define SWAP_PBYTES(a,b) { byte * c=a; a=b; b=c;}
void Copy_image_to_brush(short start_x,short start_y,short Brush_width,short Brush_height,word image_width); void Copy_image_to_brush(short start_x,short start_y,short Brush_width,short Brush_height,word image_width);
void Remap_general_lowlevel(byte * conversion_table,byte * buffer,short width,short height,short buffer_width); void Remap_general_lowlevel(byte * conversion_table,byte * in_buffer, byte *out_buffer,short width,short height,short buffer_width);
void Scroll_picture(byte * main_src, byte * main_dest, short x_offset,short y_offset); void Scroll_picture(byte * main_src, byte * main_dest, short x_offset,short y_offset);
void Wait_end_of_click(void); void Wait_end_of_click(void);
void Set_color(byte color, byte red, byte green, byte blue); void Set_color(byte color, byte red, byte green, byte blue);
@ -42,7 +42,6 @@ void Palette_256_to_64(T_Palette palette);
void Palette_64_to_256(T_Palette palette); void Palette_64_to_256(T_Palette palette);
void Clear_current_image(byte color); void Clear_current_image(byte color);
void Clear_current_image_with_stencil(byte color, byte * stencil); void Clear_current_image_with_stencil(byte color, byte * stencil);
void Slider_timer(byte speed);
dword Round_div(dword numerator,dword divisor); dword Round_div(dword numerator,dword divisor);
word Count_used_colors(dword * usage); word Count_used_colors(dword * usage);
word Count_used_colors_area(dword* usage, word start_x, word start_y, word width, word height); word Count_used_colors_area(dword* usage, word start_x, word start_y, word width, word height);
@ -86,6 +85,7 @@ void Replace_colors_within_limits(byte * replace_table);
byte Effect_interpolated_colorize (word x,word y,byte color); byte Effect_interpolated_colorize (word x,word y,byte color);
byte Effect_additive_colorize (word x,word y,byte color); byte Effect_additive_colorize (word x,word y,byte color);
byte Effect_substractive_colorize(word x,word y,byte color); byte Effect_substractive_colorize(word x,word y,byte color);
byte Effect_alpha_colorize(word x,word y,byte color);
byte Effect_sieve(word x,word y); byte Effect_sieve(word x,word y);
/// ///

View File

@ -2,6 +2,7 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2009 Petter Lindquist Copyright 2009 Petter Lindquist
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet Copyright 2008 Franck Charlet
@ -368,7 +369,8 @@ void Load_PKM(T_IO_Context * context)
Compteur_de_donnees_packees=0; Compteur_de_donnees_packees=0;
Compteur_de_pixels=0; Compteur_de_pixels=0;
Taille_pack=(file_size)-sizeof(T_PKM_Header)-header.Jump; // Header size is 780
Taille_pack=(file_size)-780-header.Jump;
// Boucle de décompression: // Boucle de décompression:
while ( (Compteur_de_pixels<image_size) && (Compteur_de_donnees_packees<Taille_pack) && (!File_error) ) while ( (Compteur_de_pixels<image_size) && (Compteur_de_donnees_packees<Taille_pack) && (!File_error) )
@ -637,7 +639,6 @@ void Save_PKM(T_IO_Context * context)
//////////////////////////////////// CEL //////////////////////////////////// //////////////////////////////////// CEL ////////////////////////////////////
#pragma pack(1)
typedef struct typedef struct
{ {
word Width; // width de l'image word Width; // width de l'image
@ -656,7 +657,6 @@ typedef struct
word Y_offset; // Offset en Y de l'image word Y_offset; // Offset en Y de l'image
byte Filler2[16]; // ??? byte Filler2[16]; // ???
} T_CEL_Header2; } T_CEL_Header2;
#pragma pack()
// -- Tester si un fichier est au format CEL -------------------------------- // -- Tester si un fichier est au format CEL --------------------------------
@ -689,7 +689,7 @@ void Test_CEL(T_IO_Context * context)
// Vu que ce header n'a pas de signature, il va falloir tester la // Vu que ce header n'a pas de signature, il va falloir tester la
// cohérence de la dimension de l'image avec celle du fichier. // cohérence de la dimension de l'image avec celle du fichier.
size=file_size-sizeof(T_CEL_Header1); size=file_size-4;
if ( (!size) || ( (((header1.Width+1)>>1)*header1.Height)!=size ) ) if ( (!size) || ( (((header1.Width+1)>>1)*header1.Height)!=size ) )
{ {
// Tentative de reconnaissance de la signature des nouveaux fichiers // Tentative de reconnaissance de la signature des nouveaux fichiers
@ -735,7 +735,7 @@ void Load_CEL(T_IO_Context * context)
short y_pos; short y_pos;
byte last_byte=0; byte last_byte=0;
long file_size; long file_size;
const long int header_size = (long int)(sizeof(header1.Width)+sizeof(header1.Height)); const long int header_size = 4;
File_error=0; File_error=0;
Get_full_filename(filename, context->File_name, context->File_directory); Get_full_filename(filename, context->File_name, context->File_directory);
@ -775,7 +775,7 @@ void Load_CEL(T_IO_Context * context)
// On réessaye avec le nouveau format // On réessaye avec le nouveau format
fseek(file,0,SEEK_SET); fseek(file,0,SEEK_SET);
if (Read_bytes(file,header2.Signature,sizeof(header2.Signature)) if (Read_bytes(file,header2.Signature,4)
&& Read_byte(file,&(header2.Kind)) && Read_byte(file,&(header2.Kind))
&& Read_byte(file,&(header2.Nb_bits)) && Read_byte(file,&(header2.Nb_bits))
&& Read_word_le(file,&(header2.Filler1)) && Read_word_le(file,&(header2.Filler1))
@ -783,7 +783,7 @@ void Load_CEL(T_IO_Context * context)
&& Read_word_le(file,&(header2.Height)) && Read_word_le(file,&(header2.Height))
&& Read_word_le(file,&(header2.X_offset)) && Read_word_le(file,&(header2.X_offset))
&& Read_word_le(file,&(header2.Y_offset)) && Read_word_le(file,&(header2.Y_offset))
&& Read_bytes(file,header2.Filler2,sizeof(header2.Filler2)) && Read_bytes(file,header2.Filler2,16)
) )
{ {
// Chargement d'un fichier CEL avec signature (nouveaux fichiers) // Chargement d'un fichier CEL avec signature (nouveaux fichiers)
@ -942,7 +942,7 @@ void Save_CEL(T_IO_Context * context)
for (x_pos=0;x_pos<16;x_pos++) // Initialisation du filler 2 (?) for (x_pos=0;x_pos<16;x_pos++) // Initialisation du filler 2 (?)
header2.Filler2[x_pos]=0; header2.Filler2[x_pos]=0;
if (Write_bytes(file,header2.Signature,sizeof(header2.Signature)) if (Write_bytes(file,header2.Signature,4)
&& Write_byte(file,header2.Kind) && Write_byte(file,header2.Kind)
&& Write_byte(file,header2.Nb_bits) && Write_byte(file,header2.Nb_bits)
&& Write_word_le(file,header2.Filler1) && Write_word_le(file,header2.Filler1)
@ -950,7 +950,7 @@ void Save_CEL(T_IO_Context * context)
&& Write_word_le(file,header2.Height) && Write_word_le(file,header2.Height)
&& Write_word_le(file,header2.X_offset) && Write_word_le(file,header2.X_offset)
&& Write_word_le(file,header2.Y_offset) && Write_word_le(file,header2.Y_offset)
&& Write_bytes(file,header2.Filler2,sizeof(header2.Filler2)) && Write_bytes(file,header2.Filler2,14)
) )
{ {
// Sauvegarde de l'image // Sauvegarde de l'image
@ -974,7 +974,6 @@ void Save_CEL(T_IO_Context * context)
//////////////////////////////////// KCF //////////////////////////////////// //////////////////////////////////// KCF ////////////////////////////////////
#pragma pack(1)
typedef struct typedef struct
{ {
struct struct
@ -986,7 +985,6 @@ typedef struct
} color[16]; } color[16];
} Palette[10]; } Palette[10];
} T_KCF_Header; } T_KCF_Header;
#pragma pack()
// -- Tester si un fichier est au format KCF -------------------------------- // -- Tester si un fichier est au format KCF --------------------------------
@ -994,7 +992,7 @@ void Test_KCF(T_IO_Context * context)
{ {
char filename[MAX_PATH_CHARACTERS]; char filename[MAX_PATH_CHARACTERS];
FILE *file; FILE *file;
T_KCF_Header buffer; T_KCF_Header header1;
T_CEL_Header2 header2; T_CEL_Header2 header2;
int pal_index; int pal_index;
int color_index; int color_index;
@ -1003,18 +1001,22 @@ void Test_KCF(T_IO_Context * context)
Get_full_filename(filename, context->File_name, context->File_directory); Get_full_filename(filename, context->File_name, context->File_directory);
if ((file=fopen(filename, "rb"))) if ((file=fopen(filename, "rb")))
{ {
if (File_length_file(file)==sizeof(T_KCF_Header)) if (File_length_file(file)==320)
{ {
Read_bytes(file,&buffer,sizeof(T_KCF_Header)); for (pal_index=0;pal_index<10 && !File_error;pal_index++)
for (color_index=0;color_index<16 && !File_error;color_index++)
if (!Read_byte(file,&header1.Palette[pal_index].color[color_index].Byte1) ||
!Read_byte(file,&header1.Palette[pal_index].color[color_index].Byte2))
File_error=1;
// On vérifie une propriété de la structure de palette: // On vérifie une propriété de la structure de palette:
for (pal_index=0;pal_index<10;pal_index++) for (pal_index=0;pal_index<10;pal_index++)
for (color_index=0;color_index<16;color_index++) for (color_index=0;color_index<16;color_index++)
if ((buffer.Palette[pal_index].color[color_index].Byte2>>4)!=0) if ((header1.Palette[pal_index].color[color_index].Byte2>>4)!=0)
File_error=1; File_error=1;
} }
else else
{ {
if (Read_bytes(file,header2.Signature,sizeof(header2.Signature)) if (Read_bytes(file,header2.Signature,4)
&& Read_byte(file,&(header2.Kind)) && Read_byte(file,&(header2.Kind))
&& Read_byte(file,&(header2.Nb_bits)) && Read_byte(file,&(header2.Nb_bits))
&& Read_word_le(file,&(header2.Filler1)) && Read_word_le(file,&(header2.Filler1))
@ -1022,7 +1024,7 @@ void Test_KCF(T_IO_Context * context)
&& Read_word_le(file,&(header2.Height)) && Read_word_le(file,&(header2.Height))
&& Read_word_le(file,&(header2.X_offset)) && Read_word_le(file,&(header2.X_offset))
&& Read_word_le(file,&(header2.Y_offset)) && Read_word_le(file,&(header2.Y_offset))
&& Read_bytes(file,header2.Filler2,sizeof(header2.Filler2)) && Read_bytes(file,header2.Filler2,14)
) )
{ {
if (memcmp(header2.Signature,"KiSS",4)==0) if (memcmp(header2.Signature,"KiSS",4)==0)
@ -1049,7 +1051,7 @@ void Load_KCF(T_IO_Context * context)
{ {
char filename[MAX_PATH_CHARACTERS]; char filename[MAX_PATH_CHARACTERS];
FILE *file; FILE *file;
T_KCF_Header buffer; T_KCF_Header header1;
T_CEL_Header2 header2; T_CEL_Header2 header2;
byte bytes[3]; byte bytes[3];
int pal_index; int pal_index;
@ -1063,11 +1065,16 @@ void Load_KCF(T_IO_Context * context)
if ((file=fopen(filename, "rb"))) if ((file=fopen(filename, "rb")))
{ {
file_size=File_length_file(file); file_size=File_length_file(file);
if (file_size==sizeof(T_KCF_Header)) if (file_size==320)
{ {
// Fichier KCF à l'ancien format // Fichier KCF à l'ancien format
for (pal_index=0;pal_index<10 && !File_error;pal_index++)
for (color_index=0;color_index<16 && !File_error;color_index++)
if (!Read_byte(file,&header1.Palette[pal_index].color[color_index].Byte1) ||
!Read_byte(file,&header1.Palette[pal_index].color[color_index].Byte2))
File_error=1;
if (Read_bytes(file,&buffer,sizeof(T_KCF_Header))) if (!File_error)
{ {
// Pre_load(context, ?); // Pas possible... pas d'image... // Pre_load(context, ?); // Pas possible... pas d'image...
@ -1079,9 +1086,9 @@ void Load_KCF(T_IO_Context * context)
for (color_index=0;color_index<16;color_index++) for (color_index=0;color_index<16;color_index++)
{ {
index=16+(pal_index*16)+color_index; index=16+(pal_index*16)+color_index;
context->Palette[index].R=((buffer.Palette[pal_index].color[color_index].Byte1 >> 4) << 4); context->Palette[index].R=((header1.Palette[pal_index].color[color_index].Byte1 >> 4) << 4);
context->Palette[index].B=((buffer.Palette[pal_index].color[color_index].Byte1 & 15) << 4); context->Palette[index].B=((header1.Palette[pal_index].color[color_index].Byte1 & 15) << 4);
context->Palette[index].G=((buffer.Palette[pal_index].color[color_index].Byte2 & 15) << 4); context->Palette[index].G=((header1.Palette[pal_index].color[color_index].Byte2 & 15) << 4);
} }
for (index=0;index<16;index++) for (index=0;index<16;index++)
@ -1100,7 +1107,7 @@ void Load_KCF(T_IO_Context * context)
{ {
// Fichier KCF au nouveau format // Fichier KCF au nouveau format
if (Read_bytes(file,header2.Signature,sizeof(header2.Signature)) if (Read_bytes(file,header2.Signature,4)
&& Read_byte(file,&(header2.Kind)) && Read_byte(file,&(header2.Kind))
&& Read_byte(file,&(header2.Nb_bits)) && Read_byte(file,&(header2.Nb_bits))
&& Read_word_le(file,&(header2.Filler1)) && Read_word_le(file,&(header2.Filler1))
@ -1108,7 +1115,7 @@ void Load_KCF(T_IO_Context * context)
&& Read_word_le(file,&(header2.Height)) && Read_word_le(file,&(header2.Height))
&& Read_word_le(file,&(header2.X_offset)) && Read_word_le(file,&(header2.X_offset))
&& Read_word_le(file,&(header2.Y_offset)) && Read_word_le(file,&(header2.Y_offset))
&& Read_bytes(file,header2.Filler2,sizeof(header2.Filler2)) && Read_bytes(file,header2.Filler2,14)
) )
{ {
// Pre_load(context, ?); // Pas possible... pas d'image... // Pre_load(context, ?); // Pas possible... pas d'image...
@ -1168,7 +1175,7 @@ void Save_KCF(T_IO_Context * context)
{ {
char filename[MAX_PATH_CHARACTERS]; char filename[MAX_PATH_CHARACTERS];
FILE *file; FILE *file;
T_KCF_Header buffer; T_KCF_Header header1;
T_CEL_Header2 header2; T_CEL_Header2 header2;
byte bytes[3]; byte bytes[3];
int pal_index; int pal_index;
@ -1196,12 +1203,16 @@ void Save_KCF(T_IO_Context * context)
for (color_index=0;color_index<16;color_index++) for (color_index=0;color_index<16;color_index++)
{ {
index=16+(pal_index*16)+color_index; index=16+(pal_index*16)+color_index;
buffer.Palette[pal_index].color[color_index].Byte1=((context->Palette[index].R>>4)<<4) | (context->Palette[index].B>>4); header1.Palette[pal_index].color[color_index].Byte1=((context->Palette[index].R>>4)<<4) | (context->Palette[index].B>>4);
buffer.Palette[pal_index].color[color_index].Byte2=context->Palette[index].G>>4; header1.Palette[pal_index].color[color_index].Byte2=context->Palette[index].G>>4;
} }
if (! Write_bytes(file,&buffer,sizeof(T_KCF_Header))) // Write all
File_error=1; for (pal_index=0;pal_index<10 && !File_error;pal_index++)
for (color_index=0;color_index<16 && !File_error;color_index++)
if (!Write_byte(file,header1.Palette[pal_index].color[color_index].Byte1) ||
!Write_byte(file,header1.Palette[pal_index].color[color_index].Byte2))
File_error=1;
} }
else else
{ {
@ -1218,7 +1229,7 @@ void Save_KCF(T_IO_Context * context)
for (index=0;index<16;index++) // Initialisation du filler 2 (?) for (index=0;index<16;index++) // Initialisation du filler 2 (?)
header2.Filler2[index]=0; header2.Filler2[index]=0;
if (!Write_bytes(file,header2.Signature,sizeof(header2.Signature)) if (!Write_bytes(file,header2.Signature,4)
|| !Write_byte(file,header2.Kind) || !Write_byte(file,header2.Kind)
|| !Write_byte(file,header2.Nb_bits) || !Write_byte(file,header2.Nb_bits)
|| !Write_word_le(file,header2.Filler1) || !Write_word_le(file,header2.Filler1)
@ -1226,7 +1237,7 @@ void Save_KCF(T_IO_Context * context)
|| !Write_word_le(file,header2.Height) || !Write_word_le(file,header2.Height)
|| !Write_word_le(file,header2.X_offset) || !Write_word_le(file,header2.X_offset)
|| !Write_word_le(file,header2.Y_offset) || !Write_word_le(file,header2.Y_offset)
|| !Write_bytes(file,header2.Filler2,sizeof(header2.Filler2)) || !Write_bytes(file,header2.Filler2,14)
) )
File_error=1; File_error=1;
@ -1326,12 +1337,24 @@ void PI1_decode_palette(byte * src,byte * palette)
ip=0; ip=0;
for (i=0;i<16;i++) for (i=0;i<16;i++)
{ {
w=((word)src[(i*2)+1]<<8) | src[(i*2)+0]; #if SDL_BYTEORDER == SDL_LIL_ENDIAN
w=(((word)src[(i*2)+1]<<8) | (src[(i*2)+0]));
// Traitement des couleurs rouge, verte et bleue:
palette[ip++]=(((w & 0x0007) << 1) | ((w & 0x0008) >> 3)) << 4;
palette[ip++]=(((w & 0x7000) >> 11) | ((w & 0x8000) >> 15)) << 4;
palette[ip++]=(((w & 0x0700) >> 7) | ((w & 0x0800) >> 11)) << 4;
#else
w=(((word)src[(i*2+1)])|(((word)src[(i*2)])<<8));
palette[ip++] = (((w & 0x0700)>>7) | ((w & 0x0800) >> 7))<<4 ;
palette[ip++]=(((w & 0x0070)>>3) | ((w & 0x0080) >> 3))<<4 ;
palette[ip++] = (((w & 0x0007)<<1) | ((w & 0x0008)))<<4 ;
#endif
// Traitement des couleurs rouge, verte et bleue:
palette[ip++]=(((w & 0x0007) << 1) | ((w & 0x0008) >> 3)) << 4;
palette[ip++]=(((w & 0x7000) >> 11) | ((w & 0x8000) >> 15)) << 4;
palette[ip++]=(((w & 0x0700) >> 7) | ((w & 0x0800) >> 11)) << 4;
} }
} }
@ -1345,13 +1368,15 @@ void PI1_code_palette(byte * palette,byte * dest)
// Schéma d'un word = // Schéma d'un word =
// //
// Low High // Low High
// VVVV RRRR | 0000 BBBB // VVVV RRRR | 0000 BBBB
// 0321 0321 | 0321 // 0321 0321 | 0321
ip=0; ip=0;
for (i=0;i<16;i++) for (i=0;i<16;i++)
{ {
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
// Traitement des couleurs rouge, verte et bleue: // Traitement des couleurs rouge, verte et bleue:
w =(((word)(palette[ip]>>2) & 0x38) >> 3) | (((word)(palette[ip]>>2) & 0x04) << 1); ip++; w =(((word)(palette[ip]>>2) & 0x38) >> 3) | (((word)(palette[ip]>>2) & 0x04) << 1); ip++;
w|=(((word)(palette[ip]>>2) & 0x38) << 9) | (((word)(palette[ip]>>2) & 0x04) << 13); ip++; w|=(((word)(palette[ip]>>2) & 0x38) << 9) | (((word)(palette[ip]>>2) & 0x04) << 13); ip++;
@ -1359,6 +1384,15 @@ void PI1_code_palette(byte * palette,byte * dest)
dest[(i*2)+0]=w & 0x00FF; dest[(i*2)+0]=w & 0x00FF;
dest[(i*2)+1]=(w>>8); dest[(i*2)+1]=(w>>8);
#else
w=(((word)(palette[ip]<<3))&0x0700);ip++;
w|=(((word)(palette[ip]>>1))&0x0070);ip++;
w|=(((word)(palette[ip]>>5))&0x0007);ip++;
dest[(i*2)+1]=w & 0x00FF;
dest[(i*2)+0]=(w>>8);
#endif
} }
} }
@ -2472,13 +2506,13 @@ int Save_C64_window(byte *saveWhat, byte *loadAddr)
Print_in_window(13,18,"Data:",MC_Dark,MC_Light); Print_in_window(13,18,"Data:",MC_Dark,MC_Light);
what=Window_set_dropdown_button(10,28,90,15,70,what_label[*saveWhat],1, 0, 1, LEFT_SIDE,0); // 3 what=Window_set_dropdown_button(10,28,90,15,70,what_label[*saveWhat],1, 0, 1, LEFT_SIDE,0); // 3
Window_dropdown_clear_items(what); Window_dropdown_clear_items(what);
for (i=0; i<sizeof(what_label)/sizeof(char *); i++) for (i=0; i<sizeof(what_label)/sizeof(what_label[0]); i++)
Window_dropdown_add_item(what,i,what_label[i]); Window_dropdown_add_item(what,i,what_label[i]);
Print_in_window(113,18,"Address:",MC_Dark,MC_Light); Print_in_window(113,18,"Address:",MC_Dark,MC_Light);
addr=Window_set_dropdown_button(110,28,70,15,70,address_label[*loadAddr/32],1, 0, 1, LEFT_SIDE,0); // 4 addr=Window_set_dropdown_button(110,28,70,15,70,address_label[*loadAddr/32],1, 0, 1, LEFT_SIDE,0); // 4
Window_dropdown_clear_items(addr); Window_dropdown_clear_items(addr);
for (i=0; i<sizeof(address_label)/sizeof(char *); i++) for (i=0; i<sizeof(address_label)/sizeof(address_label[0]); i++)
Window_dropdown_add_item(addr,i,address_label[i]); Window_dropdown_add_item(addr,i,address_label[i]);
Update_window_area(0,0,Window_width,Window_height); Update_window_area(0,0,Window_width,Window_height);

View File

@ -336,12 +336,12 @@ fstype_to_string (int t)
#define BROKEN #define BROKEN
#endif #endif
#if defined MOUNTED_GETMNTENT1 || defined MOUNTED_GETMNTENT2 #if defined MOUNTED_GETMNTENT1 || defined MOUNTED_GETMNTENT2
/* Return the device number from MOUNT_OPTIONS, if possible. /* Return the device number from MOUNT_OPTIONS, if possible.
Otherwise return (dev_t) -1. */ Otherwise return (dev_t) -1. */
static dev_t static dev_t
dev_from_mount_options (BROKEN char const *mount_options) dev_from_mount_options (BROKEN char const *mount_options)
{ {

View File

@ -2,6 +2,7 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2010 Alexander Filyanov
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
@ -30,6 +31,8 @@
#include "op_c.h" #include "op_c.h"
#include "errors.h" #include "errors.h"
int Convert_24b_bitmap_to_256_fast(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette);
/// Convert RGB to HSL. /// Convert RGB to HSL.
/// Both input and output are in the 0..255 range to use in the palette screen /// Both input and output are in the 0..255 range to use in the palette screen
void RGB_to_HSL(int r,int g,int b,byte * hr,byte * sr,byte* lr) void RGB_to_HSL(int r,int g,int b,byte * hr,byte * sr,byte* lr)
@ -165,6 +168,16 @@ void HSL_to_RGB(byte h,byte s,byte l, byte* r, byte* g, byte* b)
*b = bf * (255); *b = bf * (255);
} }
///
/// Returns a value that is high when color is near white,
/// and low when it's darker. Used for sorting.
long Perceptual_lightness(T_Components *color)
{
return 26*color->R*26*color->R +
55*color->G*55*color->G +
19*color->B*19*color->B;
}
// Conversion table handlers // Conversion table handlers
// The conversion table is built after a run of the median cut algorithm and is // The conversion table is built after a run of the median cut algorithm and is
// used to find the best color index for a given (RGB) color. GIMP avoids // used to find the best color index for a given (RGB) color. GIMP avoids
@ -1342,6 +1355,10 @@ static const byte precision_24b[]=
// Give this one a 24b source, get back the 256c bitmap and its palette // Give this one a 24b source, get back the 256c bitmap and its palette
int Convert_24b_bitmap_to_256(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette) int Convert_24b_bitmap_to_256(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette)
{ {
#if defined(__GP2X__) || defined(__gp2x__) || defined(__WIZ__) || defined(__CAANOO__)
return Convert_24b_bitmap_to_256_fast(dest, source, width, height, palette);
#else
T_Conversion_table * table; // table de conversion T_Conversion_table * table; // table de conversion
int ip; // index de précision pour la conversion int ip; // index de précision pour la conversion
@ -1363,7 +1380,36 @@ int Convert_24b_bitmap_to_256(T_Bitmap256 dest,T_Bitmap24B source,int width,int
} }
else else
return 1; return 1;
#endif
} }
//Really small, fast and ugly converter(just for handhelds)
#include "global.h"
#include "limits.h"
#include "engine.h"
#include "windows.h"
extern void Set_palette_fake_24b(T_Palette palette);
/// Really small, fast and dirty convertor(just for handhelds)
int Convert_24b_bitmap_to_256_fast(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette)
{
int size;
Set_palette_fake_24b(palette);
size = width*height;
while(size--)
{
//Set palette color index to destination bitmap
*dest = ((source->R >> 5) << 5) |
((source->G >> 5) << 2) |
((source->B >> 6));
source++;
dest++;
}
return 0;
}

View File

@ -160,6 +160,7 @@ void CT_set(T_Conversion_table * t,int r,int g,int b,byte i);
void RGB_to_HSL(int r, int g,int b, byte* h, byte*s, byte* l); void RGB_to_HSL(int r, int g,int b, byte* h, byte*s, byte* l);
void HSL_to_RGB(byte h, byte s, byte l, byte* r, byte* g, byte* b); void HSL_to_RGB(byte h, byte s, byte l, byte* r, byte* g, byte* b);
long Perceptual_lightness(T_Components *color);
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
/////////////////////////////// Méthodes de gestion des tables d'occurence // /////////////////////////////// Méthodes de gestion des tables d'occurence //

View File

@ -36,6 +36,7 @@
#include "sdlscreen.h" #include "sdlscreen.h"
#include "brush.h" #include "brush.h"
#include "windows.h" #include "windows.h"
#include "input.h"
// PI is NOT part of math.h according to C standards... // PI is NOT part of math.h according to C standards...
#if defined(__GP2X__) || defined(__VBCC__) #if defined(__GP2X__) || defined(__VBCC__)
@ -53,11 +54,12 @@ void Start_operation_stack(word new_operation)
// On mémorise l'opération précédente si on démarre une interruption // On mémorise l'opération précédente si on démarre une interruption
switch(new_operation) switch(new_operation)
{ {
case OPERATION_MAGNIFY : case OPERATION_MAGNIFY:
case OPERATION_COLORPICK : case OPERATION_COLORPICK:
case OPERATION_GRAB_BRUSH : case OPERATION_RMB_COLORPICK:
case OPERATION_POLYBRUSH : case OPERATION_GRAB_BRUSH:
case OPERATION_STRETCH_BRUSH : case OPERATION_POLYBRUSH:
case OPERATION_STRETCH_BRUSH:
case OPERATION_ROTATE_BRUSH: case OPERATION_ROTATE_BRUSH:
Operation_before_interrupt=Current_operation; Operation_before_interrupt=Current_operation;
// On passe à l'operation demandée // On passe à l'operation demandée
@ -226,6 +228,9 @@ void Freehand_mode1_2_0(void)
// //
// Souris effacée: Oui // Souris effacée: Oui
{ {
if (Rightclick_colorpick(0))
return;
Init_start_operation(); Init_start_operation();
Backup(); Backup();
Shade_table=Shade_table_right; Shade_table=Shade_table_right;
@ -322,6 +327,9 @@ void Freehand_mode2_2_0(void)
// //
// Souris effacée: Oui // Souris effacée: Oui
{ {
if (Rightclick_colorpick(0))
return;
Init_start_operation(); Init_start_operation();
Backup(); Backup();
Shade_table=Shade_table_right; Shade_table=Shade_table_right;
@ -390,6 +398,9 @@ void Freehand_Mode3_2_0(void)
// //
// Souris effacée: Oui // Souris effacée: Oui
{ {
if (Rightclick_colorpick(0))
return;
Init_start_operation(); Init_start_operation();
Backup(); Backup();
Shade_table=Shade_table_right; Shade_table=Shade_table_right;
@ -422,6 +433,9 @@ void Line_12_0(void)
// Début du tracé d'une ligne (premier clic) // Début du tracé d'une ligne (premier clic)
{ {
if (Rightclick_colorpick(0))
return;
Init_start_operation(); Init_start_operation();
Backup(); Backup();
Paintbrush_shape_before_operation=Paintbrush_shape; Paintbrush_shape_before_operation=Paintbrush_shape;
@ -480,9 +494,7 @@ void Line_12_5(void)
// On corrige les coordonnées de la ligne si la touche shift est appuyée... // On corrige les coordonnées de la ligne si la touche shift est appuyée...
if(SDL_GetModState() & KMOD_SHIFT) if(SDL_GetModState() & KMOD_SHIFT)
{
Clamp_coordinates_regular_angle(start_x,start_y,&cursor_x,&cursor_y); Clamp_coordinates_regular_angle(start_x,start_y,&cursor_x,&cursor_y);
}
// On vient de bouger // On vient de bouger
if ((cursor_x!=end_x) || (cursor_y!=end_y)) if ((cursor_x!=end_x) || (cursor_y!=end_y))
@ -557,11 +569,11 @@ void Line_0_5(void)
} }
/////////////////////////////////////////////////////////// OPERATION_K_LIGNE /////////////////////////////////////////////////////////// OPERATION_K_LINE
void K_line_12_0(void) void K_line_12_0(void)
// Opération : OPERATION_K_LIGNE // Opération : OPERATION_K_LINE
// Click Souris: 1 ou 2 // Click Souris: 1 ou 2
// Taille_Pile : 0 // Taille_Pile : 0
// //
@ -569,6 +581,9 @@ void K_line_12_0(void)
{ {
byte color; byte color;
if (Rightclick_colorpick(0))
return;
Init_start_operation(); Init_start_operation();
Backup(); Backup();
Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
@ -594,7 +609,7 @@ void K_line_12_0(void)
void K_line_12_6(void) void K_line_12_6(void)
// Opération : OPERATION_K_LIGNE // Opération : OPERATION_K_LINE
// Click Souris: 1 ou 2 | 0 // Click Souris: 1 ou 2 | 0
// Taille_Pile : 6 | 7 // Taille_Pile : 6 | 7
// //
@ -634,7 +649,7 @@ void K_line_12_6(void)
void K_line_0_6(void) void K_line_0_6(void)
// Opération : OPERATION_K_LIGNE // Opération : OPERATION_K_LINE
// Click Souris: 0 // Click Souris: 0
// Taille_Pile : 6 // Taille_Pile : 6
// //
@ -684,7 +699,7 @@ void K_line_0_6(void)
void K_line_12_7(void) void K_line_12_7(void)
// Opération : OPERATION_K_LIGNE // Opération : OPERATION_K_LINE
// Click Souris: 1 ou 2 // Click Souris: 1 ou 2
// Taille_Pile : 7 // Taille_Pile : 7
// //
@ -745,6 +760,9 @@ void Rectangle_12_0(void)
// //
// Souris effacée: Oui // Souris effacée: Oui
{ {
if (Rightclick_colorpick(0))
return;
Init_start_operation(); Init_start_operation();
if ((Config.Coords_rel) && (Menu_is_visible)) if ((Config.Coords_rel) && (Menu_is_visible))
@ -916,6 +934,9 @@ void Circle_12_0(void)
// //
// Souris effacée: Oui // Souris effacée: Oui
{ {
if (Rightclick_colorpick(0))
return;
Init_start_operation(); Init_start_operation();
Backup(); Backup();
@ -1090,6 +1111,9 @@ void Ellipse_12_0(void)
// //
// Souris effacée: Oui // Souris effacée: Oui
{ {
if (Rightclick_colorpick(0))
return;
Init_start_operation(); Init_start_operation();
Backup(); Backup();
@ -1284,9 +1308,12 @@ void Fill_2_0(void)
// Click Souris: 2 // Click Souris: 2
// Taille_Pile : 0 // Taille_Pile : 0
// //
// Souris effacée: Oui // Souris effacée: Non
// //
{ {
if (Rightclick_colorpick(1))
return;
Hide_cursor(); Hide_cursor();
// Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas // Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas
// le Fill, et on se fout de savoir si on est dans la partie gauche ou // le Fill, et on se fout de savoir si on est dans la partie gauche ou
@ -1309,7 +1336,7 @@ void Replace_1_0(void)
// Click Souris: 1 // Click Souris: 1
// Taille_Pile : 0 // Taille_Pile : 0
// //
// Souris effacée: Oui // Souris effacée: Non
// //
{ {
Hide_cursor(); Hide_cursor();
@ -1331,9 +1358,12 @@ void Replace_2_0(void)
// Click Souris: 2 // Click Souris: 2
// Taille_Pile : 0 // Taille_Pile : 0
// //
// Souris effacée: Oui // Souris effacée: Non
// //
{ {
if (Rightclick_colorpick(1))
return;
Hide_cursor(); Hide_cursor();
// Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas // Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas
// le Replace, et on se fout de savoir si on est dans la partie gauche ou // le Replace, et on se fout de savoir si on est dans la partie gauche ou
@ -1433,6 +1463,9 @@ void Curve_34_points_2_0(void)
// Souris effacée: Oui // Souris effacée: Oui
// //
{ {
if (Rightclick_colorpick(0))
return;
Init_start_operation(); Init_start_operation();
Backup(); Backup();
Shade_table=Shade_table_right; Shade_table=Shade_table_right;
@ -1711,17 +1744,17 @@ void Compute_3_point_curve(short x1, short y1, short x4, short y4,
float cx,cy; // Centre de (x1,y1) et (x4,y4) float cx,cy; // Centre de (x1,y1) et (x4,y4)
float bx,by; // Intersect. des dtes ((x1,y1),(x2,y2)) et ((x3,y3),(x4,y4)) float bx,by; // Intersect. des dtes ((x1,y1),(x2,y2)) et ((x3,y3),(x4,y4))
cx=(float)(x1+x4)/2.0; // P1*--_ Légende: cx=(float)(x1+x4)/2.0; // P1*--_ Legend:
cy=(float)(y1+y4)/2.0; // · \·· P2 -_\|/ : courbe cy=(float)(y1+y4)/2.0; // · \·· P2 -_\|/ : curve
// · \ ·*· * : point important // · \ ·*· * : important point
bx=cx+((8.0/3.0)*(Paintbrush_X-cx));// · | ·· · : pointillÚ bx=cx+((8.0/3.0)*(Paintbrush_X-cx));// · | ·· · : dotted line
by=cy+((8.0/3.0)*(Paintbrush_Y-cy));// · |P ·· B by=cy+((8.0/3.0)*(Paintbrush_Y-cy));// · |P ·· B
// C *·····*·········* P=Pos. du pinceau // C *·····*·········* P=Pencil position
*x2=Round((bx+x1)/2.0); // · | ·· C=milieu de [P1,P4] *x2=Round((bx+x1)/2.0); // · | ·· C=middle of [P1,P4]
*y2=Round((by+y1)/2.0); // · | ·· B=point tel que *y2=Round((by+y1)/2.0); // · | ·· B=point computed as
// · / ·*· C->B=(8/3) * C->P // · / ·*· C->B=(8/3) * C->P
*x3=Round((bx+x4)/2.0); // · _/·· P3 P2=milieu de [P1,B] *x3=Round((bx+x4)/2.0); // · _/·· P3 P2=middle of [P1,B]
*y3=Round((by+y4)/2.0); // P4*-- P3=milieu de [P4,B] *y3=Round((by+y4)/2.0); // P4*-- P3=middle of [P4,B]
} }
@ -1745,8 +1778,11 @@ void Curve_3_points_0_5(void)
Compute_3_point_curve(x1,y1,x4,y4,&x2,&y2,&x3,&y3); Compute_3_point_curve(x1,y1,x4,y4,&x2,&y2,&x3,&y3);
Hide_line_preview(x1,y1,x4,y4); if (!Config.Stylus_mode)
Draw_curve_preview(x1,y1,x2,y2,x3,y3,x4,y4,color); {
Hide_line_preview(x1,y1,x4,y4);
Draw_curve_preview(x1,y1,x2,y2,x3,y3,x4,y4,color);
}
if ( (Config.Coords_rel) && (Menu_is_visible) ) if ( (Config.Coords_rel) && (Menu_is_visible) )
{ {
@ -1765,17 +1801,19 @@ void Curve_3_points_0_5(void)
Operation_push(y4); Operation_push(y4);
Operation_push(Paintbrush_X); Operation_push(Paintbrush_X);
Operation_push(Paintbrush_Y); Operation_push(Paintbrush_Y);
if (Config.Stylus_mode)
{
Display_cursor();
while(!Mouse_K)
Get_input(20);
Hide_cursor();
Hide_line_preview(x1,y1,x4,y4);
}
} }
void Curve_drag(void)
void Curve_3_points_0_11(void)
//
// Opération : OPERATION_3_POINTS_CURVE
// Click Souris: 0
// Taille_Pile : 11
//
// Souris effacée: Non
//
{ {
short x1,y1,x2,y2,x3,y3,x4,y4; short x1,y1,x2,y2,x3,y3,x4,y4;
short old_x,old_y; short old_x,old_y;
@ -1817,16 +1855,7 @@ void Curve_3_points_0_11(void)
Operation_push(Paintbrush_X); Operation_push(Paintbrush_X);
Operation_push(Paintbrush_Y); Operation_push(Paintbrush_Y);
} }
void Curve_finalize(void)
void Curve_3_points_12_11(void)
//
// Opération : OPERATION_3_POINTS_CURVE
// Click Souris: 1 ou 2
// Taille_Pile : 11
//
// Souris effacée: Oui
//
{ {
short x1,y1,x2,y2,x3,y3,x4,y4; short x1,y1,x2,y2,x3,y3,x4,y4;
short old_x,old_y; short old_x,old_y;
@ -1857,6 +1886,37 @@ void Curve_3_points_12_11(void)
Wait_end_of_click(); Wait_end_of_click();
} }
void Curve_3_points_0_11(void)
//
// Opération : OPERATION_3_POINTS_CURVE
// Click Souris: 0
// Taille_Pile : 11
//
// Souris effacée: Non
//
{
if (!Config.Stylus_mode)
Curve_drag();
else
Curve_finalize();
}
void Curve_3_points_12_11(void)
//
// Opération : OPERATION_3_POINTS_CURVE
// Click Souris: 1 ou 2
// Taille_Pile : 11
//
// Souris effacée: Oui
//
{
if (!Config.Stylus_mode)
Curve_finalize();
else
Curve_drag();
}
///////////////////////////////////////////////////////////// OPERATION_AIRBRUSH ///////////////////////////////////////////////////////////// OPERATION_AIRBRUSH
@ -1873,8 +1933,11 @@ void Airbrush_1_0(void)
Backup(); Backup();
Shade_table=Shade_table_left; Shade_table=Shade_table_left;
Airbrush_next_time = SDL_GetTicks()+Airbrush_delay*10; if (SDL_GetTicks()>Airbrush_next_time)
Airbrush(LEFT_SIDE); {
Airbrush(LEFT_SIDE);
Airbrush_next_time = SDL_GetTicks()+Airbrush_delay*10;
}
Operation_push(Paintbrush_X); Operation_push(Paintbrush_X);
Operation_push(Paintbrush_Y); Operation_push(Paintbrush_Y);
@ -1889,11 +1952,17 @@ void Airbrush_2_0(void)
// Souris effacée: Non // Souris effacée: Non
// //
{ {
if (Rightclick_colorpick(1))
return;
Init_start_operation(); Init_start_operation();
Backup(); Backup();
Shade_table=Shade_table_right; Shade_table=Shade_table_right;
Airbrush_next_time = SDL_GetTicks()+Airbrush_delay*10; if (SDL_GetTicks()>Airbrush_next_time)
Airbrush(RIGHT_SIDE); {
Airbrush(RIGHT_SIDE);
Airbrush_next_time = SDL_GetTicks()+Airbrush_delay*10;
}
Operation_push(Paintbrush_X); Operation_push(Paintbrush_X);
Operation_push(Paintbrush_Y); Operation_push(Paintbrush_Y);
@ -1909,6 +1978,7 @@ void Airbrush_12_2(void)
// //
{ {
short old_x,old_y; short old_x,old_y;
Uint32 now;
Operation_pop(&old_y); Operation_pop(&old_y);
Operation_pop(&old_x); Operation_pop(&old_x);
@ -1920,9 +1990,13 @@ void Airbrush_12_2(void)
Display_cursor(); Display_cursor();
} }
if (SDL_GetTicks()>Airbrush_next_time) now=SDL_GetTicks();
if (now>Airbrush_next_time)
{ {
Airbrush_next_time+=Airbrush_delay*10; //Airbrush_next_time+=Airbrush_delay*10;
// Time is now reset, because the += was death spiral
// if drawing took more time than the frequency.
Airbrush_next_time=now+Airbrush_delay*10;
Airbrush(Mouse_K_unique); Airbrush(Mouse_K_unique);
} }
@ -1956,6 +2030,9 @@ void Polygon_12_0(void)
{ {
byte color; byte color;
if (Rightclick_colorpick(0))
return;
Init_start_operation(); Init_start_operation();
Backup(); Backup();
Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
@ -2057,6 +2134,9 @@ void Polyfill_12_0(void)
{ {
byte color; byte color;
if (Rightclick_colorpick(0))
return;
Init_start_operation(); Init_start_operation();
Backup(); Backup();
Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
@ -2255,6 +2335,9 @@ void Polyform_12_0(void)
{ {
short color; short color;
if (Rightclick_colorpick(0))
return;
Init_start_operation(); Init_start_operation();
Backup(); Backup();
Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
@ -2413,6 +2496,9 @@ void Filled_polyform_12_0(void)
{ {
short color; short color;
if (Rightclick_colorpick(0))
return;
Init_start_operation(); Init_start_operation();
// Cette opération étant également utilisée pour le lasso, on ne fait pas de // Cette opération étant également utilisée pour le lasso, on ne fait pas de
@ -2825,6 +2911,7 @@ void Grad_circle_12_0(void)
Init_start_operation(); Init_start_operation();
Backup(); Backup();
Load_gradient_data(Current_gradient);
Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color; color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color;
@ -3082,6 +3169,8 @@ void Grad_ellipse_12_0(void)
Init_start_operation(); Init_start_operation();
Backup(); Backup();
Load_gradient_data(Current_gradient);
Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color; color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color;
@ -3306,6 +3395,7 @@ void Grad_rectangle_12_0(void)
{ {
Init_start_operation(); Init_start_operation();
Backup(); Backup();
Load_gradient_data(Current_gradient);
if ((Config.Coords_rel) && (Menu_is_visible)) if ((Config.Coords_rel) && (Menu_is_visible))
Print_in_menu("\035: 1 \022: 1",0); Print_in_menu("\035: 1 \022: 1",0);
@ -3712,6 +3802,9 @@ void Centered_lines_12_0(void)
// //
// Souris effacée: Oui // Souris effacée: Oui
{ {
if (Rightclick_colorpick(0))
return;
Init_start_operation(); Init_start_operation();
Backup(); Backup();
Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;

View File

@ -225,3 +225,8 @@ void Centered_lines_0_3(void);
void Centered_lines_12_7(void); void Centered_lines_12_7(void);
void Centered_lines_0_7(void); void Centered_lines_0_7(void);
/////////////////////////////////////////////////// OPERATION_RMB_COLORPICK
byte Rightclick_colorpick(byte cursor_visible);
void Rightclick_colorpick_2_1(void);
void Rightclick_colorpick_0_1(void);

View File

@ -75,6 +75,7 @@ T_Page * New_page(byte nb_layers)
page->Filename[0]='\0'; page->Filename[0]='\0';
page->File_format=DEFAULT_FILEFORMAT; page->File_format=DEFAULT_FILEFORMAT;
page->Nb_layers=nb_layers; page->Nb_layers=nb_layers;
page->Gradients=NULL;
page->Transparent_color=0; // Default transparent color page->Transparent_color=0; // Default transparent color
page->Background_transparent=0; page->Background_transparent=0;
page->Next = page->Prev = NULL; page->Next = page->Prev = NULL;
@ -141,6 +142,24 @@ byte * Dup_layer(byte * layer)
// ============================================================== // ==============================================================
/// Adds a shared reference to the gradient data of another page. Pass NULL for new.
T_Gradient_array *Dup_gradient(T_Page * page)
{
// new
if (page==NULL || page->Gradients==NULL)
{
T_Gradient_array *array;
array=(T_Gradient_array *)calloc(1, sizeof(T_Gradient_array));
if (!array)
return NULL;
array->Used=1;
return array;
}
// shared
page->Gradients->Used++;
return page->Gradients;
}
void Download_infos_page_main(T_Page * page) void Download_infos_page_main(T_Page * page)
// Affiche la page à l'écran // Affiche la page à l'écran
{ {
@ -418,6 +437,16 @@ void Clear_page(T_Page * page)
Free_layer(page, i); Free_layer(page, i);
page->Image[i]=NULL; page->Image[i]=NULL;
} }
// Free_gradient() : This data is reference-counted
if (page->Gradients)
{
page->Gradients->Used--;
if (page->Gradients->Used==0)
free(page->Gradients);
page->Gradients=NULL;
}
page->Width=0; page->Width=0;
page->Height=0; page->Height=0;
// On ne se préoccupe pas de ce que deviens le reste des infos de l'image. // On ne se préoccupe pas de ce que deviens le reste des infos de l'image.
@ -426,6 +455,7 @@ void Clear_page(T_Page * page)
void Copy_S_page(T_Page * dest,T_Page * source) void Copy_S_page(T_Page * dest,T_Page * source)
{ {
*dest=*source; *dest=*source;
dest->Gradients=NULL;
} }
@ -460,6 +490,10 @@ int Allocate_list_of_pages(T_List_of_pages * list)
list->List_size=1; list->List_size=1;
page->Gradients=Dup_gradient(NULL);
if (!page->Gradients)
return 0;
return 1; // Succès return 1; // Succès
} }
@ -799,19 +833,10 @@ void Set_number_of_backups(int nb_backups)
// (nb_backups = Nombre de backups, sans compter les pages courantes) // (nb_backups = Nombre de backups, sans compter les pages courantes)
} }
int Backup_with_new_dimensions(int upload,byte layers,int width,int height) int Backup_new_image(byte layers,int width,int height)
{ {
// Retourne 1 si une nouvelle page est disponible (alors pleine de 0) et // Retourne 1 si une nouvelle page est disponible et 0 sinon
// 0 sinon.
T_Page * new_page; T_Page * new_page;
int return_code=0;
int i;
if (upload)
// On remet à jour l'état des infos de la page courante (pour pouvoir les
// retrouver plus tard)
Upload_infos_page_main(Main_backups->Pages);
// On crée un descripteur pour la nouvelle page courante // On crée un descripteur pour la nouvelle page courante
new_page=New_page(layers); new_page=New_page(layers);
@ -820,36 +845,161 @@ int Backup_with_new_dimensions(int upload,byte layers,int width,int height)
Error(0); Error(0);
return 0; return 0;
} }
Upload_infos_page_main(new_page);
new_page->Width=width; new_page->Width=width;
new_page->Height=height; new_page->Height=height;
strcpy(new_page->Filename, Main_backups->Pages->Filename); new_page->Transparent_color=0;
strcpy(new_page->File_directory, Main_backups->Pages->File_directory); new_page->Gradients=Dup_gradient(NULL);
if (Create_new_page(new_page,Main_backups,0xFFFFFFFF)) if (!Create_new_page(new_page,Main_backups,0xFFFFFFFF))
{ {
for (i=0; i<layers;i++) Error(0);
{ return 0;
memset(Main_backups->Pages->Image[i], Main_backups->Pages->Transparent_color, width*height);
}
Update_buffers(width, height);
Download_infos_page_main(Main_backups->Pages);
// Same code as in End_of_modification():
#ifndef NOLAYERS
memcpy(Main_visible_image_backup.Image,
Main_visible_image.Image,
Main_image_width*Main_image_height);
#else
Update_screen_targets();
#endif
Update_FX_feedback(Config.FX_Feedback);
// --
return_code=1;
} }
return return_code;
Update_buffers(width, height);
Download_infos_page_main(Main_backups->Pages);
return 1;
}
int Backup_with_new_dimensions(int width,int height)
{
// Retourne 1 si une nouvelle page est disponible (alors pleine de 0) et
// 0 sinon.
T_Page * new_page;
int i;
// On crée un descripteur pour la nouvelle page courante
new_page=New_page(Main_backups->Pages->Nb_layers);
if (!new_page)
{
Error(0);
return 0;
}
new_page->Width=width;
new_page->Height=height;
new_page->Transparent_color=0;
if (!Create_new_page(new_page,Main_backups,0xFFFFFFFF))
{
Error(0);
return 0;
}
// Copy data from previous history step
memcpy(Main_backups->Pages->Palette,Main_backups->Pages->Next->Palette,sizeof(T_Palette));
strcpy(Main_backups->Pages->Comment,Main_backups->Pages->Next->Comment);
Main_backups->Pages->File_format=Main_backups->Pages->Next->File_format;
strcpy(Main_backups->Pages->Filename, Main_backups->Pages->Next->Filename);
strcpy(Main_backups->Pages->File_directory, Main_backups->Pages->Next->File_directory);
Main_backups->Pages->Gradients=Dup_gradient(Main_backups->Pages->Next);
Main_backups->Pages->Background_transparent=Main_backups->Pages->Next->Background_transparent;
Main_backups->Pages->Transparent_color=Main_backups->Pages->Next->Transparent_color;
// Fill with transparent color
for (i=0; i<Main_backups->Pages->Nb_layers;i++)
{
memset(Main_backups->Pages->Image[i], Main_backups->Pages->Transparent_color, width*height);
}
Update_buffers(width, height);
Download_infos_page_main(Main_backups->Pages);
// Same code as in End_of_modification(),
// Without saving a safety backup:
#ifndef NOLAYERS
memcpy(Main_visible_image_backup.Image,
Main_visible_image.Image,
Main_image_width*Main_image_height);
#else
Update_screen_targets();
#endif
Update_FX_feedback(Config.FX_Feedback);
// --
return 1;
}
///
/// Resizes a backup step in-place (doesn't add a Undo/Redo step).
/// Should only be called after an actual backup, because it loses the current.
/// pixels. This function is meant to be used from within Lua scripts.
int Backup_in_place(int width,int height)
{
// Retourne 1 si une nouvelle page est disponible (alors pleine de 0) et
// 0 sinon.
int i;
byte ** new_layer;
// Perform all allocations first
new_layer=calloc(Main_backups->Pages->Nb_layers,1);
if (!new_layer)
return 0;
for (i=0; i<Main_backups->Pages->Nb_layers; i++)
{
new_layer[i]=New_layer(height*width);
if (!new_layer[i])
{
// Allocation error
for (; i>0; i--)
free(new_layer[i]);
free(new_layer);
return 0;
}
}
// Now ok to proceed
for (i=0; i<Main_backups->Pages->Nb_layers; i++)
{
// Replace layers
Free_layer(Main_backups->Pages,i);
Main_backups->Pages->Image[i]=new_layer[i];
// Fill with transparency
memset(Main_backups->Pages->Image[i], Main_backups->Pages->Transparent_color, width*height);
}
Main_backups->Pages->Width=width;
Main_backups->Pages->Height=height;
Download_infos_page_main(Main_backups->Pages);
// The following is part of Update_buffers()
// (without changing the backup buffer)
#ifndef NOLAYERS
// At least one dimension is different
if (Main_visible_image.Width*Main_visible_image.Height != width*height)
{
// Current image
free(Main_visible_image.Image);
Main_visible_image.Image = (byte *)malloc(width * height);
if (Main_visible_image.Image == NULL)
return 0;
}
Main_visible_image.Width = width;
Main_visible_image.Height = height;
if (Main_visible_image_depth_buffer.Width*Main_visible_image_depth_buffer.Height != width*height)
{
// Depth buffer
free(Main_visible_image_depth_buffer.Image);
Main_visible_image_depth_buffer.Image = (byte *)malloc(width * height);
if (Main_visible_image_depth_buffer.Image == NULL)
return 0;
}
Main_visible_image_depth_buffer.Width = width;
Main_visible_image_depth_buffer.Height = height;
#endif
Update_screen_targets();
return 1;
} }
int Backup_and_resize_the_spare(int width,int height) int Backup_and_resize_the_spare(int width,int height)
@ -872,6 +1022,7 @@ int Backup_and_resize_the_spare(int width,int height)
// Fill it with a copy of the latest history // Fill it with a copy of the latest history
Copy_S_page(new_page,Spare_backups->Pages); Copy_S_page(new_page,Spare_backups->Pages);
new_page->Gradients=Dup_gradient(Spare_backups->Pages);
new_page->Width=width; new_page->Width=width;
new_page->Height=height; new_page->Height=height;
@ -927,6 +1078,7 @@ void Backup_layers(dword layer_mask)
// Fill it with a copy of the latest history // Fill it with a copy of the latest history
Copy_S_page(new_page,Main_backups->Pages); Copy_S_page(new_page,Main_backups->Pages);
new_page->Gradients=Dup_gradient(Main_backups->Pages);
Create_new_page(new_page,Main_backups,layer_mask); Create_new_page(new_page,Main_backups,layer_mask);
Download_infos_page_main(new_page); Download_infos_page_main(new_page);
@ -963,6 +1115,7 @@ void Backup_the_spare(dword layer_mask)
// Fill it with a copy of the latest history // Fill it with a copy of the latest history
Copy_S_page(new_page,Spare_backups->Pages); Copy_S_page(new_page,Spare_backups->Pages);
new_page->Gradients=Dup_gradient(Spare_backups->Pages);
Create_new_page(new_page,Spare_backups,layer_mask); Create_new_page(new_page,Spare_backups,layer_mask);
// Copy the actual pixels from the backup to the latest page // Copy the actual pixels from the backup to the latest page
@ -1099,6 +1252,11 @@ void End_of_modification(void)
//Update_buffers(Main_image_width, Main_image_height); //Update_buffers(Main_image_width, Main_image_height);
#ifndef NOLAYERS #ifndef NOLAYERS
// Backup buffer can have "wrong" size if a Lua script
// performs a resize.
Update_buffers(Main_image_width, Main_image_height);
//
memcpy(Main_visible_image_backup.Image, memcpy(Main_visible_image_backup.Image,
Main_visible_image.Image, Main_visible_image.Image,
Main_image_width*Main_image_height); Main_image_width*Main_image_height);

View File

@ -2,6 +2,7 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
@ -39,13 +40,14 @@ extern byte * FX_feedback_screen;
/////////////////////////// BACKUP /////////////////////////////////////// /////////////////////////// BACKUP ///////////////////////////////////////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#ifndef NOLAYERS
/// The pixels of visible layers, flattened copy. /// The pixels of visible layers, flattened copy.
extern T_Bitmap Main_visible_image; extern T_Bitmap Main_visible_image;
/// The pixels of visible layers, flattened copy, used for no-feedback effects. /// The pixels of visible layers, flattened copy, used for no-feedback effects.
extern T_Bitmap Main_visible_image_backup; extern T_Bitmap Main_visible_image_backup;
/// The index of visible pixels from ::Visible image. Points to the right layer. /// The index of visible pixels from ::Visible image. Points to the right layer.
extern T_Bitmap Main_visible_image_depth_buffer; extern T_Bitmap Main_visible_image_depth_buffer;
#endif
/// The pixels of visible layers for the spare page, flattened copy. /// The pixels of visible layers for the spare page, flattened copy.
extern T_Bitmap Spare_visible_image; extern T_Bitmap Spare_visible_image;
@ -93,7 +95,13 @@ void Free_page_of_a_list(T_List_of_pages * list);
int Init_all_backup_lists(int width,int height); int Init_all_backup_lists(int width,int height);
void Set_number_of_backups(int nb_backups); void Set_number_of_backups(int nb_backups);
int Backup_with_new_dimensions(int upload,byte layers,int width,int height); int Backup_new_image(byte layers,int width,int height);
int Backup_with_new_dimensions(int width,int height);
///
/// Resizes a backup step in-place (doesn't add a Undo/Redo step).
/// Should only be called after an actual backup, because it loses the current.
/// pixels. This function is meant to be used from within Lua scripts.
int Backup_in_place(int width,int height);
/// Backup the spare image, the one you don't see. /// Backup the spare image, the one you don't see.
void Backup_the_spare(dword layer_mask); void Backup_the_spare(dword layer_mask);
int Backup_and_resize_the_spare(int width,int height); int Backup_and_resize_the_spare(int width,int height);

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,8 @@ void Button_Secondary_palette(void);
/// Choose the number of graduations for RGB components, from 2 to 256. /// Choose the number of graduations for RGB components, from 2 to 256.
void Set_palette_RGB_scale(int); void Set_palette_RGB_scale(int);
int Get_palette_RGB_scale(void);
/// ///
/// Scale a component (R, G or B) according to the current RGB graduations. /// Scale a component (R, G or B) according to the current RGB graduations.
/// Returns the resulting value, in the [0-255] range. /// Returns the resulting value, in the [0-255] range.
@ -42,3 +44,17 @@ byte Round_palette_component(byte comp);
@param not_picture 0 if the caller is the palette screen, 1 if it's a preview in the file selector. @param not_picture 0 if the caller is the palette screen, 1 if it's a preview in the file selector.
*/ */
void Set_nice_menu_colors(dword * color_usage,int not_picture); void Set_nice_menu_colors(dword * color_usage,int not_picture);
/// Put some colors in the clipboard.
/// @param nb_colors Number of colors to push
/// @param colors First color of the input array
void Set_clipboard_colors(int nb_colors, T_Components *colors);
/// Get some RGB colors from clipboard.
/// @param palette Target palette
/// @param start_color Index of first color to replace
/// @return Number of colors retrieved (0-256)
int Get_clipboard_colors(T_Palette palette, byte start_color);
/// Get the favorite color to use for GUI's black,dark,light or white.
const T_Components * Favorite_GUI_color(byte color_index);

View File

@ -2,6 +2,7 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Peter Gordon Copyright 2008 Peter Gordon
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues
@ -32,6 +33,7 @@
#include "global.h" #include "global.h"
#include "misc.h" #include "misc.h"
#include "readini.h" #include "readini.h"
#include "setup.h"
void Load_INI_clear_string(char * str, byte keep_comments) void Load_INI_clear_string(char * str, byte keep_comments)
{ {
@ -433,20 +435,27 @@ int Load_INI(T_Config * conf)
Line_number_in_INI_file=0; Line_number_in_INI_file=0;
#if defined(__WIZ__) || defined(__CAANOO__)
conf->Stylus_mode = 1;
#else
conf->Stylus_mode = 0;
#endif
// On alloue les zones de mémoire: // On alloue les zones de mémoire:
buffer=(char *)malloc(1024); buffer=(char *)malloc(1024);
filename=(char *)malloc(256); filename=(char *)malloc(256);
// On calcule le nom du fichier qu'on manipule: // On calcule le nom du fichier qu'on manipule:
strcpy(filename,Config_directory); strcpy(filename,Config_directory);
strcat(filename,"gfx2.ini"); strcat(filename,INI_FILENAME);
file=fopen(filename,"r"); file=fopen(filename,"r");
if (file==0) if (file==0)
{ {
// Si le fichier ini est absent on le relit depuis gfx2def.ini // Si le fichier ini est absent on le relit depuis gfx2def.ini
strcpy(filename,Data_directory); strcpy(filename,Data_directory);
strcat(filename,"gfx2def.ini"); strcat(filename,INIDEF_FILENAME);
file=fopen(filename,"r"); file=fopen(filename,"r");
if (file == 0) if (file == 0)
{ {
@ -895,6 +904,39 @@ int Load_INI(T_Config * conf)
} }
} }
conf->Right_click_colorpick=0;
// Optional, right mouse button to pick colors (>=2.3)
if (!Load_INI_get_values (file,buffer,"Right_click_colorpick",1,values))
{
conf->Right_click_colorpick=(values[0]!=0);
}
conf->Sync_views=1;
// Optional, synced view of main and spare (>=2.3)
if (!Load_INI_get_values (file,buffer,"Sync_views",1,values))
{
conf->Sync_views=(values[0]!=0);
}
conf->Swap_buttons=0;
// Optional, key for swap buttons (>=2.3)
if (!Load_INI_get_values (file,buffer,"Swap_buttons",1,values))
{
switch(values[0])
{
case 1:
conf->Swap_buttons=MOD_CTRL;
break;
case 2:
conf->Swap_buttons=MOD_ALT;
break;
}
}
// Insert new values here
fclose(file); fclose(file);
free(filename); free(filename);

View File

@ -40,6 +40,13 @@
#include "windows.h" #include "windows.h"
#include "input.h" #include "input.h"
// Virtual keyboard is mandatory on these platforms:
#if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__)
#ifndef VIRT_KEY
#define VIRT_KEY 1
#endif
#endif
#define TEXT_COLOR MC_Black #define TEXT_COLOR MC_Black
#define BACKGROUND_COLOR MC_Light #define BACKGROUND_COLOR MC_Light
#define CURSOR_COLOR MC_Black #define CURSOR_COLOR MC_Black
@ -98,8 +105,41 @@ int Valid_character(int c)
void Display_whole_string(word x_pos,word y_pos,char * str,byte position) void Display_whole_string(word x_pos,word y_pos,char * str,byte position)
{ {
Print_in_window(x_pos,y_pos,str,TEXT_COLOR,BACKGROUND_COLOR); char cursor[2];
Print_char_in_window(x_pos+(position<<3),y_pos,str[position],CURSOR_COLOR,CURSOR_BACKGROUND_COLOR); Print_general(x_pos,y_pos,str,TEXT_COLOR,BACKGROUND_COLOR);
cursor[0]=str[position] ? str[position] : ' ';
cursor[1]='\0';
Print_general(x_pos+(position<<3)*Menu_factor_X,y_pos,cursor,CURSOR_COLOR,CURSOR_BACKGROUND_COLOR);
}
void Init_virtual_keyboard(word y_pos, word keyboard_width, word keyboard_height)
{
int h_pos;
int v_pos;
int parent_window_x=Window_pos_X+2;
h_pos= Window_pos_X+(keyboard_width-Window_width)*Menu_factor_X/-2;
if (h_pos<0)
h_pos=0;
else if (h_pos+keyboard_width*Menu_factor_X>Screen_width)
h_pos=Screen_width-keyboard_width*Menu_factor_X;
v_pos=Window_pos_Y+(y_pos+9)*Menu_factor_Y;
if (v_pos+(keyboard_height*Menu_factor_Y)>Screen_height)
v_pos=Window_pos_Y+(y_pos-keyboard_height-4)*Menu_factor_Y;
Hide_cursor();
Open_popup(h_pos,v_pos,keyboard_width,keyboard_height);
Window_rectangle(1,0,Window_width-1, Window_height-1, MC_Light);
Window_rectangle(0,0,1,Window_height-2, MC_White);
// white border on top left angle, when it exceeds border.
if (parent_window_x>Window_pos_X)
Window_rectangle(0,0,(parent_window_x-Window_pos_X)/Menu_factor_X, 1, MC_White);
Window_rectangle(2,Window_height-2,Window_width-2, 2, MC_Black);
if(keyboard_width<320)
{
Window_rectangle(Window_width-2,2,2,Window_height-2, MC_Black);
}
} }
/**************************************************************************** /****************************************************************************
@ -143,28 +183,156 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
byte size; byte size;
word input_key=0; word input_key=0;
byte is_authorized; byte is_authorized;
word window_x=Window_pos_X;
word window_y=Window_pos_Y;
byte offset=0; // index du premier caractère affiché byte offset=0; // index du premier caractère affiché
#ifdef VIRT_KEY
// Virtual keyboard
byte use_virtual_keyboard=0;
static byte caps_lock=0;
word keymapping[] =
{
SDLK_CLEAR,SDLK_BACKSPACE,SDLK_RETURN,KEY_ESC,
'0','1','2','3','4','5','6','7','8','9','.',',',
'Q','W','E','R','T','Y','U','I','O','P',
'A','S','D','F','G','H','J','K','L',
SDLK_CAPSLOCK,'Z','X','C','V','B','N','M',' ',
'-','+','*','/','|','\\',
'(',')','{','}','[',']',
'_','=','<','>','%','@',
':',';','`','\'','"','~',
'!','?','^','&','#','$'
};
#endif
// Si on a commencé à editer par un clic-droit, on vide la chaine. // Si on a commencé à editer par un clic-droit, on vide la chaine.
if (Mouse_K==RIGHT_SIDE) if (Mouse_K==RIGHT_SIDE)
str[0]='\0'; str[0]='\0';
else if (input_type==1 && str[0]!='\0') else if (input_type==INPUT_TYPE_INTEGER && str[0]!='\0')
snprintf(str,10,"%d",atoi(str)); // On tasse la chaine à gauche snprintf(str,10,"%d",atoi(str)); // On tasse la chaine à gauche
else if (input_type==3) else if (input_type==INPUT_TYPE_DECIMAL)
{ {
// Nothing. The caller should have used Sprint_double, with min_positions // Nothing. The caller should have used Sprint_double, with min_positions
// at zero, so there's no spaces on the left and no useless 0s on the right. // at zero, so there's no spaces on the left and no useless 0s on the right.
} }
else if (input_type==INPUT_TYPE_HEXA)
{
// Nothing. The caller should have initialized a valid hexa number.
}
Wait_end_of_click(); // Virtual keyboards
#ifdef VIRT_KEY
if (input_type == INPUT_TYPE_STRING || input_type == INPUT_TYPE_FILENAME )
{
int x,y;
Init_virtual_keyboard(y_pos, 320, 87);
use_virtual_keyboard=1;
// The order is important, see the array
Window_set_normal_button( 7,67,43,15,"Clr", 0,1,KEY_NONE);
Window_set_normal_button( 51,67,43,15,"Del", 0,1,KEY_NONE);
Window_set_normal_button( 95,67,43,15,"OK", 0,1,KEY_NONE);
Window_set_normal_button(139,67,43,15,"Esc", 0,1,KEY_NONE);
Window_display_frame_in(5,65,179,19);
Window_set_normal_button(193,63,17,19,"0", 0,1,KEY_NONE);
Window_set_normal_button(193,43,17,19,"1", 0,1,KEY_NONE);
Window_set_normal_button(211,43,17,19,"2", 0,1,KEY_NONE);
Window_set_normal_button(229,43,17,19,"3", 0,1,KEY_NONE);
Window_set_normal_button(193,23,17,19,"4", 0,1,KEY_NONE);
Window_set_normal_button(211,23,17,19,"5", 0,1,KEY_NONE);
Window_set_normal_button(229,23,17,19,"6", 0,1,KEY_NONE);
Window_set_normal_button(193, 3,17,19,"7", 0,1,KEY_NONE);
Window_set_normal_button(211, 3,17,19,"8", 0,1,KEY_NONE);
Window_set_normal_button(229, 3,17,19,"9", 0,1,KEY_NONE);
Window_set_normal_button(211,63,17,19,".", 0,1,KEY_NONE);
Window_set_normal_button(229,63,17,19,",", 0,1,KEY_NONE);
Window_set_normal_button( 3, 3,18,19,"Q", 0,1,KEY_NONE);
Window_set_normal_button( 22, 3,18,19,"W", 0,1,KEY_NONE);
Window_set_normal_button( 41, 3,18,19,"E", 0,1,KEY_NONE);
Window_set_normal_button( 60, 3,18,19,"R", 0,1,KEY_NONE);
Window_set_normal_button( 79, 3,18,19,"T", 0,1,KEY_NONE);
Window_set_normal_button( 98, 3,18,19,"Y", 0,1,KEY_NONE);
Window_set_normal_button(117, 3,18,19,"U", 0,1,KEY_NONE);
Window_set_normal_button(136, 3,18,19,"I", 0,1,KEY_NONE);
Window_set_normal_button(155, 3,18,19,"O", 0,1,KEY_NONE);
Window_set_normal_button(174, 3,18,19,"P", 0,1,KEY_NONE);
Window_set_normal_button( 12,23,18,19,"A", 0,1,KEY_NONE);
Window_set_normal_button( 31,23,18,19,"S", 0,1,KEY_NONE);
Window_set_normal_button( 50,23,18,19,"D", 0,1,KEY_NONE);
Window_set_normal_button( 69,23,18,19,"F", 0,1,KEY_NONE);
Window_set_normal_button( 88,23,18,19,"G", 0,1,KEY_NONE);
Window_set_normal_button(107,23,18,19,"H", 0,1,KEY_NONE);
Window_set_normal_button(126,23,18,19,"J", 0,1,KEY_NONE);
Window_set_normal_button(145,23,18,19,"K", 0,1,KEY_NONE);
Window_set_normal_button(164,23,18,19,"L", 0,1,KEY_NONE);
Window_set_normal_button( 3,43,18,19,caps_lock?"\036":"\037", 0,1,KEY_NONE);
Window_set_normal_button( 22,43,18,19,"Z", 0,1,KEY_NONE);
Window_set_normal_button( 41,43,18,19,"X", 0,1,KEY_NONE);
Window_set_normal_button( 60,43,18,19,"C", 0,1,KEY_NONE);
Window_set_normal_button( 79,43,18,19,"V", 0,1,KEY_NONE);
Window_set_normal_button( 98,43,18,19,"B", 0,1,KEY_NONE);
Window_set_normal_button(117,43,18,19,"N", 0,1,KEY_NONE);
Window_set_normal_button(136,43,18,19,"M", 0,1,KEY_NONE);
Window_set_normal_button(155,43,18,19," ", 0,1,KEY_NONE);
for (y=0; y<5; y++)
{
for (x=0; x<6; x++)
{
char label[2]=" ";
label[0]=keymapping[x+y*6+44];
Window_set_normal_button(247+x*12, 3+y*16,11,15,label, 0,1,KEY_NONE);
}
}
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
}
else if (input_type == INPUT_TYPE_INTEGER || input_type == INPUT_TYPE_DECIMAL )
{
Init_virtual_keyboard(y_pos, 215, 47);
use_virtual_keyboard=1;
// The order is important, see the array
Window_set_normal_button( 7,27,43,15,"Clr", 0,1,KEY_NONE);
Window_set_normal_button( 51,27,43,15,"Del", 0,1,KEY_NONE);
Window_set_normal_button( 95,27,43,15,"OK", 0,1,KEY_NONE);
Window_set_normal_button(139,27,43,15,"Esc", 0,1,KEY_NONE);
Window_display_frame_in(5,25,179,19);
Window_set_normal_button(174, 3,18,19,"0", 0,1,KEY_NONE);
Window_set_normal_button( 3, 3,18,19,"1", 0,1,KEY_NONE);
Window_set_normal_button( 22, 3,18,19,"2", 0,1,KEY_NONE);
Window_set_normal_button( 41, 3,18,19,"3", 0,1,KEY_NONE);
Window_set_normal_button( 60, 3,18,19,"4", 0,1,KEY_NONE);
Window_set_normal_button( 79, 3,18,19,"5", 0,1,KEY_NONE);
Window_set_normal_button( 98, 3,18,19,"6", 0,1,KEY_NONE);
Window_set_normal_button(117, 3,18,19,"7", 0,1,KEY_NONE);
Window_set_normal_button(136, 3,18,19,"8", 0,1,KEY_NONE);
Window_set_normal_button(155, 3,18,19,"9", 0,1,KEY_NONE);
Window_set_normal_button(193, 3,18,19,".", 0,1,KEY_NONE);
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
}
#endif
Keyboard_click_allowed = 0; Keyboard_click_allowed = 0;
Hide_cursor(); Hide_cursor();
// Effacement de la chaîne // Effacement de la chaîne
Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), Block(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR); visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR);
Update_rect(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), Update_rect(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3)); visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3));
// Mise à jour des variables se rapportant à la chaîne en fonction de la chaîne initiale // Mise à jour des variables se rapportant à la chaîne en fonction de la chaîne initiale
@ -182,19 +350,67 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
if (visible_size + offset + 1 < size ) if (visible_size + offset + 1 < size )
display_string[visible_size-1]=RIGHT_TRIANGLE_CHARACTER; display_string[visible_size-1]=RIGHT_TRIANGLE_CHARACTER;
Display_whole_string(x_pos,y_pos,display_string,position - offset); Display_whole_string(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),display_string,position - offset);
Update_rect(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), Update_rect(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3)); visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3));
Flush_update(); Flush_update();
if (Mouse_K)
while ((input_key!=SDLK_RETURN) && (input_key!=KEY_ESC) && Mouse_K == 0)
{ {
Display_cursor(); Display_cursor();
do Wait_end_of_click();
Hide_cursor();
}
while ((input_key!=SDLK_RETURN) && (input_key!=KEY_ESC))
{
Display_cursor();
#ifdef VIRT_KEY
if (use_virtual_keyboard)
{ {
if(!Get_input()) SDL_Delay(20); int clicked_button;
clicked_button=Window_clicked_button();
input_key=Key_ANSI; input_key=Key_ANSI;
} while(input_key==0 && Mouse_K == 0);
if (clicked_button==-1)
input_key=SDLK_RETURN;
else if (clicked_button>0)
{
input_key=keymapping[clicked_button-1];
if (input_key==SDLK_CAPSLOCK)
{
// toggle uppercase
caps_lock=!caps_lock;
Hide_cursor();
Print_in_window(8, 49,caps_lock?"\036":"\037", MC_Black,MC_Light);
Display_cursor();
}
else if (input_key==SDLK_BACKSPACE)
{
// A little hack: the button for backspace will:
// - backspace if the cursor is at end of string
// - delete otherwise
// It's needed for those input boxes that are completely full.
if (position<size)
input_key = SDLK_DELETE;
}
else if (input_key>='A' && input_key<='Z' && !caps_lock)
{
input_key+='a'-'A';
}
}
}
else
#endif
{
do
{
Get_input(20);
input_key=Key_ANSI;
if (Mouse_K)
input_key=SDLK_RETURN;
} while(input_key==0);
}
Hide_cursor(); Hide_cursor();
switch (input_key) switch (input_key)
{ {
@ -205,7 +421,7 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
size--; size--;
// Effacement de la chaîne // Effacement de la chaîne
Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), Block(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR); visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR);
goto affichage; goto affichage;
} }
@ -215,7 +431,7 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
{ {
// Effacement de la chaîne // Effacement de la chaîne
if (position==size) if (position==size)
Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), Block(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR); visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR);
position--; position--;
if (offset > 0 && (position == 0 || position < (offset + 1))) if (offset > 0 && (position == 0 || position < (offset + 1)))
@ -239,7 +455,7 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
{ {
// Effacement de la chaîne // Effacement de la chaîne
if (position==size) if (position==size)
Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), Block(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR); visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR);
position = 0; position = 0;
offset = 0; offset = 0;
@ -265,11 +481,18 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
Remove_character(str,position); Remove_character(str,position);
size--; size--;
// Effacement de la chaîne // Effacement de la chaîne
Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), Block(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR); visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR);
goto affichage; goto affichage;
} }
break; break;
case SDLK_CLEAR : // Clear
str[0]='\0';
position=offset=0;
// Effacement de la chaîne
Block(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR);
goto affichage;
case SDLK_RETURN : case SDLK_RETURN :
break; break;
@ -285,15 +508,15 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
is_authorized=0; // On commence par supposer qu'elle est interdite is_authorized=0; // On commence par supposer qu'elle est interdite
switch(input_type) switch(input_type)
{ {
case 0 : // N'importe quelle chaîne: case INPUT_TYPE_STRING :
if (input_key>=' ' && input_key<= 255) if (input_key>=' ' && input_key<= 255)
is_authorized=1; is_authorized=1;
break; break;
case 1 : // Nombre case INPUT_TYPE_INTEGER :
if ( (input_key>='0') && (input_key<='9') ) if ( (input_key>='0') && (input_key<='9') )
is_authorized=1; is_authorized=1;
break; break;
case 3: // Decimal number case INPUT_TYPE_DECIMAL:
if ( (input_key>='0') && (input_key<='9') ) if ( (input_key>='0') && (input_key<='9') )
is_authorized=1; is_authorized=1;
else if (input_key=='-' && position==0 && str[0]!='-') else if (input_key=='-' && position==0 && str[0]!='-')
@ -301,10 +524,18 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
else if (input_key=='.') else if (input_key=='.')
is_authorized=1; is_authorized=1;
break; break;
default : // Nom de fichier case INPUT_TYPE_FILENAME:
// On regarde si la touche est autorisée // On regarde si la touche est autorisée
if ( Valid_character(input_key)) if ( Valid_character(input_key))
is_authorized=1; is_authorized=1;
case INPUT_TYPE_HEXA:
if ( (input_key>='0') && (input_key<='9') )
is_authorized=1;
else if ( (input_key>='A') && (input_key<='F') )
is_authorized=1;
else if ( (input_key>='a') && (input_key<='f') )
is_authorized=1;
break;
} // End du "switch(input_type)" } // End du "switch(input_type)"
// Si la touche était autorisée... // Si la touche était autorisée...
@ -337,20 +568,29 @@ affichage:
if (visible_size + offset + 0 < size ) if (visible_size + offset + 0 < size )
display_string[visible_size-1]=RIGHT_TRIANGLE_CHARACTER; display_string[visible_size-1]=RIGHT_TRIANGLE_CHARACTER;
Display_whole_string(x_pos,y_pos,display_string,position - offset); Display_whole_string(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),display_string,position - offset);
Update_rect(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), Update_rect(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3)); visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3));
} // End du "switch(input_key)" } // End du "switch(input_key)"
Flush_update(); Flush_update();
} // End du "while" } // End du "while"
Keyboard_click_allowed = 1; Keyboard_click_allowed = 1;
#ifdef VIRT_KEY
if (use_virtual_keyboard)
{
byte old_mouse_k = Mouse_K;
Close_popup();
Mouse_K=old_mouse_k;
Input_sticky_control=0;
}
#endif
// Effacement de la chaîne // Effacement de la chaîne
Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), Block(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR); visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR);
// On raffiche la chaine correctement // On raffiche la chaine correctement
if (input_type==1) if (input_type==INPUT_TYPE_INTEGER)
{ {
if (str[0]=='\0') if (str[0]=='\0')
{ {
@ -359,7 +599,7 @@ affichage:
} }
Print_in_window(x_pos+((max_size-size)<<3),y_pos,str,TEXT_COLOR,BACKGROUND_COLOR); Print_in_window(x_pos+((max_size-size)<<3),y_pos,str,TEXT_COLOR,BACKGROUND_COLOR);
} }
else if (input_type==3) else if (input_type==INPUT_TYPE_DECIMAL)
{ {
double value; double value;
// Discard extra digits // Discard extra digits
@ -377,10 +617,10 @@ affichage:
{ {
Print_in_window_limited(x_pos,y_pos,str,visible_size,TEXT_COLOR,BACKGROUND_COLOR); Print_in_window_limited(x_pos,y_pos,str,visible_size,TEXT_COLOR,BACKGROUND_COLOR);
} }
Update_rect(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), Update_rect(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3)); visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3));
return (input_key==SDLK_RETURN || Mouse_K != 0); return (input_key==SDLK_RETURN);
} }
void Sprint_double(char *str, double value, byte decimal_places, byte min_positions) void Sprint_double(char *str, double value, byte decimal_places, byte min_positions)

View File

@ -24,13 +24,22 @@
/// Text input functions. /// Text input functions.
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
enum INPUT_TYPE
{
INPUT_TYPE_STRING=0, ///< Any string
INPUT_TYPE_INTEGER=1, ///< Decimal integer
INPUT_TYPE_FILENAME=2,///< Filename
INPUT_TYPE_DECIMAL=3, ///< Decimal value
INPUT_TYPE_HEXA=4, ///< Hexadecimal integer
};
/// ///
/// Lets the user input a line of text, exit by Esc or Return. /// Lets the user input a line of text, exit by Esc or Return.
/// @param x_pos Coordinates of input, in window coordinates before scaling. /// @param x_pos Coordinates of input, in window coordinates before scaling.
/// @param y_pos Coordinates of input, in window coordinates before scaling. /// @param y_pos Coordinates of input, in window coordinates before scaling.
/// @param str The original string value (will be modified, unless user cancels. /// @param str The original string value (will be modified, unless user cancels.
/// @param visible_size Number of characters visible and editable. /// @param visible_size Number of characters visible and editable.
/// @param input_type 0=string, 1=number, 2=filename (255 editable characters) /// @param input_type one of enum ::INPUT_TYPE
/// @return 0 if user cancelled (esc), 1 if accepted (return) /// @return 0 if user cancelled (esc), 1 if accepted (return)
byte Readline(word x_pos,word y_pos,char * str,byte visible_size,byte input_type); byte Readline(word x_pos,word y_pos,char * str,byte visible_size,byte input_type);
@ -41,7 +50,7 @@ byte Readline(word x_pos,word y_pos,char * str,byte visible_size,byte input_type
/// @param str The original string value (will be modified, unless user cancels. /// @param str The original string value (will be modified, unless user cancels.
/// @param visible_size Number of characters visible. /// @param visible_size Number of characters visible.
/// @param max_size Number of characters editable. /// @param max_size Number of characters editable.
/// @param input_type 0=string, 1=integer, 2=filename (255 editable characters) 3=decimal /// @param input_type one of enum ::INPUT_TYPE
/// @param decimal_places Number of decimal places (used only with decimal type) /// @param decimal_places Number of decimal places (used only with decimal type)
/// @return 0 if user cancelled (esc), 1 if accepted (return) /// @return 0 if user cancelled (esc), 1 if accepted (return)
byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_size, byte input_type, byte decimal_places); byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_size, byte input_type, byte decimal_places);

View File

@ -6,8 +6,11 @@
#include <fcntl.h> #include <fcntl.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#if defined(__AROS__)
#include <limits.h>
#endif
#if defined(__AROS__) || defined(__BEOS__) || defined(__MORPHOS__) || defined(__GP2X__) || defined(__amigaos__) #if defined(__AROS__) || defined(__BEOS__) || defined(__MORPHOS__) || defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__) || defined(__amigaos__)
// These platforms don't have realpath(). // These platforms don't have realpath().
// We use the following implementation, found in: // We use the following implementation, found in:
// http://amiga.sourceforge.net/amigadevhelp/FUNCTIONS/GeekGadgets/realpath/ex02_realpath.c // http://amiga.sourceforge.net/amigadevhelp/FUNCTIONS/GeekGadgets/realpath/ex02_realpath.c
@ -17,7 +20,7 @@
// the path. So this implementation is limited, it's really better to // the path. So this implementation is limited, it's really better to
// use realpath() if your platform has it. // use realpath() if your platform has it.
#if defined(__GP2X__) || defined(__amigaos__) #if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__) || defined(__amigaos__)
// This is a random default value ... // This is a random default value ...
#define PATH_MAX 32768 #define PATH_MAX 32768
#endif #endif

View File

@ -2,6 +2,7 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Peter Gordon Copyright 2008 Peter Gordon
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues
@ -30,6 +31,7 @@
#include "errors.h" #include "errors.h"
#include "misc.h" #include "misc.h"
#include "saveini.h" #include "saveini.h"
#include "setup.h"
int Save_INI_reach_group(FILE * old_file,FILE * new_file,char * buffer,char * group) int Save_INI_reach_group(FILE * old_file,FILE * new_file,char * buffer,char * group)
{ {
@ -393,8 +395,8 @@ void Save_INI_flush(FILE * old_file,FILE * new_file,char * buffer)
int Save_INI(T_Config * conf) int Save_INI(T_Config * conf)
{ {
FILE * Ancien_fichier; FILE * old_file;
FILE * Nouveau_fichier; FILE * new_file;
char * buffer; char * buffer;
int values[3]; int values[3];
char filename[MAX_PATH_CHARACTERS]; char filename[MAX_PATH_CHARACTERS];
@ -409,13 +411,13 @@ int Save_INI(T_Config * conf)
// On calcule les noms des fichiers qu'on manipule: // On calcule les noms des fichiers qu'on manipule:
strcpy(filename,Config_directory); strcpy(filename,Config_directory);
strcat(filename,"gfx2.ini"); strcat(filename,INI_FILENAME);
// On vérifie si le fichier INI existe // On vérifie si le fichier INI existe
if ((ini_file_exists = File_exists(filename))) if ((ini_file_exists = File_exists(filename)))
{ {
strcpy(temp_filename,Config_directory); strcpy(temp_filename,Config_directory);
strcat(temp_filename,"gfx2.$$$"); strcat(temp_filename,INISAVE_FILENAME);
// On renome l'ancienne version du fichier INI vers un fichier temporaire: // On renome l'ancienne version du fichier INI vers un fichier temporaire:
if (rename(filename,temp_filename)!=0) if (rename(filename,temp_filename)!=0)
@ -425,237 +427,237 @@ int Save_INI(T_Config * conf)
} }
// On récupère un fichier INI "propre" à partir de gfx2def.ini // On récupère un fichier INI "propre" à partir de gfx2def.ini
strcpy(ref_ini_file,Data_directory); strcpy(ref_ini_file,Data_directory);
strcat(ref_ini_file,"gfx2def.ini"); strcat(ref_ini_file,INIDEF_FILENAME);
Ancien_fichier=fopen(ref_ini_file,"rb"); old_file=fopen(ref_ini_file,"rb");
if (Ancien_fichier==0) if (old_file==0)
{ {
fclose(Ancien_fichier); fclose(old_file);
free(buffer); free(buffer);
return ERROR_INI_MISSING; return ERROR_INI_MISSING;
} }
Nouveau_fichier=fopen(filename,"wb"); new_file=fopen(filename,"wb");
if (Nouveau_fichier==0) if (new_file==0)
{ {
free(buffer); free(buffer);
return ERROR_SAVING_INI; return ERROR_SAVING_INI;
} }
if ((return_code=Save_INI_reach_group(Ancien_fichier,Nouveau_fichier,buffer,"[MOUSE]"))) if ((return_code=Save_INI_reach_group(old_file,new_file,buffer,"[MOUSE]")))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Mouse_sensitivity_index_x; values[0]=conf->Mouse_sensitivity_index_x;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"X_sensitivity",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"X_sensitivity",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Mouse_sensitivity_index_y; values[0]=conf->Mouse_sensitivity_index_y;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Y_sensitivity",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Y_sensitivity",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=0; values[0]=0;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"X_correction_factor",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"X_correction_factor",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=0; values[0]=0;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Y_correction_factor",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Y_correction_factor",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=(conf->Cursor)+1; values[0]=(conf->Cursor)+1;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Cursor_aspect",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Cursor_aspect",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
if ((return_code=Save_INI_reach_group(Ancien_fichier,Nouveau_fichier,buffer,"[MENU]"))) if ((return_code=Save_INI_reach_group(old_file,new_file,buffer,"[MENU]")))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Fav_menu_colors[2].R>>2; values[0]=conf->Fav_menu_colors[2].R>>2;
values[1]=conf->Fav_menu_colors[2].G>>2; values[1]=conf->Fav_menu_colors[2].G>>2;
values[2]=conf->Fav_menu_colors[2].B>>2; values[2]=conf->Fav_menu_colors[2].B>>2;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Light_color",3,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Light_color",3,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Fav_menu_colors[1].R>>2; values[0]=conf->Fav_menu_colors[1].R>>2;
values[1]=conf->Fav_menu_colors[1].G>>2; values[1]=conf->Fav_menu_colors[1].G>>2;
values[2]=conf->Fav_menu_colors[1].B>>2; values[2]=conf->Fav_menu_colors[1].B>>2;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Dark_color",3,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Dark_color",3,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Ratio; values[0]=conf->Ratio;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Menu_ratio",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Menu_ratio",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
if ((return_code=Save_INI_reach_group(Ancien_fichier,Nouveau_fichier,buffer,"[FILE_SELECTOR]"))) if ((return_code=Save_INI_reach_group(old_file,new_file,buffer,"[FILE_SELECTOR]")))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Show_hidden_files?1:0; values[0]=conf->Show_hidden_files?1:0;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Show_hidden_files",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Show_hidden_files",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Show_hidden_directories?1:0; values[0]=conf->Show_hidden_directories?1:0;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Show_hidden_directories",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Show_hidden_directories",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
/* values[0]=conf->Show_system_directories?1:0; /* values[0]=conf->Show_system_directories?1:0;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Show_system_directories",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Show_system_directories",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
*/ */
values[0]=conf->Timer_delay; values[0]=conf->Timer_delay;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Preview_delay",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Preview_delay",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Maximize_preview; values[0]=conf->Maximize_preview;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Maximize_preview",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Maximize_preview",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Find_file_fast; values[0]=conf->Find_file_fast;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Find_file_fast",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Find_file_fast",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
if ((return_code=Save_INI_reach_group(Ancien_fichier,Nouveau_fichier,buffer,"[LOADING]"))) if ((return_code=Save_INI_reach_group(old_file,new_file,buffer,"[LOADING]")))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Auto_set_res; values[0]=conf->Auto_set_res;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Auto_set_resolution",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Auto_set_resolution",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Set_resolution_according_to; values[0]=conf->Set_resolution_according_to;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Set_resolution_according_to",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Set_resolution_according_to",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Clear_palette; values[0]=conf->Clear_palette;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Clear_palette",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Clear_palette",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
if ((return_code=Save_INI_reach_group(Ancien_fichier,Nouveau_fichier,buffer,"[MISCELLANEOUS]"))) if ((return_code=Save_INI_reach_group(old_file,new_file,buffer,"[MISCELLANEOUS]")))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Display_image_limits; values[0]=conf->Display_image_limits;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Draw_limits",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Draw_limits",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Adjust_brush_pick; values[0]=conf->Adjust_brush_pick;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Adjust_brush_pick",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Adjust_brush_pick",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=2-conf->Coords_rel; values[0]=2-conf->Coords_rel;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Coordinates",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Coordinates",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Backup; values[0]=conf->Backup;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Backup",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Backup",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Max_undo_pages; values[0]=conf->Max_undo_pages;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Undo_pages",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Undo_pages",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Delay_left_click_on_slider; values[0]=conf->Delay_left_click_on_slider;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Gauges_scrolling_speed_Left",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Gauges_scrolling_speed_Left",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Delay_right_click_on_slider; values[0]=conf->Delay_right_click_on_slider;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Gauges_scrolling_speed_Right",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Gauges_scrolling_speed_Right",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Auto_save; values[0]=conf->Auto_save;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Auto_save",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Auto_save",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Nb_max_vertices_per_polygon; values[0]=conf->Nb_max_vertices_per_polygon;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Vertices_per_polygon",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Vertices_per_polygon",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Fast_zoom; values[0]=conf->Fast_zoom;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Fast_zoom",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Fast_zoom",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Separate_colors; values[0]=conf->Separate_colors;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Separate_colors",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Separate_colors",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->FX_Feedback; values[0]=conf->FX_Feedback;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"FX_feedback",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"FX_feedback",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Safety_colors; values[0]=conf->Safety_colors;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Safety_colors",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Safety_colors",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Opening_message; values[0]=conf->Opening_message;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Opening_message",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Opening_message",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Clear_with_stencil; values[0]=conf->Clear_with_stencil;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Clear_with_stencil",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Clear_with_stencil",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Auto_discontinuous; values[0]=conf->Auto_discontinuous;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Auto_discontinuous",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Auto_discontinuous",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Screen_size_in_GIF; values[0]=conf->Screen_size_in_GIF;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Save_screen_size_in_GIF",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Save_screen_size_in_GIF",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Auto_nb_used; values[0]=conf->Auto_nb_used;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Auto_nb_colors_used",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Auto_nb_colors_used",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
if ((return_code=Save_INI_set_strings (Ancien_fichier,Nouveau_fichier,buffer,"Default_video_mode",Mode_label(conf->Default_resolution)))) if ((return_code=Save_INI_set_strings (old_file,new_file,buffer,"Default_video_mode",Mode_label(conf->Default_resolution))))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=Video_mode[0].Width; values[0]=Video_mode[0].Width;
values[1]=Video_mode[0].Height; values[1]=Video_mode[0].Height;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Default_window_size",2,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Default_window_size",2,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=(conf->Mouse_merge_movement); values[0]=(conf->Mouse_merge_movement);
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Merge_movement",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Merge_movement",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=(conf->Palette_cells_X); values[0]=(conf->Palette_cells_X);
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Palette_cells_X",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Palette_cells_X",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=(conf->Palette_cells_Y); values[0]=(conf->Palette_cells_Y);
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Palette_cells_Y",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Palette_cells_Y",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
for (index=0;index<NB_BOOKMARKS;index++) for (index=0;index<NB_BOOKMARKS;index++)
{ {
if ((return_code=Save_INI_set_strings (Ancien_fichier,Nouveau_fichier,buffer,"Bookmark_label",conf->Bookmark_label[index]))) if ((return_code=Save_INI_set_strings (old_file,new_file,buffer,"Bookmark_label",conf->Bookmark_label[index])))
goto Erreur_Retour; goto Erreur_Retour;
if ((return_code=Save_INI_set_strings (Ancien_fichier,Nouveau_fichier,buffer,"Bookmark_directory",conf->Bookmark_directory[index]))) if ((return_code=Save_INI_set_strings (old_file,new_file,buffer,"Bookmark_directory",conf->Bookmark_directory[index])))
goto Erreur_Retour; goto Erreur_Retour;
} }
values[0]=(conf->Palette_vertical); values[0]=(conf->Palette_vertical);
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Palette_vertical",1,values,1))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Palette_vertical",1,values,1)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=conf->Window_pos_x; values[0]=conf->Window_pos_x;
values[1]=conf->Window_pos_y; values[1]=conf->Window_pos_y;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Window_position",2,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Window_position",2,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=(conf->Double_click_speed); values[0]=(conf->Double_click_speed);
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Double_click_speed",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Double_click_speed",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=(conf->Double_key_speed); values[0]=(conf->Double_key_speed);
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Double_key_speed",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Double_key_speed",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
if ((return_code=Save_INI_set_strings (Ancien_fichier,Nouveau_fichier,buffer,"Skin_file",conf->Skin_file))) if ((return_code=Save_INI_set_strings (old_file,new_file,buffer,"Skin_file",conf->Skin_file)))
goto Erreur_Retour; goto Erreur_Retour;
if ((return_code=Save_INI_set_strings (Ancien_fichier,Nouveau_fichier,buffer,"Font_file",conf->Font_file))) if ((return_code=Save_INI_set_strings (old_file,new_file,buffer,"Font_file",conf->Font_file)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=(conf->Grid_XOR_color); values[0]=(conf->Grid_XOR_color);
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Grid_XOR_color",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Grid_XOR_color",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=(Pixel_ratio); values[0]=(Pixel_ratio);
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Pixel_ratio",1,values,0))) { if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Pixel_ratio",1,values,0))) {
DEBUG("saving pixel ratio",return_code); DEBUG("saving pixel ratio",return_code);
goto Erreur_Retour; goto Erreur_Retour;
} }
@ -670,14 +672,37 @@ int Save_INI(T_Config * conf)
for (; index<8;index++) for (; index<8;index++)
values[0] |= (1<<index); values[0] |= (1<<index);
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Menubars_visible",1,values,0))) if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Menubars_visible",1,values,0)))
goto Erreur_Retour; goto Erreur_Retour;
values[0]=(conf->Right_click_colorpick);
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Right_click_colorpick",1,values,1)))
goto Erreur_Retour;
Save_INI_flush(Ancien_fichier,Nouveau_fichier,buffer); values[0]=(conf->Sync_views);
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Sync_views",1,values,1)))
goto Erreur_Retour;
fclose(Nouveau_fichier); switch(conf->Swap_buttons)
fclose(Ancien_fichier); {
case MOD_CTRL:
values[0]=1;
break;
case MOD_ALT:
values[0]=2;
break;
default:
values[0]=0;
}
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Swap_buttons",1,values,0)))
goto Erreur_Retour;
// Insert new values here
Save_INI_flush(old_file,new_file,buffer);
fclose(new_file);
fclose(old_file);
// On efface le fichier temporaire <=> Ancienne version du .INI // On efface le fichier temporaire <=> Ancienne version du .INI
if (ini_file_exists) if (ini_file_exists)
@ -689,8 +714,8 @@ int Save_INI(T_Config * conf)
Erreur_Retour: Erreur_Retour:
fclose(Nouveau_fichier); fclose(new_file);
fclose(Ancien_fichier); fclose(old_file);
free(buffer); free(buffer);
return return_code; return return_code;

View File

@ -2,6 +2,7 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues
@ -23,6 +24,15 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <SDL.h> #include <SDL.h>
#include <SDL_endian.h>
#if defined(__WIN32__)
#include <windows.h>
#endif
// There is no WM on the GP2X...
#ifndef __GP2X__
#include <SDL_syswm.h>
#endif
#include "global.h" #include "global.h"
#include "sdlscreen.h" #include "sdlscreen.h"
#include "errors.h" #include "errors.h"
@ -42,14 +52,21 @@
#ifndef UPDATE_METHOD #ifndef UPDATE_METHOD
#if defined(__macosx__) #if defined(__macosx__)
#define UPDATE_METHOD UPDATE_METHOD_FULL_PAGE #define UPDATE_METHOD UPDATE_METHOD_FULL_PAGE
#elif defined(__MINT__)
#define UPDATE_METHOD UPDATE_METHOD_CUMULATED
#else #else
#define UPDATE_METHOD UPDATE_METHOD_CUMULATED #define UPDATE_METHOD UPDATE_METHOD_CUMULATED
#endif #endif
#endif #endif
volatile int Allow_colorcycling=1;
/// Sets the new screen/window dimensions. /// Sets the new screen/window dimensions.
void Set_mode_SDL(int *width, int *height, int fullscreen) void Set_mode_SDL(int *width, int *height, int fullscreen)
{ {
static SDL_Cursor* cur = NULL;
static byte cursorData = 0;
Screen_SDL=SDL_SetVideoMode(*width,*height,8,(fullscreen?SDL_FULLSCREEN:0)|SDL_RESIZABLE); Screen_SDL=SDL_SetVideoMode(*width,*height,8,(fullscreen?SDL_FULLSCREEN:0)|SDL_RESIZABLE);
if(Screen_SDL != NULL) if(Screen_SDL != NULL)
{ {
@ -66,7 +83,15 @@ void Set_mode_SDL(int *width, int *height, int fullscreen)
{ {
DEBUG("Error: Unable to change video mode!",0); DEBUG("Error: Unable to change video mode!",0);
} }
SDL_ShowCursor(0); // Hide the SDL mouse cursor, we use our own
// Trick borrowed to Barrage (http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg737265.html) :
// Showing the cursor but setting it to fully transparent allows us to get absolute mouse coordinates,
// this means we can use tablet in fullscreen mode.
SDL_ShowCursor(1); // Hide the SDL mouse cursor, we use our own
SDL_FreeCursor(cur);
cur = SDL_CreateCursor(&cursorData, &cursorData, 1,1,0,0);
SDL_SetCursor(cur);
} }
#if (UPDATE_METHOD == UPDATE_METHOD_CUMULATED) #if (UPDATE_METHOD == UPDATE_METHOD_CUMULATED)
@ -194,16 +219,36 @@ byte Get_SDL_pixel_8(SDL_Surface *bmp, int x, int y)
return ((byte *)(bmp->pixels))[(y*bmp->pitch+x)]; return ((byte *)(bmp->pixels))[(y*bmp->pitch+x)];
} }
/// Writes a pixel in a 8-bit SDL surface.
void Set_SDL_pixel_8(SDL_Surface *bmp, int x, int y, byte color)
{
((byte *)(bmp->pixels))[(y*bmp->pitch+x)]=color;
}
/// Reads a pixel in a multi-byte SDL surface. /// Reads a pixel in a multi-byte SDL surface.
dword Get_SDL_pixel_hicolor(SDL_Surface *bmp, int x, int y) dword Get_SDL_pixel_hicolor(SDL_Surface *bmp, int x, int y)
{ {
byte * ptr;
switch(bmp->format->BytesPerPixel) switch(bmp->format->BytesPerPixel)
{ {
case 4: case 4:
default: default:
return *((dword *)((byte *)bmp->pixels+(y*bmp->pitch+x*4))); return *((dword *)((byte *)bmp->pixels+(y*bmp->pitch+x*4)));
case 3: case 3:
return *(((dword *)((byte *)bmp->pixels+(y*bmp->pitch+x*3)))) & 0xFFFFFF; // Reading a 4-byte number starting at an address that isn't a multiple
// of 2 (or 4?) is not supported on Caanoo console at least (ARM CPU)
// So instead, we will read the 3 individual bytes, and re-construct the
// "dword" expected by SDL.
ptr = ((byte *)bmp->pixels)+(y*bmp->pitch+x*3);
#ifdef SDL_LIL_ENDIAN
// Read ABC, output _CBA : Most Significant Byte is zero.
return (*ptr) | (*(ptr+1)<<8) | (*(ptr+2)<<16);
#else
// Read ABC, output ABC_ : Least Significant Byte is zero.
return ((*ptr)<<24) | (*(ptr+1)<<16) | (*(ptr+2)<<8);
#endif
case 2: case 2:
return *((word *)((byte *)bmp->pixels+(y*bmp->pitch+x*2))); return *((word *)((byte *)bmp->pixels+(y*bmp->pitch+x*2)));
} }
@ -257,3 +302,18 @@ void Clear_border(byte color)
} }
} }
/// Activates or desactivates file drag-dropping in program window.
void Allow_drag_and_drop(int flag)
{
// Inform Windows that we accept drag-n-drop events or not
#ifdef __WIN32__
SDL_SysWMinfo wminfo;
HWND hwnd;
SDL_VERSION(&wminfo.version);
SDL_GetWMInfo(&wminfo);
hwnd = wminfo.window;
DragAcceptFiles(hwnd,flag?TRUE:FALSE);
SDL_EventState (SDL_SYSWMEVENT,flag?SDL_ENABLE:SDL_DISABLE );
#endif
}

View File

@ -56,6 +56,8 @@ SDL_Color Color_to_SDL_color(byte);
byte Get_SDL_pixel_8(SDL_Surface *bmp, int x, int y); byte Get_SDL_pixel_8(SDL_Surface *bmp, int x, int y);
/// Reads a pixel in a multi-byte SDL surface. /// Reads a pixel in a multi-byte SDL surface.
dword Get_SDL_pixel_hicolor(SDL_Surface *bmp, int x, int y); dword Get_SDL_pixel_hicolor(SDL_Surface *bmp, int x, int y);
/// Writes a pixel in a 8-bit SDL surface.
void Set_SDL_pixel_8(SDL_Surface *bmp, int x, int y, byte color);
/// Convert a SDL Palette to a grafx2 palette /// Convert a SDL Palette to a grafx2 palette
void Get_SDL_Palette(const SDL_Palette * sdl_palette, T_Palette palette); void Get_SDL_Palette(const SDL_Palette * sdl_palette, T_Palette palette);
@ -65,4 +67,9 @@ void Get_SDL_Palette(const SDL_Palette * sdl_palette, T_Palette palette);
/// size, eg: 3x3 pixels in 1024x768 leaves 1 column on the right, 0 rows on bottom. /// size, eg: 3x3 pixels in 1024x768 leaves 1 column on the right, 0 rows on bottom.
void Clear_border(byte color); void Clear_border(byte color);
extern volatile int Allow_colorcycling;
/// Activates or desactivates file drag-dropping in program window.
void Allow_drag_and_drop(int flag);
#endif // SDLSCREEN_H_INCLUDED #endif // SDLSCREEN_H_INCLUDED

View File

@ -2,6 +2,7 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Peter Gordon Copyright 2008 Peter Gordon
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet Copyright 2008 Franck Charlet
@ -35,6 +36,9 @@
#import <sys/param.h> #import <sys/param.h>
#elif defined(__FreeBSD__) #elif defined(__FreeBSD__)
#import <sys/param.h> #import <sys/param.h>
#elif defined(__MINT__)
#include <mint/osbind.h>
#include <mint/sysbind.h>
#elif defined(__linux__) #elif defined(__linux__)
#include <limits.h> #include <limits.h>
#include <unistd.h> #include <unistd.h>
@ -44,7 +48,7 @@
#include "io.h" #include "io.h"
#include "setup.h" #include "setup.h"
#if defined(__GP2X__) #if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__)
// This is a random default value ... // This is a random default value ...
#define PATH_MAX 32768 #define PATH_MAX 32768
#endif #endif
@ -84,7 +88,16 @@ void Set_program_directory(ARG_UNUSED const char * argv0,char * program_dir)
// AmigaOS and alike: hard-coded volume name. // AmigaOS and alike: hard-coded volume name.
#elif defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__) #elif defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
strcpy(program_dir,"PROGDIR:"); strcpy(program_dir,"PROGDIR:");
#elif defined(__MINT__)
static char path[1024]={0};
char currentDrive='A';
currentDrive=currentDrive+Dgetdrv();
Dgetpath(path,0);
sprintf(program_dir,"%c:\%s",currentDrive,path);
// Append trailing slash
strcat(program_dir,PATH_SEPARATOR);
// Linux: argv[0] unreliable // Linux: argv[0] unreliable
#elif defined(__linux__) #elif defined(__linux__)
if (argv0[0]!='/') if (argv0[0]!='/')
@ -115,9 +128,14 @@ void Set_data_directory(const char * program_dir, char * data_dir)
#if defined(__macosx__) #if defined(__macosx__)
strcat(data_dir,"Contents/Resources/"); strcat(data_dir,"Contents/Resources/");
// On GP2X, executable is not in bin/ // On GP2X, executable is not in bin/
#elif defined (__gp2x__) #elif defined (__GP2X__) || defined (__gp2x__) || defined (__WIZ__) || defined (__CAANOO__)
strcat(data_dir,"share/grafx2/"); strcat(data_dir,"share/grafx2/");
//on tos the same directory
#elif defined (__MINT__)
strcpy(data_dir, program_dir);
// All other targets, program is in a "bin" subdirectory // All other targets, program is in a "bin" subdirectory
#elif defined (__AROS__)
strcat(data_dir,"/share/grafx2/");
#else #else
strcat(data_dir,"../share/grafx2/"); strcat(data_dir,"../share/grafx2/");
#endif #endif
@ -140,21 +158,23 @@ void Set_config_directory(const char * program_dir, char * config_dir)
#if defined(__amigaos4__) || defined(__AROS__) #if defined(__amigaos4__) || defined(__AROS__)
strcpy(config_dir,"PROGDIR:"); strcpy(config_dir,"PROGDIR:");
// GP2X // GP2X
#elif defined(__GP2X__) #elif defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__)
// On the GP2X, the program is installed to the sdcard, and we don't want to mess with the system tree which is // On the GP2X, the program is installed to the sdcard, and we don't want to mess with the system tree which is
// on an internal flash chip. So, keep these settings locals. // on an internal flash chip. So, keep these settings locals.
strcpy(config_dir,program_dir); strcpy(config_dir,program_dir);
#elif defined(__MINT__)
strcpy(config_dir,program_dir);
#else #else
char filename[MAX_PATH_CHARACTERS]; char filename[MAX_PATH_CHARACTERS];
// In priority: check root directory // In priority: check root directory
strcpy(config_dir, program_dir); strcpy(config_dir, program_dir);
// On all these targets except OSX and GP2X, the executable is in ./bin // On all the remaining targets except OSX, the executable is in ./bin
#if !defined(__macosx__) && !defined(__gp2x__) #if !defined(__macosx__)
strcat(config_dir, "../"); strcat(config_dir, "../");
#endif #endif
strcpy(filename, config_dir); strcpy(filename, config_dir);
strcat(filename, "gfx2.cfg"); strcat(filename, CONFIG_FILENAME);
if (!File_exists(filename)) if (!File_exists(filename))
{ {
@ -171,6 +191,10 @@ void Set_config_directory(const char * program_dir, char * config_dir)
// "~/Library/Preferences/com.googlecode.grafx2" // "~/Library/Preferences/com.googlecode.grafx2"
const char* Config_SubDir = "Library/Preferences/com.googlecode.grafx2"; const char* Config_SubDir = "Library/Preferences/com.googlecode.grafx2";
config_parent_dir = getenv("HOME"); config_parent_dir = getenv("HOME");
#elif defined(__MINT__)
const char* Config_SubDir = "";
printf("GFX2.CFG not found in %s\n",filename);
strcpy(config_parent_dir, config_dir);
#else #else
// "~/.grafx2" // "~/.grafx2"
const char* Config_SubDir = ".grafx2"; const char* Config_SubDir = ".grafx2";
@ -203,7 +227,7 @@ void Set_config_directory(const char * program_dir, char * config_dir)
{ {
// Echec: on se rabat sur le repertoire de l'executable. // Echec: on se rabat sur le repertoire de l'executable.
strcpy(config_dir,program_dir); strcpy(config_dir,program_dir);
#if !defined(__macosx__) && !defined(__gp2x__) #if defined(__macosx__)
strcat(config_dir, "../"); strcat(config_dir, "../");
#endif #endif
} }

View File

@ -2,6 +2,7 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Peter Gordon Copyright 2008 Peter Gordon
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet Copyright 2008 Franck Charlet
@ -54,3 +55,103 @@ void Set_data_directory(const char * program_dir, char * data_dir);
/// OUT: Write into config_dir. Trailing / or \ is kept. /// OUT: Write into config_dir. Trailing / or \ is kept.
void Set_config_directory(const char * program_dir, char * config_dir); void Set_config_directory(const char * program_dir, char * config_dir);
/// Name of the subdirectory containing fonts, under the data directory (::Set_data_directory())
#if defined (__MINT__)
#define FONTS_SUBDIRECTORY "FONTS"
#else
#define FONTS_SUBDIRECTORY "fonts"
#endif
/// Name of the subdirectory containing fonts, under the data directory (::Set_data_directory())
#if defined (__MINT__)
#define SKINS_SUBDIRECTORY "SKINS"
#else
#define SKINS_SUBDIRECTORY "skins"
#endif
/// Name of the binary file containing some configuration settings.
#if defined (__MINT__)
#define CONFIG_FILENAME "GFX2.CFG"
#else
#define CONFIG_FILENAME "gfx2.cfg"
#endif
/// Name of the text file containing some settings in INI format.
#if defined (__MINT__)
#define INI_FILENAME "GFX2.INI"
#else
#define INI_FILENAME "gfx2.ini"
#endif
/// Name of the backup of the INI file.
#if defined (__MINT__)
#define INISAVE_FILENAME "GFX2.$$$"
#else
#define INISAVE_FILENAME "gfx2.$$$"
#endif
/// Name of the default .INI file (read-only: gives .INI format and defaults)
#if defined (__MINT__)
#define INIDEF_FILENAME "GFX2DEF.INI"
#else
#define INIDEF_FILENAME "gfx2def.ini"
#endif
/// Prefix for filenames of safety backups (main)
#if defined (__MINT__)
#define SAFETYBACKUP_PREFIX_A "A"
#else
#define SAFETYBACKUP_PREFIX_A "a"
#endif
/// Prefix for filenames of safety backups (spare)
#if defined (__MINT__)
#define SAFETYBACKUP_PREFIX_B "B"
#else
#define SAFETYBACKUP_PREFIX_B "b"
#endif
/// Name of the image file that serves as an application icon.
#if defined (__MINT__)
#define GFX2_ICON_FILENAME "GFX2.GIF"
#else
#define GFX2_ICON_FILENAME "gfx2.gif"
#endif
/// Name of the image file for the default (and fallback) GUI skin.
#if defined (__MINT__)
#define DEFAULT_SKIN_FILENAME "SDPAINT.PNG"
#else
#define DEFAULT_SKIN_FILENAME "skin_DPaint.png"
#endif
/// Name of the image file for the default (and fallback) 8x8 font.
#if defined (__MINT__)
#define DEFAULT_FONT_FILENAME "FDPAINT.PNG"
#else
#define DEFAULT_FONT_FILENAME "font_DPaint.png"
#endif
/// File extension for safety backups
#if defined (__MINT__)
#define BACKUP_FILE_EXTENSION ".BKP"
#else
#define BACKUP_FILE_EXTENSION ".bkp"
#endif
/// File prefix for fonts
#if defined (__MINT__)
#define FONT_PREFIX "F"
#else
#define FONT_PREFIX "font_"
#endif
/// File prefix for skins
#if defined (__MINT__)
#define SKIN_PREFIX "S"
#else
#define SKIN_PREFIX "skin_"
#endif

View File

@ -348,7 +348,7 @@ short Wait_click_in_shade_table()
while (selected_cell<0) while (selected_cell<0)
{ {
Get_input(); Get_input(20);
if ( (Mouse_K==LEFT_SIDE) if ( (Mouse_K==LEFT_SIDE)
&& ( ( (Window_click_in_rectangle(8,127,263,179)) && (((((Mouse_Y-Window_pos_Y)/Menu_factor_Y)-127)%7)<4) ) && ( ( (Window_click_in_rectangle(8,127,263,179)) && (((((Mouse_Y-Window_pos_Y)/Menu_factor_Y)-127)%7)<4) )
@ -837,7 +837,7 @@ int Menu_shade(void)
case 15 : // Saisie du pas case 15 : // Saisie du pas
Num2str(Shade_list[Shade_current].Step,str,3); Num2str(Shade_list[Shade_current].Step,str,3);
Readline(276,176,str,3,1); Readline(276,176,str,3,INPUT_TYPE_INTEGER);
temp=atoi(str); temp=atoi(str);
// On corrige le pas // On corrige le pas
if (!temp) if (!temp)
@ -1089,7 +1089,7 @@ void Button_Quick_shade_menu(void)
case 4 : // Saisie du pas case 4 : // Saisie du pas
Num2str(Quick_shade_step,str,3); Num2str(Quick_shade_step,str,3);
Readline(42,21,str,3,1); Readline(42,21,str,3,INPUT_TYPE_INTEGER);
temp=atoi(str); temp=atoi(str);
// On corrige le pas // On corrige le pas
if (!temp) if (!temp)

View File

@ -431,6 +431,9 @@ void Transparency_set(byte amount)
break; break;
case 2 : case 2 :
Effect_function=Effect_substractive_colorize; Effect_function=Effect_substractive_colorize;
break;
case 3 :
Effect_function=Effect_alpha_colorize;
} }
Shade_mode=0; Shade_mode=0;
Quick_shade_mode=0; Quick_shade_mode=0;

View File

@ -2,6 +2,7 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
@ -73,14 +74,23 @@ typedef void (* Func_draw_brush) (byte *,word,word,word,word,word,word,byte,word
typedef void (* Func_draw_list_item) (word,word,word,byte); ///< Draw an item inside a list button. This is done with a callback so it is possible to draw anything, as the list itself doesn't handle the content typedef void (* Func_draw_list_item) (word,word,word,byte); ///< Draw an item inside a list button. This is done with a callback so it is possible to draw anything, as the list itself doesn't handle the content
/// A set of RGB values. /// A set of RGB values.
#ifdef __GNUC__
typedef struct
{
byte R; ///< Red
byte G; ///< Green
byte B; ///< Blue
} __attribute__((__packed__)) T_Components, T_Palette[256] ; ///< A complete 256-entry RGB palette (768 bytes).
#else
#pragma pack(1) #pragma pack(1)
typedef struct typedef struct
{ {
byte R; ///< Red byte R; ///< Red
byte G; ///< Green byte G; ///< Green
byte B; ///< Blue byte B; ///< Blue
} T_Components, T_Palette[256]; ///< A complete 256-entry RGB palette (768 bytes). } T_Components, T_Palette[256] ; ///< A complete 256-entry RGB palette (768 bytes).
#pragma pack() #pragma pack()
#endif
/// A normal rectangular button in windows and menus. /// A normal rectangular button in windows and menus.
typedef struct T_Normal_button typedef struct T_Normal_button
@ -105,17 +115,18 @@ typedef struct T_Palette_button
struct T_Palette_button * Next;///< Pointer to the next palette of current window. struct T_Palette_button * Next;///< Pointer to the next palette of current window.
} T_Palette_button; } T_Palette_button;
/// A window control that represents a vertical scrollbar, with a slider, and two arrow buttons. /// A window control that represents a scrollbar, with a slider, and two arrow buttons.
typedef struct T_Scroller_button typedef struct T_Scroller_button
{ {
short Number; ///< Unique identifier for all controls short Number; ///< Unique identifier for all controls
byte Is_horizontal; ///< Boolean: True if slider is horizontal instead of vertical.
word Pos_X; ///< Coordinate for top of button, relative to the window, before scaling. word Pos_X; ///< Coordinate for top of button, relative to the window, before scaling.
word Pos_Y; ///< Coordinate for left of button, relative to the window, before scaling. word Pos_Y; ///< Coordinate for left of button, relative to the window, before scaling.
word Height; ///< Height before scaling. word Length; ///< Length before scaling.
word Nb_elements; ///< Number of distinct values it can take. word Nb_elements; ///< Number of distinct values it can take.
word Nb_visibles; ///< If this slider is meant to show several elements of a collection, this is their number (otherwise, it's 1). word Nb_visibles; ///< If this slider is meant to show several elements of a collection, this is their number (otherwise, it's 1).
word Position; ///< Current position of the slider: which item it's pointing. word Position; ///< Current position of the slider: which item it's pointing.
word Cursor_height; ///< Vertical dimension of the slider, in pixels before scaling. word Cursor_length; ///< Dimension of the slider, in pixels before scaling.
struct T_Scroller_button * Next;///< Pointer to the next scroller of current window. struct T_Scroller_button * Next;///< Pointer to the next scroller of current window.
} T_Scroller_button; } T_Scroller_button;
@ -162,12 +173,20 @@ typedef struct T_Dropdown_button
/// Data for one item (file, directory) in a fileselector. /// Data for one item (file, directory) in a fileselector.
typedef struct T_Fileselector_item typedef struct T_Fileselector_item
{ {
char Short_name[19]; ///< Name to display.
char Full_name[256]; ///< Filesystem value. char Full_name[256]; ///< Filesystem value.
byte Type; ///< Type of item: 0 = File, 1 = Directory, 2 = Drive byte Type; ///< Type of item: 0 = File, 1 = Directory, 2 = Drive
byte Icon; ///< One of ::ICON_TYPES, ICON_NONE for none.
struct T_Fileselector_item * Next; ///< Pointer to next item of the current fileselector. struct T_Fileselector_item * Next; ///< Pointer to next item of the current fileselector.
struct T_Fileselector_item * Previous;///< Pointer to previous item of the current fileselector. struct T_Fileselector_item * Previous;///< Pointer to previous item of the current fileselector.
word Length_short_name; ///< Number of bytes allocated for :Short_name
#if __GNUC__ < 3
char Short_name[0]; ///< Name to display.
#else
char Short_name[]; ///< Name to display.
#endif
// No field after Short_name[] ! Dynamic allocation according to name length.
} T_Fileselector_item; } T_Fileselector_item;
/// Data for a fileselector /// Data for a fileselector
@ -201,6 +220,25 @@ typedef struct T_List_button
struct T_List_button * Next; ///< Pointer to the next list button of current window. struct T_List_button * Next; ///< Pointer to the next list button of current window.
} T_List_button; } T_List_button;
/// A stackable window (editor screen)
typedef struct
{
word Pos_X;
word Pos_Y;
word Width;
word Height;
word Nb_buttons;
T_Normal_button *Normal_button_list;
T_Palette_button *Palette_button_list;
T_Scroller_button *Scroller_button_list;
T_Special_button *Special_button_list;
T_Dropdown_button *Dropdown_button_list;
T_List_button *List_button_list;
int Attribute1;
int Attribute2;
byte Draggable;
} T_Window;
/// Data for one line of the "Help" screens. /// Data for one line of the "Help" screens.
typedef struct { typedef struct {
char Line_type; ///< Kind of line: 'N' for normal line, 'S' for a bold line, 'K' for a line with keyboard shortcut, 'T' and '-' for upper and lower titles. char Line_type; ///< Kind of line: 'N' for normal line, 'S' for a bold line, 'K' for a line with keyboard shortcut, 'T' and '-' for upper and lower titles.
@ -223,7 +261,15 @@ typedef struct
dword Inverse; ///< Boolean, true if the gradient goes in descending order dword Inverse; ///< Boolean, true if the gradient goes in descending order
dword Mix; ///< Amount of randomness to add to the mix (0-255) dword Mix; ///< Amount of randomness to add to the mix (0-255)
dword Technique;///< Gradient technique: 0 (no pattern) 1 (dithering), or 2 (big dithering) dword Technique;///< Gradient technique: 0 (no pattern) 1 (dithering), or 2 (big dithering)
} T_Gradient_array; byte Speed; ///< Speed of cycling. 0 for disabled, 1-64 otherwise.
} T_Gradient_range;
/// Data for a full set of gradients.
typedef struct
{
int Used; ///< Reference count
T_Gradient_range Range[16];
} T_Gradient_array;
/// Data for one setting of shade. Warning, this one is saved/loaded as binary. /// Data for one setting of shade. Warning, this one is saved/loaded as binary.
typedef struct typedef struct
@ -233,7 +279,6 @@ typedef struct
byte Mode; ///< Shade mode: Normal, Loop, or No-saturation see ::SHADE_MODES byte Mode; ///< Shade mode: Normal, Loop, or No-saturation see ::SHADE_MODES
} T_Shade; } T_Shade;
#pragma pack(1) // is it useful ?
/// Data for one fullscreen video mode in configuration file. Warning, this one is saved/loaded as binary. /// Data for one fullscreen video mode in configuration file. Warning, this one is saved/loaded as binary.
typedef struct typedef struct
{ {
@ -242,8 +287,7 @@ typedef struct
word Height;///< Videomode height in pixels. word Height;///< Videomode height in pixels.
} T_Config_video_mode; } T_Config_video_mode;
/// Header for gfx2.cfg
/// Header for gfx2.cfg. Warning, this one is saved/loaded as binary.
typedef struct typedef struct
{ {
char Signature[3]; ///< Signature for the file format. "CFG". char Signature[3]; ///< Signature for the file format. "CFG".
@ -253,24 +297,22 @@ typedef struct
byte Beta2; ///< Major beta version number (ex: 5) byte Beta2; ///< Major beta version number (ex: 5)
} T_Config_header; } T_Config_header;
#pragma pack() /// Header for a config chunk in for gfx2.cfg
/// Header for a config chunk in for gfx2.cfg. Warning, this one is saved/loaded as binary.
typedef struct typedef struct
{ {
byte Number; ///< Section identfier. Possible values are in enum ::CHUNKS_CFG byte Number; ///< Section identfier. Possible values are in enum ::CHUNKS_CFG
word Size; ///< Size of the configuration block that follows, in bytes. word Size; ///< Size of the configuration block that follows, in bytes.
} T_Config_chunk; } T_Config_chunk;
#pragma pack(1)
/// Configuration for one keyboard shortcut in gfx2.cfg. Warning, this one is saved/loaded as binary. /// Configuration for one keyboard shortcut in gfx2.cfg
typedef struct typedef struct
{ {
word Number; ///< Indicates the shortcut action. This is a number starting from 0, which matches ::T_Key_config.Number word Number; ///< Indicates the shortcut action. This is a number starting from 0, which matches ::T_Key_config.Number
word Key; ///< Keyboard shortcut: SDLK_something, or -1 for none word Key; ///< Keyboard shortcut: SDLK_something, or -1 for none
word Key2; ///< Alternate keyboard shortcut: SDLK_something, or -1 for none word Key2; ///< Alternate keyboard shortcut: SDLK_something, or -1 for none
} T_Config_shortcut_info; } T_Config_shortcut_info;
#pragma pack()
/// This structure holds all the settings saved and loaded as gfx2.ini. /// This structure holds all the settings saved and loaded as gfx2.ini.
typedef struct typedef struct
@ -321,6 +363,10 @@ typedef struct
word Double_click_speed; ///< Maximum delay for double-click, in ms. word Double_click_speed; ///< Maximum delay for double-click, in ms.
word Double_key_speed; ///< Maximum delay for double-keypress, in ms. word Double_key_speed; ///< Maximum delay for double-keypress, in ms.
byte Grid_XOR_color; ///< XOR value to apply for grid color. byte Grid_XOR_color; ///< XOR value to apply for grid color.
byte Right_click_colorpick; ///< Boolean, true to enable a "tablet" mode, where RMB acts as instant colorpicker
byte Sync_views; ///< Boolean, true when the Main and Spare should share their viewport settings.
byte Stylus_mode; ///< Boolean, true to tweak some tools (eg:Curve) for single-button stylus.
word Swap_buttons; ///< Sets which key swaps mouse buttons : 0=none, or MOD_CTRL, or MOD_ALT.
} T_Config; } T_Config;
// Structures utilisées pour les descriptions de pages et de liste de pages. // Structures utilisées pour les descriptions de pages et de liste de pages.
@ -347,6 +393,7 @@ typedef struct T_Page
byte File_format; ///< File format, in enum ::FILE_FORMATS byte File_format; ///< File format, in enum ::FILE_FORMATS
struct T_Page *Next; ///< Pointer to the next backup struct T_Page *Next; ///< Pointer to the next backup
struct T_Page *Prev; ///< Pointer to the previous backup struct T_Page *Prev; ///< Pointer to the previous backup
T_Gradient_array *Gradients; ///< Pointer to the gradients used by the image.
byte Background_transparent; ///< Boolean, true if Layer 0 should have transparent pixels byte Background_transparent; ///< Boolean, true if Layer 0 should have transparent pixels
byte Transparent_color; ///< Index of transparent color. 0 to 255. byte Transparent_color; ///< Index of transparent color. 0 to 255.
byte Nb_layers; ///< Number of layers byte Nb_layers; ///< Number of layers
@ -381,6 +428,7 @@ typedef struct
word Height; word Height;
byte * Brush; /// < Color brush (if any) byte * Brush; /// < Color brush (if any)
T_Palette Palette; T_Palette Palette;
byte Colormap[256];
byte Transp_color; byte Transp_color;
} T_Brush_template; } T_Brush_template;
@ -396,21 +444,6 @@ typedef struct
/// Graphic resources for the mouse cursor. /// Graphic resources for the mouse cursor.
byte Cursor_sprite[NB_CURSOR_SPRITES][CURSOR_SPRITE_HEIGHT][CURSOR_SPRITE_WIDTH]; byte Cursor_sprite[NB_CURSOR_SPRITES][CURSOR_SPRITE_HEIGHT][CURSOR_SPRITE_WIDTH];
// Preset paintbrushes
/// Graphic resources for the preset paintbrushes.
byte Paintbrush_sprite [NB_PAINTBRUSH_SPRITES][PAINTBRUSH_HEIGHT][PAINTBRUSH_WIDTH];
/// Width of the preset paintbrushes.
word Preset_paintbrush_width[NB_PAINTBRUSH_SPRITES];
/// Height of the preset paintbrushes.
word Preset_paintbrush_height[NB_PAINTBRUSH_SPRITES];
/// Type of the preset paintbrush: index in enum PAINTBRUSH_SHAPES
byte Paintbrush_type[NB_PAINTBRUSH_SPRITES];
/// Brush handle for the preset brushes. Generally ::Preset_paintbrush_width[]/2
word Preset_paintbrush_offset_X[NB_PAINTBRUSH_SPRITES];
/// Brush handle for the preset brushes. Generally ::Preset_paintbrush_height[]/2
word Preset_paintbrush_offset_Y[NB_PAINTBRUSH_SPRITES];
// Sieve patterns // Sieve patterns
/// Preset sieve patterns, stored as binary (one word per line) /// Preset sieve patterns, stored as binary (one word per line)
@ -419,13 +452,13 @@ typedef struct
// Menu and other graphics // Menu and other graphics
/// Bitmap data for the menu, a single rectangle. /// Bitmap data for the menu, a single rectangle.
byte Menu_block[35][MENU_WIDTH]; byte Menu_block[3][35][MENU_WIDTH];
byte Layerbar_block[10][144]; byte Layerbar_block[3][10][144];
byte Statusbar_block[9][20]; byte Statusbar_block[3][9][20];
/// Bitmap data for the icons that are displayed over the menu. /// Bitmap data for the icons that are displayed over the menu.
byte Menu_sprite[NB_MENU_SPRITES][MENU_SPRITE_HEIGHT][MENU_SPRITE_WIDTH]; byte Menu_sprite[2][NB_MENU_SPRITES][MENU_SPRITE_HEIGHT][MENU_SPRITE_WIDTH];
/// Bitmap data for the different "effects" icons. /// Bitmap data for the different "effects" icons.
byte Effect_sprite[NB_EFFECTS_SPRITES][MENU_SPRITE_HEIGHT][MENU_SPRITE_WIDTH]; byte Effect_sprite[NB_EFFECTS_SPRITES][EFFECT_SPRITE_HEIGHT][EFFECT_SPRITE_WIDTH];
/// Bitmap data for the different Layer icons. /// Bitmap data for the different Layer icons.
byte Layer_sprite[3][16][LAYER_SPRITE_HEIGHT][LAYER_SPRITE_WIDTH]; byte Layer_sprite[3][16][LAYER_SPRITE_HEIGHT][LAYER_SPRITE_WIDTH];
/// Bitmap data for the Grafx2 logo that appears on splash screen. All 256 colors allowed. /// Bitmap data for the Grafx2 logo that appears on splash screen. All 256 colors allowed.
@ -458,16 +491,33 @@ typedef struct
/// Transparent GUI color index in skin file /// Transparent GUI color index in skin file
byte Color_trans; byte Color_trans;
} T_Gui_skin; } T_Gui_skin;
typedef struct {
// Preset paintbrushes
/// Graphic resources for the preset paintbrushes.
byte Sprite[PAINTBRUSH_HEIGHT][PAINTBRUSH_WIDTH];
/// Width of the preset paintbrushes.
word Width;
/// Height of the preset paintbrushes.
word Height;
/// Type of the preset paintbrush: index in enum PAINTBRUSH_SHAPES
byte Shape;
/// Brush handle for the preset brushes. Generally ::Width[]/2
word Offset_X;
/// Brush handle for the preset brushes. Generally ::Height[]/2
word Offset_Y;
} T_Paintbrush;
// A menubar. // A menubar.
typedef struct { typedef struct {
word Width; word Width;
word Height; word Height;
byte Visible; byte Visible;
word Top; ///< Relative to the top line of the menu, hidden bars don't count. word Top; ///< Relative to the top line of the menu, hidden bars don't count.
byte* Skin; byte* Skin[3]; ///< [0] has normal buttons, [1] has selected buttons, [2] is current.
word Skin_width; word Skin_width;
byte Last_button_index; byte Last_button_index;
} T_Menu_Bar; } T_Menu_Bar;

View File

@ -2,6 +2,7 @@
*/ */
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet Copyright 2008 Franck Charlet
Copyright 2008 Adrien Destugues Copyright 2008 Adrien Destugues
@ -36,19 +37,18 @@
#include <SDL_ttf.h> #include <SDL_ttf.h>
#endif #endif
#if defined(__linux__) #if defined(__CAANOO__) || defined(__WIZ__) || defined(__GP2X__)
#if defined(__macosx__) // No X11
#elif defined(__macosx__)
#include <Carbon/Carbon.h> #include <Carbon/Carbon.h>
#import <corefoundation/corefoundation.h> #import <corefoundation/corefoundation.h>
#import <sys/param.h> #import <sys/param.h>
#else #elif defined(__linux__)
#include <X11/Xlib.h> #include <X11/Xlib.h>
#endif #endif
#endif #endif
#endif
#include <SDL_image.h> #include <SDL_image.h>
// SFont
#include "SFont.h" #include "SFont.h"
#include "struct.h" #include "struct.h"
@ -56,6 +56,9 @@
#include "sdlscreen.h" #include "sdlscreen.h"
#include "io.h" #include "io.h"
#include "errors.h" #include "errors.h"
#include "windows.h"
#include "misc.h"
#include "setup.h"
typedef struct T_Font typedef struct T_Font
{ {
@ -282,7 +285,7 @@ void Init_text(void)
Nb_fonts=0; Nb_fonts=0;
// Parcours du répertoire "fonts" // Parcours du répertoire "fonts"
strcpy(directory_name, Data_directory); strcpy(directory_name, Data_directory);
strcat(directory_name, "fonts"); strcat(directory_name, FONTS_SUBDIRECTORY);
For_each_file(directory_name, Add_font); For_each_file(directory_name, Add_font);
#if defined(__WIN32__) #if defined(__WIN32__)
@ -321,6 +324,8 @@ void Init_text(void)
CFRelease(url); CFRelease(url);
#endif #endif
#elif defined(__CAANOO__) || defined(__WIZ__) || defined(__GP2X__)
// No X11 : Only use fonts from Grafx2
#elif defined(__linux__) #elif defined(__linux__)
#ifndef NOTTF #ifndef NOTTF
#define USE_XLIB #define USE_XLIB
@ -343,15 +348,22 @@ void Init_text(void)
#ifndef NOTTF #ifndef NOTTF
For_each_file( "FONTS:_TrueType", Add_font ); For_each_file( "FONTS:_TrueType", Add_font );
#endif #endif
#elif defined(__BEOS__) || defined(__HAIKU__) #elif defined(__BEOS__)
#ifndef NOTTF #ifndef NOTTF
For_each_file("/etc/fonts/ttfonts", Add_font); For_each_file("/etc/fonts/ttfonts", Add_font);
#endif #endif
#elif defined(__HAIKU__)
#ifndef NOTTF
For_each_file("/boot/system/data/fonts/ttfonts/", Add_font);
#endif
#elif defined(__SKYOS__) #elif defined(__SKYOS__)
#ifndef NOTTF #ifndef NOTTF
For_each_file("/boot/system/fonts", Add_font); For_each_file("/boot/system/fonts", Add_font);
#endif #endif
#elif defined(__MINT__)
#ifndef NOTTF
For_each_file("C:/BTFONTS", Add_font);
#endif
#endif #endif
} }
@ -368,17 +380,15 @@ int TrueType_is_supported()
#ifndef NOTTF #ifndef NOTTF
byte *Render_text_TTF(const char *str, int font_number, int size, int antialias, int bold, int italic, int *width, int *height) byte *Render_text_TTF(const char *str, int font_number, int size, int antialias, int bold, int italic, int *width, int *height, T_Palette palette)
{ {
TTF_Font *font; TTF_Font *font;
SDL_Surface * TexteColore; SDL_Surface * text_surface;
SDL_Surface * Texte8Bit;
byte * new_brush; byte * new_brush;
int index;
int style; int style;
SDL_Color Couleur_Avant; SDL_Color fg_color;
SDL_Color Couleur_Arriere; SDL_Color bg_color;
// Chargement de la fonte // Chargement de la fonte
font=TTF_OpenFont(Font_name(font_number), size); font=TTF_OpenFont(Font_name(font_number), size);
@ -386,6 +396,7 @@ byte *Render_text_TTF(const char *str, int font_number, int size, int antialias,
{ {
return NULL; return NULL;
} }
// Style // Style
style=0; style=0;
if (italic) if (italic)
@ -393,82 +404,170 @@ byte *Render_text_TTF(const char *str, int font_number, int size, int antialias,
if (bold) if (bold)
style|=TTF_STYLE_BOLD; style|=TTF_STYLE_BOLD;
TTF_SetFontStyle(font, style); TTF_SetFontStyle(font, style);
// Couleurs
if (antialias)
{
Couleur_Avant = Color_to_SDL_color(Fore_color);
Couleur_Arriere = Color_to_SDL_color(Back_color);
}
else
{
Couleur_Avant = Color_to_SDL_color(MC_White);
Couleur_Arriere = Color_to_SDL_color(MC_Black);
}
// Colors: Text will be generated as white on black.
fg_color.r=fg_color.g=fg_color.b=255;
bg_color.r=bg_color.g=bg_color.b=0;
// The following is alpha, supposedly unused
bg_color.unused=fg_color.unused=255;
// Rendu du texte: crée une surface SDL RGB 24bits // Text rendering: creates a 8bit surface with its dedicated palette
if (antialias) if (antialias)
TexteColore=TTF_RenderText_Shaded(font, str, Couleur_Avant, Couleur_Arriere ); text_surface=TTF_RenderText_Shaded(font, str, fg_color, bg_color );
else else
TexteColore=TTF_RenderText_Solid(font, str, Couleur_Avant); text_surface=TTF_RenderText_Solid(font, str, fg_color);
if (!TexteColore) if (!text_surface)
{ {
TTF_CloseFont(font); TTF_CloseFont(font);
return NULL; return NULL;
} }
Texte8Bit=SDL_DisplayFormat(TexteColore); new_brush=Surface_to_bytefield(text_surface, NULL);
SDL_FreeSurface(TexteColore);
new_brush=Surface_to_bytefield(Texte8Bit, NULL);
if (!new_brush) if (!new_brush)
{ {
SDL_FreeSurface(TexteColore); SDL_FreeSurface(text_surface);
SDL_FreeSurface(Texte8Bit);
TTF_CloseFont(font); TTF_CloseFont(font);
return NULL; return NULL;
} }
if (!antialias)
// Import palette
Get_SDL_Palette(text_surface->format->palette, palette);
if (antialias)
{ {
// Mappage des couleurs int black_col;
for (index=0; index < Texte8Bit->w * Texte8Bit->h; index++) // Shaded text: X-Swap the color that is pure black with the BG color number,
// so that the brush is immediately 'transparent'
// Find black (c)
for (black_col=0; black_col<256; black_col++)
{ {
if (*(new_brush+index) == MC_Black) if (palette[black_col].R==0 && palette[black_col].G==0 && palette[black_col].B==0)
*(new_brush+index)=Back_color; break;
else if (*(new_brush+index) == MC_White) } // If not found: c = 256 = 0 (byte)
*(new_brush+index)=Fore_color;
if (black_col != Back_color)
{
int c;
byte colmap[256];
// Swap palette entries
SWAP_BYTES(palette[black_col].R, palette[Back_color].R)
SWAP_BYTES(palette[black_col].G, palette[Back_color].G)
SWAP_BYTES(palette[black_col].B, palette[Back_color].B)
// Define a colormap
for (c=0; c<256; c++)
colmap[c]=c;
// The swap
colmap[black_col]=Back_color;
colmap[Back_color]=black_col;
Remap_general_lowlevel(colmap, new_brush, new_brush, text_surface->w,text_surface->h, text_surface->w);
// Also, make the BG color in brush palette have same RGB values as
// the current BG color : this will help for remaps.
palette[Back_color].R=Main_palette[Back_color].R;
palette[Back_color].G=Main_palette[Back_color].G;
palette[Back_color].B=Main_palette[Back_color].B;
} }
} }
*width=Texte8Bit->w; else
*height=Texte8Bit->h; {
SDL_FreeSurface(Texte8Bit); // Solid text: Was rendered as white on black. Now map colors:
// White becomes FG color, black becomes BG. 2-color palette.
// Exception: if BG==FG, FG will be set to black or white - any different color.
long index;
byte new_fore=Fore_color;
if (Fore_color==Back_color)
{
if (Main_palette[Back_color].R+Main_palette[Back_color].G+Main_palette[Back_color].B > 128*3)
// Back color is rather light:
new_fore=MC_Black;
else
// Back color is rather dark:
new_fore=MC_White;
}
for (index=0; index < text_surface->w * text_surface->h; index++)
{
if (palette[*(new_brush+index)].G < 128)
*(new_brush+index)=Back_color;
else
*(new_brush+index)=new_fore;
}
// Now copy the current palette to brushe's, for consistency
// with the indices.
memcpy(palette, Main_palette, sizeof(T_Palette));
}
*width=text_surface->w;
*height=text_surface->h;
SDL_FreeSurface(text_surface);
TTF_CloseFont(font); TTF_CloseFont(font);
return new_brush; return new_brush;
} }
#endif #endif
byte *Render_text_SFont(const char *str, int font_number, int *width, int *height) byte *Render_text_SFont(const char *str, int font_number, int *width, int *height, T_Palette palette)
{ {
SFont_Font *font; SFont_Font *font;
SDL_Surface * TexteColore; SDL_Surface * text_surface;
SDL_Surface * Texte8Bit; SDL_Surface *font_surface;
SDL_Surface *Surface_fonte;
byte * new_brush; byte * new_brush;
SDL_Rect rectangle; SDL_Rect rectangle;
// Chargement de la fonte // Chargement de la fonte
Surface_fonte=IMG_Load(Font_name(font_number)); font_surface=IMG_Load(Font_name(font_number));
if (!Surface_fonte) if (!font_surface)
{ {
DEBUG("Font loading failed",0); Verbose_message("Warning","Error loading font.\nThe file may be corrupt.");
return NULL; return NULL;
} }
font=SFont_InitFont(Surface_fonte); // Font is 24bit: Perform a color reduction
if (font_surface->format->BitsPerPixel>8)
{
SDL_Surface * reduced_surface;
int x,y,color;
SDL_Color rgb;
reduced_surface=SDL_CreateRGBSurface(SDL_SWSURFACE, font_surface->w, font_surface->h, 8, 0, 0, 0, 0);
if (!reduced_surface)
{
SDL_FreeSurface(font_surface);
return NULL;
}
// Set the quick palette
for (color=0;color<256;color++)
{
rgb.r=((color & 0xE0)>>5)<<5;
rgb.g=((color & 0x1C)>>2)<<5;
rgb.b=((color & 0x03)>>0)<<6;
SDL_SetColors(reduced_surface, &rgb, color, 1);
}
// Perform reduction
for (y=0; y<font_surface->h; y++)
for (x=0; x<font_surface->w; x++)
{
SDL_GetRGB(Get_SDL_pixel_hicolor(font_surface, x, y), font_surface->format, &rgb.r, &rgb.g, &rgb.b);
color=((rgb.r >> 5) << 5) |
((rgb.g >> 5) << 2) |
((rgb.b >> 6));
Set_SDL_pixel_8(reduced_surface, x, y, color);
}
SDL_FreeSurface(font_surface);
font_surface=reduced_surface;
}
font=SFont_InitFont(font_surface);
if (!font) if (!font)
{ {
DEBUG("Font init failed",1); DEBUG("Font init failed",1);
SDL_FreeSurface(font_surface);
return NULL; return NULL;
} }
@ -476,40 +575,36 @@ byte *Render_text_SFont(const char *str, int font_number, int *width, int *heigh
*height=SFont_TextHeight(font); *height=SFont_TextHeight(font);
*width=SFont_TextWidth(font, str); *width=SFont_TextWidth(font, str);
// Allocation d'une surface SDL // Allocation d'une surface SDL
TexteColore=SDL_CreateRGBSurface(SDL_SWSURFACE, *width, *height, 24, 0, 0, 0, 0); text_surface=SDL_CreateRGBSurface(SDL_SWSURFACE, *width, *height, 8, 0, 0, 0, 0);
// Copy palette
SDL_SetPalette(text_surface, SDL_LOGPAL, font_surface->format->palette->colors, 0, 256);
// Fill with backcolor // Fill with backcolor
rectangle.x=0; rectangle.x=0;
rectangle.y=0; rectangle.y=0;
rectangle.w=*width; rectangle.w=*width;
rectangle.h=*height; rectangle.h=*height;
SDL_FillRect(TexteColore, &rectangle, SDL_MapRGB( SDL_FillRect(text_surface, &rectangle, Back_color);
TexteColore->format,
Main_palette[Back_color].R,
Main_palette[Back_color].G,
Main_palette[Back_color].B
));
// Rendu du texte // Rendu du texte
SFont_Write(TexteColore, font, 0, 0, str); SFont_Write(text_surface, font, 0, 0, str);
if (!TexteColore) if (!text_surface)
{ {
DEBUG("Rendering failed",2); DEBUG("Rendering failed",2);
SFont_FreeFont(font); SFont_FreeFont(font);
return NULL; return NULL;
} }
Texte8Bit=SDL_DisplayFormat(TexteColore); new_brush=Surface_to_bytefield(text_surface, NULL);
SDL_FreeSurface(TexteColore);
new_brush=Surface_to_bytefield(Texte8Bit, NULL);
if (!new_brush) if (!new_brush)
{ {
DEBUG("Converting failed",3); DEBUG("Converting failed",3);
SDL_FreeSurface(TexteColore); SDL_FreeSurface(text_surface);
SDL_FreeSurface(Texte8Bit);
SFont_FreeFont(font); SFont_FreeFont(font);
return NULL; return NULL;
} }
SDL_FreeSurface(Texte8Bit);
Get_SDL_Palette(font_surface->format->palette, palette);
SDL_FreeSurface(text_surface);
SFont_FreeFont(font); SFont_FreeFont(font);
return new_brush; return new_brush;
@ -524,7 +619,7 @@ byte *Render_text_SFont(const char *str, int font_number, int *width, int *heigh
// Crée une brosse à partir des paramètres de texte demandés. // Crée une brosse à partir des paramètres de texte demandés.
// Si cela réussit, la fonction place les dimensions dans width et height, // Si cela réussit, la fonction place les dimensions dans width et height,
// et retourne l'adresse du bloc d'octets. // et retourne l'adresse du bloc d'octets.
byte *Render_text(const char *str, int font_number, TTFONLY int size, int TTFONLY antialias, TTFONLY int bold, TTFONLY int italic, int *width, int *height) byte *Render_text(const char *str, int font_number, TTFONLY int size, int TTFONLY antialias, TTFONLY int bold, TTFONLY int italic, int *width, int *height, T_Palette palette)
{ {
T_Font *font = font_list_start; T_Font *font = font_list_start;
int index=font_number; int index=font_number;
@ -538,14 +633,14 @@ byte *Render_text(const char *str, int font_number, TTFONLY int size, int TTFONL
if (font->Is_truetype) if (font->Is_truetype)
{ {
#ifndef NOTTF #ifndef NOTTF
return Render_text_TTF(str, font_number, size, antialias, bold, italic, width, height); return Render_text_TTF(str, font_number, size, antialias, bold, italic, width, height, palette);
#else #else
return NULL; return NULL;
#endif #endif
} }
else else
{ {
return Render_text_SFont(str, font_number, width, height); return Render_text_SFont(str, font_number, width, height, palette);
} }
} }

View File

@ -41,15 +41,16 @@ void Add_font(const char *name);
/// @param italic Boolean, true to use italic rendering in TrueType /// @param italic Boolean, true to use italic rendering in TrueType
/// @param width Returns the width of the created brush, in pixels. /// @param width Returns the width of the created brush, in pixels.
/// @param height Returns the height of the created brush, in pixels. /// @param height Returns the height of the created brush, in pixels.
/// @param palette Returns the custom palette for the brush.
/// Returns true on success. /// Returns true on success.
byte *Render_text(const char *str, int font_number, int size, int antialias, int bold, int italic, int *width, int *height); byte *Render_text(const char *str, int font_number, int size, int antialias, int bold, int italic, int *width, int *height, T_Palette palette);
/// Finds a label to display for a font declared with ::Add_font(). /// Finds a label to display for a font declared with ::Add_font().
char * Font_label(int index); char * Font_label(int index);
/// Finds the filename of a font declared with ::Add_font(). /// Finds the filename of a font declared with ::Add_font().
char * Font_name(int index); char * Font_name(int index);
/// Returns true if the font of this number is TrueType, false if it's a SFont bitmap. /// Returns true if the font of this number is TrueType, false if it's a SFont bitmap.
char * TrueType_font(int index); int TrueType_font(int index);
/// ///
/// Number of fonts declared with a series of ::Add_font(). This is public for /// Number of fonts declared with a series of ::Add_font(). This is public for
/// convenience, but functionaly it is read-only. /// convenience, but functionaly it is read-only.

114
src/tiles.c Normal file
View File

@ -0,0 +1,114 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2010 Adrien Destugues
Grafx2 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; version 2
of the License.
Grafx2 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 Grafx2; if not, see <http://www.gnu.org/licenses/>
*/
/// \file Handle tiles.
/// Build the tile-area from the current picture
void build_tile_area()
{
word tileAreaWidth = Main_image_width / Snap_width + 1;
word tileAreaHeight = Main_image_height / Snap_height + 1;
int* tileArea = malloc(tileAreaWidth*tileAreaHeight*sizeof(int));
word tile_x, tile_y, pixel_x, pixel_y;
// For each tile, we have to crawl up to the top of the picture and
// find the first identical tile
for (tile_y = 0; tile_y < tileAreaWidth; tile_y++)
for(tile_x = 0; tile_x < tileAreaHeight; tile_x++)
{
// So, this is the "for each tile"
word ctx, cty;
// First we compare the tile with the others one in the same line at the left
for(ctx = tile_x - 1; ctx >= 0; ctx--)
if(compare_tiles(tile_x*Snap_width, tile_y*Snap_height, ctx*Snap_width, tile_y*Snap_height))
{
// We found a match !
tileArea[tile_y*tileAreaWidth+tile_x] = tile_y*tileAreaWidth+ctx;
goto found;
}
// Then we look at all the lines above
for(cty = tile_y - 1; cty >= 0; cty--)
for(ctx = tileAreaWidth - 1; ctx >= 0; ctx--)
if(compare_tiles(tile_x*Snap_width, tile_y*Snap_height, ctx*Snap_width, cty*Snap_height))
{
// We found a match !
tileArea[tile_y*tileAreaWidth+tile_x] = cty*tileAreaWidth+ctx;
goto found;
}
// Then we look at all the lines below
for(cty = tileAreaHeight - 1; cty >= tile_y; cty--)
for(ctx = tileAreaWidth - 1; ctx >= 0; ctx--)
if(compare_tiles(tile_x*Snap_width, tile_y*Snap_height, ctx*Snap_width, cty*Snap_height))
{
// We found a match !
tileArea[tile_y*tileAreaWidth+tile_x] = cty*tileAreaWidth+ctx;
goto found;
}
// Then we look at the tiles at the right of this one
// (including the tile itself, so we are sure we match something this time)
for(ctx = tileAreaHeight; ctx >= tile_x; ctx--)
if(compare_tiles(tile_x*Snap_width, tile_y*Snap_height, ctx*Snap_width, tile_y*Snap_height))
{
// We found a match !
tileArea[tile_y*tileAreaWidth+tile_x] = tile_y*tileAreaWidth+ctx;
}
found:
}
}
// Compare tiles
// The parameters are in pixel-space.
void compare_tiles(word x1, word y1, word x2, word y2)
{
word pixel_x, pixel_y;
byte c1, c2;
for (pixel_y = 0; pixel_y < Snap_width; pixel_y++)
for (pixel_x = 0; pixel_x < Snap_height; pixel_x++)
{
c1 = Main_screen + (y1+pixel_y) * Main_image_width + (x1+pixel_x);
c2 = Main_screen + (y2+pixel_y) * Main_image_width + (x2+pixel_x);
if (c1 != c2) return 0;
}
return 1;
}
/// Copy a tile pixeldata to all the identical ones
// Call this after the end of an operation
void update_tile(word pixel_x, word pixel_y)
{
int tileOffset = (pixel_y/Snap_height)*tileAreaHeight + pixel_x/Snap_width;
int firstTileOffset = tileOffset + 1; // to make sure they are not equal
while(firstTileOffset != tileOffset)
{
tileOffset = tileArea[tileOffset];
//do the copy of a block starting at (pixel_x, pixel_y)
}
}

View File

@ -273,7 +273,7 @@ void Button_Transform_menu(void)
input_button[clicked_button-10]->Pos_Y+2, input_button[clicked_button-10]->Pos_Y+2,
buffer, buffer,
4, 4,
1)) INPUT_TYPE_INTEGER))
{ {
// Accept entered value // Accept entered value
*(input_value[clicked_button-10])=atoi(buffer); *(input_value[clicked_button-10])=atoi(buffer);
@ -369,8 +369,9 @@ void Button_Transform_menu(void)
old_width=Main_image_width; old_width=Main_image_width;
old_height=Main_image_height; old_height=Main_image_height;
Upload_infos_page_main(Main_backups->Pages);
// Allocate a new page // Allocate a new page
if (Backup_with_new_dimensions(1,Main_backups->Pages->Nb_layers,new_width,new_height)) if (Backup_with_new_dimensions(new_width,new_height))
{ {
// The new image is allocated, the new dimensions are already updated. // The new image is allocated, the new dimensions are already updated.

View File

@ -36,8 +36,11 @@
#include "graph.h" #include "graph.h"
#include "input.h" #include "input.h"
#include "misc.h" #include "misc.h"
#include "op_c.h"
#include "readline.h" #include "readline.h"
#include "sdlscreen.h" #include "sdlscreen.h"
#include "palette.h"
/// Width of one layer button, in pixels before scaling /// Width of one layer button, in pixels before scaling
word Layer_button_width = 1; word Layer_button_width = 1;
@ -67,7 +70,7 @@ void Pixel_in_menu(word bar, word x, word y, byte color)
void Pixel_in_menu_and_skin(word bar, word x, word y, byte color) void Pixel_in_menu_and_skin(word bar, word x, word y, byte color)
{ {
Pixel_in_menu(bar, x, y, color); Pixel_in_menu(bar, x, y, color);
Menu_bars[bar].Skin[y*Menu_bars[bar].Skin_width + x] = color; Menu_bars[bar].Skin[2][y*Menu_bars[bar].Skin_width + x] = color;
} }
// Affichage d'un pixel dans la fenêtre (la fenêtre doit être visible) // Affichage d'un pixel dans la fenêtre (la fenêtre doit être visible)
@ -454,7 +457,7 @@ void Draw_bar_remainder(word current_menu, word x_off)
for (y_pos=0;y_pos<Menu_bars[current_menu].Height;y_pos++) for (y_pos=0;y_pos<Menu_bars[current_menu].Height;y_pos++)
for (x_pos=x_off;x_pos<Screen_width/Menu_factor_X;x_pos++) for (x_pos=x_off;x_pos<Screen_width/Menu_factor_X;x_pos++)
Pixel_in_menu(current_menu, x_pos, y_pos, Menu_bars[current_menu].Skin[y_pos * Menu_bars[current_menu].Skin_width + Menu_bars[current_menu].Skin_width - 2 + (x_pos&1)]); Pixel_in_menu(current_menu, x_pos, y_pos, Menu_bars[current_menu].Skin[0][y_pos * Menu_bars[current_menu].Skin_width + Menu_bars[current_menu].Skin_width - 2 + (x_pos&1)]);
} }
@ -491,7 +494,7 @@ void Display_layerbar(void)
x_off=Menu_bars[MENUBAR_LAYERS].Skin_width; x_off=Menu_bars[MENUBAR_LAYERS].Skin_width;
for (current_button=0; current_button<button_number; current_button++) for (current_button=0; current_button<button_number; current_button++)
{ {
word x_pos; word x_pos=0;
word y_pos; word y_pos;
word sprite_index; word sprite_index;
@ -566,7 +569,7 @@ void Display_menu(void)
// Skinned area // Skinned area
for (y_pos=0;y_pos<Menu_bars[current_menu].Height;y_pos++) for (y_pos=0;y_pos<Menu_bars[current_menu].Height;y_pos++)
for (x_pos=0;x_pos<Menu_bars[current_menu].Skin_width;x_pos++) for (x_pos=0;x_pos<Menu_bars[current_menu].Skin_width;x_pos++)
Pixel_in_menu(current_menu, x_pos, y_pos, Menu_bars[current_menu].Skin[y_pos * Menu_bars[current_menu].Skin_width + x_pos]); Pixel_in_menu(current_menu, x_pos, y_pos, Menu_bars[current_menu].Skin[2][y_pos * Menu_bars[current_menu].Skin_width + x_pos]);
if (current_menu == MENUBAR_LAYERS) if (current_menu == MENUBAR_LAYERS)
{ {
@ -706,6 +709,7 @@ void Print_coordinates(void)
if (Menu_is_visible && !Cursor_in_menu) if (Menu_is_visible && !Cursor_in_menu)
{ {
if ( (Current_operation==OPERATION_COLORPICK) if ( (Current_operation==OPERATION_COLORPICK)
|| (Current_operation==OPERATION_RMB_COLORPICK)
|| (Current_operation==OPERATION_REPLACE) ) || (Current_operation==OPERATION_REPLACE) )
{ {
if ( (Paintbrush_X>=0) && (Paintbrush_Y>=0) if ( (Paintbrush_X>=0) && (Paintbrush_Y>=0)
@ -1073,7 +1077,7 @@ int Requester_window(char* message, int initial_value)
{ {
clicked_button = Window_clicked_button(); clicked_button = Window_clicked_button();
if (clicked_button == 1) if (clicked_button == 1)
Readline(11, 39, str, 4, 1); Readline(11, 39, str, 4, INPUT_TYPE_INTEGER);
if (Key == SDLK_ESCAPE) clicked_button = 2; if (Key == SDLK_ESCAPE) clicked_button = 2;
} }
while (clicked_button <= 0); while (clicked_button <= 0);
@ -1179,90 +1183,34 @@ void Verbose_message(const char *caption, const char * message )
// -- Redessiner le sprite d'un bouton dans le menu -- // -- Redessiner le sprite d'un bouton dans le menu --
void Display_sprite_in_menu(int btn_number,int sprite_number) void Display_sprite_in_menu(int btn_number,char sprite_number)
{ {
word x_pos; Buttons_Pool[btn_number].Icon=sprite_number;
word y_pos;
word menu_x_pos;
word menu_y_pos;
byte color;
menu_y_pos=Buttons_Pool[btn_number].Y_offset; if (Buttons_Pool[btn_number].Shape == BUTTON_SHAPE_TRIANGLE_TOP_LEFT)
menu_x_pos=Buttons_Pool[btn_number].X_offset; Buttons_Pool[btn_number+1].Icon=sprite_number;
if (Buttons_Pool[btn_number].Shape != BUTTON_SHAPE_TRIANGLE_BOTTOM_RIGHT)
{
menu_y_pos+=1;
menu_x_pos+=1;
}
for (y_pos=0;y_pos<MENU_SPRITE_HEIGHT;y_pos++) else if (Buttons_Pool[btn_number].Shape == BUTTON_SHAPE_TRIANGLE_BOTTOM_RIGHT)
for (x_pos=0;x_pos<MENU_SPRITE_WIDTH;x_pos++) Buttons_Pool[btn_number-1].Icon=sprite_number;
{
color=Gfx->Menu_sprite[sprite_number][y_pos][x_pos];
Pixel_in_menu_and_skin(MENUBAR_TOOLS, menu_x_pos+x_pos, menu_y_pos+y_pos, color);
}
if (Menu_is_visible && Menu_bars[MENUBAR_TOOLS].Visible)
Update_rect(Menu_factor_X*(Buttons_Pool[btn_number].X_offset+1),
(Buttons_Pool[btn_number].Y_offset+1+Menu_bars[MENUBAR_TOOLS].Top)*Menu_factor_Y+Menu_Y,
MENU_SPRITE_WIDTH*Menu_factor_X,MENU_SPRITE_HEIGHT*Menu_factor_Y);
} }
// -- Redessiner la forme du pinceau dans le menu -- // -- Redessiner la forme du pinceau dans le menu --
void Display_paintbrush_in_menu(void) void Display_paintbrush_in_menu(void)
{ {
short x_pos,y_pos; switch(Paintbrush_shape)
short start_x;
short menu_x_pos,menu_y_pos;
short menu_start_x;
byte color;
switch (Paintbrush_shape)
{ {
case PAINTBRUSH_SHAPE_COLOR_BRUSH : // Brush en couleur case PAINTBRUSH_SHAPE_COLOR_BRUSH:
case PAINTBRUSH_SHAPE_MONO_BRUSH : // Brush monochrome Display_sprite_in_menu(BUTTON_PAINTBRUSHES, MENU_SPRITE_COLOR_BRUSH);
for (menu_y_pos=2,y_pos=0;y_pos<MENU_SPRITE_HEIGHT;menu_y_pos++,y_pos++) break;
for (menu_x_pos=1,x_pos=0;x_pos<MENU_SPRITE_WIDTH;menu_x_pos++,x_pos++) case PAINTBRUSH_SHAPE_MONO_BRUSH:
{ Display_sprite_in_menu(BUTTON_PAINTBRUSHES, MENU_SPRITE_MONO_BRUSH);
color=Gfx->Menu_sprite[4][y_pos][x_pos]; break;
Pixel_in_menu_and_skin(MENUBAR_TOOLS, menu_x_pos, menu_y_pos, color); default:
} Display_sprite_in_menu(BUTTON_PAINTBRUSHES, -1);
break; break;
default : // Pinceau
// On efface le pinceau précédent
for (menu_y_pos=2,y_pos=0;y_pos<MENU_SPRITE_HEIGHT;menu_y_pos++,y_pos++)
for (menu_x_pos=1,x_pos=0;x_pos<MENU_SPRITE_WIDTH;menu_x_pos++,x_pos++)
{
Pixel_in_menu_and_skin(MENUBAR_TOOLS, menu_x_pos, menu_y_pos, MC_Light);
}
// On affiche le nouveau
menu_start_x=8-Paintbrush_offset_X;
if (menu_start_x<1)
{
start_x=Paintbrush_offset_X-7;
menu_start_x=1;
}
else
start_x=0;
menu_y_pos=9-Paintbrush_offset_Y;
if (menu_y_pos<2)
{
y_pos=Paintbrush_offset_Y-7;
menu_y_pos=2;
}
else
y_pos=0;
for (;((y_pos<Paintbrush_height) && (menu_y_pos<16));menu_y_pos++,y_pos++)
for (menu_x_pos=menu_start_x,x_pos=start_x;((x_pos<Paintbrush_width) && (menu_x_pos<15));menu_x_pos++,x_pos++)
{
color=(Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos])?MC_Black:MC_Light;
Pixel_in_menu_and_skin(MENUBAR_TOOLS, menu_x_pos, menu_y_pos, color);
}
} }
if (Menu_is_visible && Menu_bars[MENUBAR_TOOLS].Visible) Draw_menu_button(BUTTON_PAINTBRUSHES,BUTTON_RELEASED);
Update_rect(0,Menu_Y + Menu_bars[MENUBAR_TOOLS].Top*Menu_factor_Y,MENU_SPRITE_WIDTH*Menu_factor_X+3,MENU_SPRITE_HEIGHT*Menu_factor_Y+3);
} }
// -- Dessiner un pinceau prédéfini dans la fenêtre -- // -- Dessiner un pinceau prédéfini dans la fenêtre --
@ -1278,6 +1226,8 @@ void Display_paintbrush_in_window(word x,word y,int number)
int y_size; int y_size;
word origin_x; word origin_x;
word origin_y; word origin_y;
word width;
word height;
x_size=Menu_factor_X/Pixel_height; x_size=Menu_factor_X/Pixel_height;
if (x_size<1) if (x_size<1)
@ -1286,18 +1236,22 @@ void Display_paintbrush_in_window(word x,word y,int number)
if (y_size<1) if (y_size<1)
y_size=1; y_size=1;
origin_x = (x + 8)*Menu_factor_X - (Gfx->Preset_paintbrush_offset_X[number])*x_size+Window_pos_X; width=Min(Paintbrush[number].Width,PAINTBRUSH_WIDTH);
origin_y = (y + 8)*Menu_factor_Y - (Gfx->Preset_paintbrush_offset_Y[number])*y_size+Window_pos_Y; height=Min(Paintbrush[number].Height,PAINTBRUSH_WIDTH);
for (window_y_pos=0,y_pos=0; y_pos<Gfx->Preset_paintbrush_height[number]; window_y_pos++,y_pos++) origin_x = (x + 8)*Menu_factor_X - (width/2)*x_size+Window_pos_X;
for (window_x_pos=0,x_pos=0; x_pos<Gfx->Preset_paintbrush_width[number]; window_x_pos++,x_pos++) origin_y = (y + 8)*Menu_factor_Y - (height/2)*y_size+Window_pos_Y;
Block(origin_x+window_x_pos*x_size,origin_y+window_y_pos*y_size,x_size,y_size,(Gfx->Paintbrush_sprite[number][y_pos][x_pos])?MC_Black:MC_Light);
for (window_y_pos=0,y_pos=0; y_pos<height; window_y_pos++,y_pos++)
for (window_x_pos=0,x_pos=0; x_pos<width; window_x_pos++,x_pos++)
if (Paintbrush[number].Sprite[y_pos][x_pos])
Block(origin_x+window_x_pos*x_size,origin_y+window_y_pos*y_size,x_size,y_size,MC_Black);
// On n'utilise pas Pixel_in_window() car on ne dessine pas // On n'utilise pas Pixel_in_window() car on ne dessine pas
// forcément avec la même taille de pixel. // forcément avec la même taille de pixel.
Update_rect( ToWinX(origin_x), ToWinY(origin_y), Update_rect( ToWinX(origin_x), ToWinY(origin_y),
ToWinL(Gfx->Preset_paintbrush_width[number]), ToWinL(Paintbrush[number].Width),
ToWinH(Gfx->Preset_paintbrush_height[number]) ToWinH(Paintbrush[number].Height)
); );
} }
@ -1553,6 +1507,7 @@ void Compute_paintbrush_coordinates(void)
{ {
// Operations that don't implement it // Operations that don't implement it
case OPERATION_LINE: case OPERATION_LINE:
case OPERATION_ROTATE_BRUSH:
Snap_axis=0; Snap_axis=0;
break; break;
// Operations that implement it // Operations that implement it
@ -1857,7 +1812,36 @@ void Change_magnifier_factor(byte factor_index, byte point_at_mouse)
Compute_paintbrush_coordinates(); Compute_paintbrush_coordinates();
} }
void Copy_view_to_spare(void)
{
// Don't do anything if the pictures have different dimensions
if (Main_image_width!=Spare_image_width || Main_image_height!=Spare_image_height)
return;
// Copie des décalages de la fenêtre principale (non zoomée) de l'image
Spare_offset_X=Main_offset_X;
Spare_offset_Y=Main_offset_Y;
// Copie du booléen "Mode loupe" de l'image
Spare_magnifier_mode=Main_magnifier_mode;
// Copie du facteur de zoom du brouillon
Spare_magnifier_factor=Main_magnifier_factor;
// Copie des dimensions de la fenêtre de zoom
Spare_magnifier_width=Main_magnifier_width;
Spare_magnifier_height=Main_magnifier_height;
// Copie des décalages de la fenêtre de zoom
Spare_magnifier_offset_X=Main_magnifier_offset_X;
Spare_magnifier_offset_Y=Main_magnifier_offset_Y;
// Copie des données du split du zoom
Spare_separator_position=Main_separator_position;
Spare_X_zoom=Main_X_zoom;
Spare_separator_proportion=Main_separator_proportion;
}
// -- Afficher la barre de séparation entre les parties zoomées ou non en // -- Afficher la barre de séparation entre les parties zoomées ou non en
// mode Loupe -- // mode Loupe --
@ -2629,7 +2613,7 @@ void Display_all_screen(void)
byte Best_color(byte r,byte g,byte b) byte Best_color(byte r,byte g,byte b)
{ {
short col; int col;
int delta_r,delta_g,delta_b; int delta_r,delta_g,delta_b;
int dist; int dist;
int best_dist=0x7FFFFFFF; int best_dist=0x7FFFFFFF;
@ -2663,7 +2647,7 @@ byte Best_color(byte r,byte g,byte b)
byte Best_color_nonexcluded(byte red,byte green,byte blue) byte Best_color_nonexcluded(byte red,byte green,byte blue)
{ {
short col; int col;
int delta_r,delta_g,delta_b; int delta_r,delta_g,delta_b;
int dist; int dist;
int best_dist=0x7FFFFFFF; int best_dist=0x7FFFFFFF;
@ -2692,65 +2676,50 @@ byte Best_color_nonexcluded(byte red,byte green,byte blue)
return best_color; return best_color;
} }
void Compute_4_best_colors_for_1_menu_color
(byte red, byte green, byte blue, T_Components * palette, byte * table)
{
short col;
int delta_r,delta_g,delta_b;
int dist;
int best_dist[4]={0x7FFFFFFF,0x7FFFFFFF,0x7FFFFFFF,0x7FFFFFFF};
byte Best_color_perceptual(byte r,byte g,byte b)
{
int col;
float best_diff=255.0*1.56905;
byte best_color=0;
float target_bri;
float bri;
float diff_b, diff_c, diff;
// Similar to Perceptual_lightness();
target_bri = sqrt(0.26*r*0.26*r + 0.55*g*0.55*g + 0.19*b*0.19*b);
for (col=0; col<256; col++) for (col=0; col<256; col++)
{ {
delta_r=(int)palette[col].R-red; if (Exclude_color[col])
delta_g=(int)palette[col].G-green; continue;
delta_b=(int)palette[col].B-blue;
dist=(delta_r*delta_r*30)+(delta_g*delta_g*59)+(delta_b*delta_b*11); diff_c = sqrt(
(0.26*(Main_palette[col].R-r))*
(0.26*(Main_palette[col].R-r))+
(0.55*(Main_palette[col].G-g))*
(0.55*(Main_palette[col].G-g))+
(0.19*(Main_palette[col].B-b))*
(0.19*(Main_palette[col].B-b)));
// Exact match
if (diff_c==0)
return col;
if (dist<best_dist[0]) bri = sqrt(0.26*Main_palette[col].R*0.26*Main_palette[col].R + 0.55*Main_palette[col].G*0.55*Main_palette[col].G + 0.19*Main_palette[col].B*0.19*Main_palette[col].B);
diff_b = abs(target_bri-bri);
diff=0.25*(diff_b-diff_c)+diff_c;
if (diff<best_diff)
{ {
best_dist[3]=best_dist[2]; best_diff=diff;
best_dist[2]=best_dist[1]; best_color=col;
best_dist[1]=best_dist[0];
best_dist[0]=dist;
table[3]=table[2];
table[2]=table[1];
table[1]=table[0];
table[0]=col;
}
else
{
if (dist<best_dist[1])
{
best_dist[3]=best_dist[2];
best_dist[2]=best_dist[1];
best_dist[1]=dist;
table[3]=table[2];
table[2]=table[1];
table[1]=col;
}
else
{
if (dist<best_dist[2])
{
best_dist[3]=best_dist[2];
best_dist[2]=dist;
table[3]=table[2];
table[2]=col;
}
else
if (dist<best_dist[3])
{
best_dist[3]=dist;
table[3]=col;
}
}
} }
} }
}
return best_color;
}
byte Old_black; byte Old_black;
@ -2835,11 +2804,32 @@ void Remap_screen_after_menu_colors_change(void)
} }
int Same_color(T_Components * palette, byte c1, byte c2)
{
if (palette[c1].R==palette[c2].R &&
palette[c1].G==palette[c2].G &&
palette[c1].B==palette[c2].B)
return 1;
return 0;
}
void Compute_optimal_menu_colors(T_Components * palette) void Compute_optimal_menu_colors(T_Components * palette)
{ {
byte table[4]; int i;
byte l[256];
byte s[256];
byte h;
int max_l = -1, min_l = 256;
int low_l, hi_l;
int delta_low = 999999;
int delta_high = 999999;
const int tolerence=16;
const T_Components cpc_colors[4] = {
{ 0, 0, 0},
{ 0, 0,128}, // Dark blue
{128,128,128}, // Grey
{255,255,255}
};
Old_black =MC_Black; Old_black =MC_Black;
Old_dark = MC_Dark; Old_dark = MC_Dark;
@ -2847,62 +2837,208 @@ void Compute_optimal_menu_colors(T_Components * palette)
Old_white = MC_White; Old_white = MC_White;
Old_trans = MC_Trans; Old_trans = MC_Trans;
// Recherche du noir // First method:
Compute_4_best_colors_for_1_menu_color // If all close matches for the ideal colors exist, pick them.
(Gfx->Default_palette[Gfx->Color[0]].R, Gfx->Default_palette[Gfx->Color[0]].G, Gfx->Default_palette[Gfx->Color[0]].B,palette,table); for (i=255; i>=0; i--)
MC_Black=table[0];
// Recherche du blanc
Compute_4_best_colors_for_1_menu_color
(Gfx->Default_palette[Gfx->Color[3]].R, Gfx->Default_palette[Gfx->Color[3]].G, Gfx->Default_palette[Gfx->Color[3]].B,palette,table);
if (MC_Black!=table[0])
MC_White=table[0];
else
MC_White=table[1];
// Recherche du gris clair
Compute_4_best_colors_for_1_menu_color
(Gfx->Default_palette[Gfx->Color[2]].R, Gfx->Default_palette[Gfx->Color[2]].G, Gfx->Default_palette[Gfx->Color[2]].B,palette,table);
if ( (MC_Black!=table[0]) && (MC_White!=table[0]) )
MC_Light=table[0];
else
{ {
if ( (MC_Black!=table[1]) && (MC_White!=table[1]) )
MC_Light=table[1];
else
MC_Light=table[2];
}
// Recherche du gris foncé if (Round_palette_component(palette[i].R)/tolerence==Gfx->Default_palette[Gfx->Color[3]].R/tolerence
Compute_4_best_colors_for_1_menu_color && Round_palette_component(palette[i].G)/tolerence==Gfx->Default_palette[Gfx->Color[3]].G/tolerence
(Gfx->Default_palette[Gfx->Color[1]].R, Gfx->Default_palette[Gfx->Color[1]].G, Gfx->Default_palette[Gfx->Color[1]].B,palette,table); && Round_palette_component(palette[i].B)/tolerence==Gfx->Default_palette[Gfx->Color[3]].B/tolerence)
if ( (MC_Black!=table[0]) && (MC_White!=table[0]) && (MC_Light!=table[0]) )
MC_Dark=table[0];
else
{
if ( (MC_Black!=table[1]) && (MC_White!=table[1]) && (MC_Light!=table[1]) )
MC_Dark=table[1];
else
{ {
if ( (MC_Black!=table[2]) && (MC_White!=table[2]) && (MC_Light!=table[2]) ) MC_White=i;
MC_Dark=table[2]; for (i=255; i>=0; i--)
else {
MC_Dark=table[3]; if (Round_palette_component(palette[i].R)/tolerence==Gfx->Default_palette[Gfx->Color[2]].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==Gfx->Default_palette[Gfx->Color[2]].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==Gfx->Default_palette[Gfx->Color[2]].B/tolerence)
{
MC_Light=i;
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==Gfx->Default_palette[Gfx->Color[1]].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==Gfx->Default_palette[Gfx->Color[1]].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==Gfx->Default_palette[Gfx->Color[1]].B/tolerence)
{
MC_Dark=i;
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==Gfx->Default_palette[Gfx->Color[0]].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==Gfx->Default_palette[Gfx->Color[0]].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==Gfx->Default_palette[Gfx->Color[0]].B/tolerence)
{
MC_Black=i;
// On cherche une couleur de transparence différente des 4 autres.
for (MC_Trans=0; ((MC_Trans==MC_Black) || (MC_Trans==MC_Dark) ||
(MC_Trans==MC_Light) || (MC_Trans==MC_White)); MC_Trans++);
// Easy case
MC_OnBlack=MC_Dark;
MC_Window=MC_Light;
MC_Lighter=MC_White;
MC_Darker=MC_Dark;
Remap_menu_sprites();
return;
}
}
}
}
}
}
}
}
// Second method: For CPC 27-color modes only
// Try to find colors that just work
if (Get_palette_RGB_scale()==3)
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==cpc_colors[3].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==cpc_colors[3].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==cpc_colors[3].B/tolerence)
{
MC_White=i;
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==cpc_colors[2].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==cpc_colors[2].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==cpc_colors[2].B/tolerence)
{
MC_Light=i;
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==cpc_colors[1].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==cpc_colors[1].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==cpc_colors[1].B/tolerence)
{
MC_Dark=i;
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==cpc_colors[0].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==cpc_colors[0].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==cpc_colors[0].B/tolerence)
{
MC_Black=i;
// On cherche une couleur de transparence différente des 4 autres.
for (MC_Trans=0; ((MC_Trans==MC_Black) || (MC_Trans==MC_Dark) ||
(MC_Trans==MC_Light) || (MC_Trans==MC_White)); MC_Trans++);
// Easy case
MC_OnBlack=MC_Dark;
MC_Window=MC_Light;
MC_Lighter=MC_White;
MC_Darker=MC_Dark;
Remap_menu_sprites();
return;
}
}
}
}
}
}
} }
} }
// C'est peu probable mais il est possible que MC_Light soit plus foncée que // Third method:
// MC_Dark. Dans ce cas, on les inverse.
if ( ((palette[MC_Light].R*30)+(palette[MC_Light].G*59)+(palette[MC_Light].B*11)) < // Compute luminance for whole palette
((palette[MC_Dark].R*30)+(palette[MC_Dark].G*59)+(palette[MC_Dark].B*11)) ) // Take the darkest as black, the brightest white
for(i = 0; i < 256; i++)
{ {
SWAP_BYTES(MC_Light, MC_Dark); RGB_to_HSL(palette[i].R, palette[i].G, palette[i].B, &h, &s[i], &l[i]);
// Another formula for lightness, in 0-255 range
//l[i]=Perceptual_lightness(&palette[i])/4062/255;
if (l[i] > max_l)
{
max_l = l[i];
MC_White = i;
}
} }
for(i = 0; i < 256; i++)
{
if (l[i] < min_l && i!=MC_White)
{
min_l = l[i];
MC_Black = i;
}
}
// Alter the S values according to the L range - this is for the future
// comparisons, so that highly variable saturation doesn't weigh
// too heavily when the the lightness is in a narrow range.
for(i = 0; i < 256; i++)
{
s[i]=s[i]*(max_l-min_l)/255;
}
for(i = 0; i < 256; i++)
{
// Adjust (reduce) perceived saturation at both ends of L spectrum
if (l[i]>192)
s[i]=s[i]*(255-l[i])/64;
else if (l[i]<64)
s[i]=s[i]*l[i]/64;
}
// Find color nearest to min+2(max-min)/3
// but at the same time we try to minimize the saturation so that the menu
// still looks grey
hi_l = min_l + 2*(max_l - min_l)/3;
for (i = 0; i < 256; i++)
{
if ( abs(l[i] - hi_l) + s[i]/2 < delta_high && i!=MC_White && i!=MC_Black)
{
delta_high = abs(l[i] - hi_l) + s[i]/2;
MC_Light = i;
}
}
// Target "Dark color" is 2/3 between Light and Black
low_l = ((int)l[MC_Light]*2+l[MC_Black])/3;
for (i = 0; i < 256; i++)
{
if ( abs((int)l[i] - low_l) + s[i]/6 < delta_low && i!=MC_White && i!=MC_Black && i!=MC_Light)
{
delta_low = abs((int)l[i] - low_l)+ s[i]/6;
MC_Dark = i;
}
}
//if (l[MC_Light]<l[MC_Dark])
//{
// // Not sure if that can happen, but just in case:
// SWAP_BYTES(MC_Light, MC_Dark)
//}
// Si deux des couleurs choisies ont le même index, c'est destructif car
// on fait ensuite un remap de l'image. Donc on évite ce problème (un
// peu brutalement)
// On commence par déplacer les gris, comme ça on a plus de chances de garder au moins
// le blanc et le noir
//while (MC_Dark == MC_Light || MC_Dark == MC_White || MC_Black == MC_Dark || Same_color(palette, MC_Dark, MC_White)) MC_Dark--;
//while (MC_White == MC_Light || MC_Dark == MC_Light || MC_Black == MC_Light || Same_color(palette, MC_Light, MC_Black)) MC_Light--;
//while (MC_White == MC_Light || MC_Dark == MC_White || MC_Black == MC_White) MC_White--;
// On cherche une couleur de transparence différente des 4 autres. // On cherche une couleur de transparence différente des 4 autres.
for (MC_Trans=0; ((MC_Trans==MC_Black) || (MC_Trans==MC_Dark) || for (MC_Trans=0; ((MC_Trans==MC_Black) || (MC_Trans==MC_Dark) ||
(MC_Trans==MC_Light) || (MC_Trans==MC_White)); MC_Trans++); (MC_Trans==MC_Light) || (MC_Trans==MC_White)); MC_Trans++);
if (Same_color(palette, MC_Black, MC_Dark))
MC_OnBlack=MC_Light;
else
MC_OnBlack=MC_Dark;
if (Same_color(palette, MC_White, MC_Light))
{
MC_Window=MC_Dark;
MC_Darker=MC_Black;
}
else
{
MC_Window=MC_Light;
MC_Darker=MC_Dark;
}
MC_Lighter=MC_White;
Remap_menu_sprites(); Remap_menu_sprites();
} }
@ -2923,18 +3059,20 @@ void Remap_menu_sprites()
for (i=0; i<CURSOR_SPRITE_WIDTH; i++) for (i=0; i<CURSOR_SPRITE_WIDTH; i++)
Remap_pixel(&Gfx->Cursor_sprite[k][j][i]); Remap_pixel(&Gfx->Cursor_sprite[k][j][i]);
// Main menu bar // Main menu bar
for (j=0; j<Menu_bars[MENUBAR_TOOLS].Height; j++) for (k=0; k<3; k++)
for (i=0; i<Menu_bars[MENUBAR_TOOLS].Skin_width; i++) for (j=0; j<Menu_bars[MENUBAR_TOOLS].Height; j++)
Remap_pixel(&Gfx->Menu_block[j][i]); for (i=0; i<Menu_bars[MENUBAR_TOOLS].Skin_width; i++)
Remap_pixel(&Gfx->Menu_block[k][j][i]);
// Menu sprites // Menu sprites
for (k=0; k<NB_MENU_SPRITES; k++) for (l=0; l<2; l++)
for (j=0; j<MENU_SPRITE_HEIGHT; j++) for (k=0; k<NB_MENU_SPRITES; k++)
for (i=0; i<MENU_SPRITE_WIDTH; i++) for (j=0; j<MENU_SPRITE_HEIGHT; j++)
Remap_pixel(&Gfx->Menu_sprite[k][j][i]); for (i=0; i<MENU_SPRITE_WIDTH; i++)
Remap_pixel(&Gfx->Menu_sprite[l][k][j][i]);
// Effects sprites // Effects sprites
for (k=0; k<NB_EFFECTS_SPRITES; k++) for (k=0; k<NB_EFFECTS_SPRITES; k++)
for (j=0; j<MENU_SPRITE_HEIGHT; j++) for (j=0; j<EFFECT_SPRITE_HEIGHT; j++)
for (i=0; i<MENU_SPRITE_WIDTH; i++) for (i=0; i<EFFECT_SPRITE_WIDTH; i++)
Remap_pixel(&Gfx->Effect_sprite[k][j][i]); Remap_pixel(&Gfx->Effect_sprite[k][j][i]);
// Layers buttons // Layers buttons
for (l=0; l<3; l++) for (l=0; l<3; l++)
@ -2944,13 +3082,15 @@ void Remap_menu_sprites()
Remap_pixel(&Gfx->Layer_sprite[l][k][j][i]); Remap_pixel(&Gfx->Layer_sprite[l][k][j][i]);
// Status bar // Status bar
for (j=0; j<Menu_bars[MENUBAR_STATUS].Height; j++) for (k=0; k<3; k++)
for (i=0; i<Menu_bars[MENUBAR_STATUS].Skin_width; i++) for (j=0; j<Menu_bars[MENUBAR_STATUS].Height; j++)
Remap_pixel(&Gfx->Statusbar_block[j][i]); for (i=0; i<Menu_bars[MENUBAR_STATUS].Skin_width; i++)
Remap_pixel(&Gfx->Statusbar_block[k][j][i]);
// Layer bar // Layer bar
for (j=0; j<Menu_bars[MENUBAR_LAYERS].Height; j++) for (k=0; k<3; k++)
for (i=0; i<Menu_bars[MENUBAR_LAYERS].Skin_width; i++) for (j=0; j<Menu_bars[MENUBAR_LAYERS].Height; j++)
Remap_pixel(&Gfx->Layerbar_block[j][i]); for (i=0; i<Menu_bars[MENUBAR_LAYERS].Skin_width; i++)
Remap_pixel(&Gfx->Layerbar_block[k][j][i]);
// Help fonts // Help fonts
for (k=0; k<256; k++) for (k=0; k<256; k++)

View File

@ -89,7 +89,7 @@ void Window_display_frame_in(word x_pos,word y_pos,word width,word height);
void Window_display_frame_out(word x_pos,word y_pos,word width,word height); void Window_display_frame_out(word x_pos,word y_pos,word width,word height);
void Window_display_frame(word x_pos,word y_pos,word width,word height); void Window_display_frame(word x_pos,word y_pos,word width,word height);
void Display_sprite_in_menu(int btn_number,int sprite_number); void Display_sprite_in_menu(int btn_number,char sprite_number);
void Display_paintbrush_in_menu(void); void Display_paintbrush_in_menu(void);
void Display_paintbrush_in_window(word x,word y,int number); void Display_paintbrush_in_window(word x,word y,int number);
@ -99,6 +99,7 @@ void Window_display_icon_sprite(word x_pos,word y_pos,byte type);
byte Best_color(byte red,byte green,byte blue); byte Best_color(byte red,byte green,byte blue);
byte Best_color_nonexcluded(byte red,byte green,byte blue); byte Best_color_nonexcluded(byte red,byte green,byte blue);
byte Best_color_perceptual(byte r,byte g,byte b);
void Horizontal_XOR_line_zoom(short x_pos, short y_pos, short width); void Horizontal_XOR_line_zoom(short x_pos, short y_pos, short width);
void Vertical_XOR_line_zoom(short x_pos, short y_pos, short height); void Vertical_XOR_line_zoom(short x_pos, short y_pos, short height);
@ -108,4 +109,7 @@ void Change_magnifier_factor(byte factor_index, byte point_at_mouse);
/// Width of one layer button, in pixels before scaling /// Width of one layer button, in pixels before scaling
extern word Layer_button_width; extern word Layer_button_width;
/// Copy viewport settings and offsets from the Main to the Spare.
void Copy_view_to_spare(void);
#endif #endif