Added grafx2 app

This commit is contained in:
pelya
2011-07-05 15:12:35 +03:00
parent 2d4a420797
commit b4546c9687
101 changed files with 72563 additions and 4292 deletions

16
checkMissing.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/sh
# Print list of symbols inside libapplication.so which are not defined in Android libc
# Internal compiler things like '__aeabi_ddiv' or '___Unwind_Resume' may be safely ignored
rm -f exports.txt libapplication.txt
cat exports-eclair.txt > exports.txt
nm -g -p --undefined-only project/obj/local/armeabi/libapplication.so | cut -b 12- | sort > libapplication.txt
for f in project/obj/local/armeabi/*.so; do
if [ "$f" = "project/obj/local/armeabi/libapplication.so" ]; then
continue
fi
nm -g -p --defined-only $f 2>/dev/null | cut -b 12- >> exports.txt
done
cat exports.txt | sort > exports1.txt
mv -f exports1.txt exports.txt
diff libapplication.txt exports.txt | grep \< | cut -d \ -f 2
rm libapplication.txt exports.txt

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,36 @@
# The application settings for Android libSDL port
AppSettingVersion=17
LibSdlVersion=1.2
AppName="grafx2"
AppFullName=com.grafx2
ScreenOrientation=h
InhibitSuspend=y
AppDataDownloadUrl="!Data|data.zip"
SdlVideoResize=y
SdlVideoResizeKeepAspect=n
NeedDepthBuffer=n
SwVideoMode=y
AppUsesMouse=y
AppNeedsTwoButtonMouse=y
AppNeedsArrowKeys=n
AppNeedsTextInput=n
AppUsesJoystick=n
AppHandlesJoystickSensitivity=y
AppUsesMultitouch=n
NonBlockingSwapBuffers=n
RedefinedKeys="SPACE TAB NO_REMAP NO_REMAP RETURN ESCAPE DELETE"
AppTouchscreenKeyboardKeysAmount=0
AppTouchscreenKeyboardKeysAmountAutoFire=0
RedefinedKeysScreenKb="SPACE TAB PLUS MINUS RETURN ESCAPE DELETE"
StartupMenuButtonTimeout=3000
HiddenMenuOptions='OptionalDownloadConfig'
MultiABI=n
AppVersionCode=23178101
AppVersionName="2.3.1781.01"
CompiledLibraries="jpeg png sdl_image sdl_ttf lua"
CustomBuildScript=n
AppCflags='-DVIRT_KEY -D__ENABLE_LUA__ -std=c99'
AppLdflags=''
AppSubdirsBuild='grafx2/src'
AppCmdline='sdl'
ReadmeText='^You may press "Home" now - the data will be downloaded in background'

Binary file not shown.

View File

@@ -0,0 +1,11 @@
/* SDLMain.m - main entry point for our Cocoa-ized SDL app
Initial Version: Darrell Walisser <dwaliss1@purdue.edu>
Non-NIB-Code & other changes: Max Horn <max@quendi.de>
Feel free to customize this file to suit your needs
*/
#import <Cocoa/Cocoa.h>
@interface SDLMain : NSObject
@end

View File

@@ -0,0 +1,224 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* SFont: a simple font-library that uses special .pngs as fonts
Copyright (C) 2003 Karl Bartel
License: GPL or LGPL (at your choice)
WWW: http://www.linux-games.com/sfont/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
Karl Bartel
Cecilienstr. 14
12307 Berlin
GERMANY
karlb@gmx.net
*/
#include <SDL.h>
#include <SDL_video.h>
#include <assert.h>
#include <stdlib.h>
#include "SFont.h"
static Uint32 GetPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y)
{
Uint8 *bits;
Uint32 Bpp;
assert(X>=0);
assert(X<Surface->w);
Bpp = Surface->format->BytesPerPixel;
bits = ((Uint8 *)Surface->pixels)+Y*Surface->pitch+X*Bpp;
// Get the pixel
switch(Bpp) {
case 1:
return *((Uint8 *)Surface->pixels + Y * Surface->pitch + X);
break;
case 2:
return *((Uint16 *)Surface->pixels + Y * Surface->pitch/2 + X);
break;
case 3: { // Format/endian independent
Uint8 r, g, b;
r = *((bits)+Surface->format->Rshift/8);
g = *((bits)+Surface->format->Gshift/8);
b = *((bits)+Surface->format->Bshift/8);
return SDL_MapRGB(Surface->format, r, g, b);
}
break;
case 4:
return *((Uint32 *)Surface->pixels + Y * Surface->pitch/4 + X);
break;
}
return -1;
}
SFont_Font* SFont_InitFont(SDL_Surface* Surface)
{
int x = 0, i = 33;
Uint32 pixel;
SFont_Font* Font;
Uint32 pink;
if (Surface == NULL)
return NULL;
Font = (SFont_Font *) malloc(sizeof(SFont_Font));
memset(Font, 0, sizeof(SFont_Font));
Font->Surface = Surface;
SDL_LockSurface(Surface);
pink = GetPixel(Surface, 0, 0);
while (x < Surface->w) {
if (GetPixel(Surface, x, 0) != pink) {
Font->CharBegin[i]=x;
while((x < Surface->w) && (GetPixel(Surface, x, 0)!= pink))
x++;
Font->CharWidth[i]=x-Font->CharBegin[i];
i++;
}
x++;
}
// 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);
SDL_UnlockSurface(Surface);
// No longer use SDL color keying
//SDL_SetColorKey(Surface, SDL_SRCCOLORKEY, pixel);
Font->Transparent=pixel;
return Font;
}
void SFont_FreeFont(SFont_Font* FontInfo)
{
SDL_FreeSurface(FontInfo->Surface);
free(FontInfo);
}
void SFont_Write(SDL_Surface *Surface, const SFont_Font *Font,
int x, int y, const char *text)
{
const char* c;
SDL_Rect srcrect, dstrect;
if(text == NULL)
return;
// these values won't change in the loop
srcrect.y = 1;
dstrect.y = y;
srcrect.h = dstrect.h = Font->Surface->h - 1;
for(c = text; *c != '\0' && x <= Surface->w ; c++) {
if (*c == '\n') {
dstrect.y += Font->Surface->h-1;
x=0;
continue;
}
// skip spaces and nonprintable characters
else if (*c == ' ' || Font->CharWidth[(int)*c]==0) {
x += Font->Space;
continue;
}
srcrect.w = Font->CharWidth[(int)*c];
dstrect.w = srcrect.w;
srcrect.x = Font->CharBegin[(int)*c];
dstrect.x = x;
SDL_BlitSurface(Font->Surface, &srcrect, Surface, &dstrect);
x += Font->CharWidth[(int)*c];
}
}
int SFont_TextWidth(const SFont_Font *Font, const char *text)
{
const char* c;
int width = 0;
int previous_width = 0;
if(text == NULL)
return 0;
for(c = text; *c != '\0'; c++)
{
if (*c == '\n')
{
if (previous_width<width)
previous_width=width;
width=0;
}
else
// skip spaces and nonprintable characters
if (*c == ' ' || Font->CharWidth[(int)*c]==0)
{
width += Font->Space;
continue;
}
width += Font->CharWidth[(int)*c];
}
return previous_width<width ? width : previous_width;
}
int SFont_TextHeight(const SFont_Font* Font, const char *text)
{
// Count occurences of '\n'
int nb_cr=0;
while (*text!='\0')
{
if (*text=='\n')
nb_cr++;
text++;
}
return (Font->Surface->h - 1) * (nb_cr+1);
}
/*
// Do not use: Doesn't implement carriage returns
void SFont_WriteCenter(SDL_Surface *Surface, const SFont_Font *Font,
int y, const char *text)
{
SFont_Write(Surface, Font, Surface->w/2 - SFont_TextWidth(Font, text)/2,
y, text);
}
*/

View File

@@ -0,0 +1,100 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* SFont: a simple font-library that uses special bitmaps as fonts
Copyright (C) 2003 Karl Bartel
License: GPL or LGPL (at your choice)
WWW: http://www.linux-games.com/sfont/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
Karl Bartel
Cecilienstr. 14
12307 Berlin
GERMANY
karlb@gmx.net
*/
/************************************************************************
* SFONT - SDL Font Library by Karl Bartel <karlb@gmx.net> *
* *
* All functions are explained below. For further information, take a *
* look at the example files, the links at the SFont web site, or *
* contact me, if you problem isn' addressed anywhere. *
* *
************************************************************************/
//////////////////////////////////////////////////////////////////////////////
///@file SFont.h
/// Text rendering system, that uses bitmaps as fonts.
/// Not specific to Grafx2, it writes to SDL_Surface.
//////////////////////////////////////////////////////////////////////////////
#ifndef _SFONT_H_
#define _SFONT_H_
#include <SDL.h>
#ifdef __cplusplus
extern "C" {
#endif
///
/// Declare one variable of this type for each font you are using.
/// To load the fonts, load the font image into YourFont->Surface
/// and call InitFont( YourFont );
typedef struct {
SDL_Surface *Surface;
int CharBegin[256];
int CharWidth[256];
int Space;
unsigned char Transparent;
} SFont_Font;
///
/// Initializes the font.
/// @param Font this contains the suface with the font.
/// The Surface must be loaded before calling this function
SFont_Font* SFont_InitFont (SDL_Surface *Font);
///
/// Frees the font.
/// @param Font The font to free
/// The font must be loaded before using this function.
void SFont_FreeFont(SFont_Font* Font);
///
/// Blits a string to a surface.
/// @param Surface The surface you want to blit to.
/// @param Font The font to use.
/// @param text A string containing the text you want to blit.
/// @param x Coordinates to start drawing.
/// @param y Coordinates to start drawing.
void SFont_Write(SDL_Surface *Surface, const SFont_Font *Font, int x, int y,
const char *text);
/// Returns the width of "text" in pixels
int SFont_TextWidth(const SFont_Font* Font, const char *text);
/// Returns the height of "text" in pixels (which is always equal to Font->Surface->h)
int SFont_TextHeight(const SFont_Font* Font, const char *text);
/// Blits a string to Surface with centered x position
void SFont_WriteCenter(SDL_Surface *Surface, const SFont_Font* Font, int y,
const char *text);
#ifdef __cplusplus
}
#endif
#endif /* SFONT_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,129 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007-2008 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 brush.h
/// Actions on the brush.
//////////////////////////////////////////////////////////////////////////////
#ifndef __BRUSH_H_
#define __BRUSH_H_
#include "struct.h"
/*!
Gets the brush from the picture.
@param start_x left edge coordinate in the picture
@param start_y upper edge coordinate in the picture
@param end_x right edge coordinate in the picture
@param end_y bottom edge coordinate in the picture
@param clear If 1, the area is also cleared from the picture.
*/
void Capture_brush(short start_x,short start_y,short end_x,short end_y,short clear);
/*!
Rotates the brush to the right.
*/
void Rotate_90_deg(void);
/*!
Stretch the brush to fit the given rectangle.
*/
void Stretch_brush(short x1, short y1, short x2, short y2);
/*!
Stretch the brush to fit the given rectangle.
Uses fast approximation for the preview while drawing the rectangle on screen.
*/
void Stretch_brush_preview(short x1, short y1, short x2, short y2);
/*!
Rotates the brush to the right from the given angle.
*/
void Rotate_brush(float angle);
/*!
Stretch the brush to fit the given rectangle.
Uses fast approximation for the preview while changing the angle.
*/
void Rotate_brush_preview(float angle);
/*!
Remap the brush palette to the nearest color in the picture one.
Used when switching to the spare page.
*/
/*!
Distort the brush on the screen.
*/
void Distort_brush_preview(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4);
/*!
Replace the brush by a distorted version of itself.
*/
void Distort_brush(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4);
void Remap_brush(void);
/*!
Get color indexes used by the brush.
*/
void Get_colors_from_brush(void);
/*!
Outline the brush, add 1 foreground-colored pixel on the edges.
Edges are detected considering the backcolor as transparent.
*/
void Outline_brush(void);
/*!
Nibble the brush, remove 1 pixel on the edges and make it transparent (ie filled with back color).
Edges are detected considering the backcolor as transparent.
*/
void Nibble_brush(void);
/*!
Get brush from picture according to a freehand form.
@param vertices number of points in the freehand form
@param points array of points coordinates
@param clear If set to 1, the captured area is also cleared from the picture.
*/
void Capture_brush_with_lasso(int vertices, short * points,short clear);
///
/// Changes the Brush size.
/// @return 0 on success, non-zero on failure (memory?).
/// @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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,678 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 buttons.h
/// Almost all the editor actions that are called by the menu are here.
////////////////////////////////////////////////////////////////////////////
#ifndef __BOUTONS_H_
#define __BOUTONS_H_
#include "struct.h"
void Stencil_update_color(byte color);
void Stencil_tag_color(byte color, byte tag_color);
/*!
Displays an error message when there is no more memory for the requested
operation.
*/
void Message_out_of_memory(void);
/*!
Displays the splash screen at program startup.
*/
void Button_Message_initial(void);
/*!
Changes brush shape.
This function saves the current brush shape and swith to the default one
(single pixel brush) for the filler and the color picker.
These functions don't need (and will not work with) a custom brush.
*/
void Change_paintbrush_shape(byte shape);
// Boutons relatifs aux couleurs
/*!
Callback for the palette scroller buttons left click.
Scrolls the menubar palette one column to the left.
*/
void Button_Pal_left(void);
/*!
Callback for the palette scroller buttons right click.
Scrolls the menubar palette faster to the left.
*/
void Button_Pal_left_fast(void);
/*!
Callback for the palette scroller buttons left click.
Scrolls the menubar palette one column to the right.
*/
void Button_Pal_right(void);
/*!
Callback for the palette scroller buttons right click.
Scrolls the menubar palette faster to the right.
*/
void Button_Pal_right_fast(void);
/*!
Callback for the palette color buttons left click.
Selects the foreground drawing color when clicking on the menubar palette.
*/
void Button_Select_forecolor(void);
/*!
Callback for the palette color buttons right click.
Selects the background drawing color when clicking on the menubar palette.
*/
void Button_Select_backcolor(void);
// Boutons relatifs au pinceaux
/*!
Callback for the brush button left click.
Selects the monochrome brush mode when right clicking on the brush button.
*/
void Button_Brush_monochrome(void);
/*!
Callback for the brush button right click.
Displays the "Paintbrush menu".
*/
void Button_Paintbrush_menu(void);
// Boutons relatifs au mode de dessin à main levée
/*!
Callback for the freehand draw button left click.
Selects freehand drawing mode, depending on the current state of the freehand button.
*/
void Button_Draw(void);
/*!
Callback for the freehand draw button right click.
Cycles the drawing modes for the freehand tool.
*/
void Button_Draw_switch_mode(void);
// Dessin par ligne
/*!
Callback for the lines button left click.
Selects lines drawing mode, depending on the current state of the lines button.
*/
void Button_Lines(void);
/*!
Callback for the lines button right click.
Cycles the drawing modes for the lines tool.
*/
void Button_Lines_switch_mode(void);
// Button relatif au remplissage
/*!
Callback for the fill button left click.
Start the filling operation.
*/
void Button_Fill(void);
/*!
Callback for the fill button right click.
Start the color replace operation.
*/
void Button_Replace(void);
/*!
Disable and release the fill button.
Restores the cursor (custom brushes are disabled for the fill operation).
Cleans the status bar if the color replacement tool put a preview color inside it.
*/
void Button_Unselect_fill(void);
// Spray
/*!
Callback for the spray button left click.
Start the spray operation.
*/
void Button_Airbrush(void);
/*!
Callback for the spray button right click.
Opens the spray's setup menu.
*/
void Button_Airbrush_menu(void);
// Courbes de Bézier
/*!
Callback for the curves button left click.
Start curve operation according to the selected mode.
*/
void Button_Curves(void);
/*!
Callback for the curves button right click.
Select the curve mode (1-point, 2-point)
*/
void Button_Curves_switch_mode(void);
// Boutons relatifs aux rectangles pleins et vides
/*!
Callback for the empty rectangle button.
Start the rectangle operation.
*/
void Button_Empty_rectangle(void);
/*!
Callback for the filled rectangle button.
Start the filled rectangle operation.
*/
void Button_Filled_rectangle(void);
// Boutons relatifs au texte
/*!
Callback for the text button.
Opens the text setup window.
*/
void Button_Text(void);
// Boutons relatifs aux dégradés
/*!
Callback for the gradation button.
Opens the "Gradation menu".
*/
void Button_Gradients(void);
/*!
Gets the informations from the gradations table and set the global vars for the current gradation.
@param index index of the selected gradation
*/
void Load_gradient_data(int index);
// Boutons relatifs aux cercles (ellipses) dégradé(e)s
/*!
Callback for the gradation circle button left click.
Starts drawing a gradation circle.
*/
void Button_Grad_circle(void);
/*!
Callback for the gradation circle right click.
Starts drawing a gradation ellipsis.
*/
void Button_Grad_ellipse(void);
/*!
Callback for the gradation rectangle button.
Starts the gradation rectangle drawing operation.
*/
void Button_Grad_rectangle(void);
// Boutons relatifs aux cercles (ellipses) plein(e)s et vides
/*!
Callback for the circle button left click.
Starts drawing an empty circle
*/
void Button_Empty_circle(void);
/*!
Callback for the circle button left click.
Starts drawing an empty ellipsis
*/
void Button_Empty_ellipse(void);
/*!
Callback for the filled circle button ledt click.
Starts drawing a filled circle.
*/
void Button_Filled_circle(void);
/*!
Callback for the filled circle right click.
Starts drawing a filled ellipsis.
*/
void Button_Filled_ellipse(void);
// Boutons relatifs aux polygones vides et pleins
/*!
Callback for the polyline button left click.
Starts drawing a polygon.
*/
void Button_polygon(void);
/*!
Callback for the polyline right click.
Starts drawing a polyform.
*/
void Button_Polyform(void);
/*!
Callback for the polyfill button left click.
Starts drawing a filled polygon.
*/
void Button_Polyfill(void);
/*!
Callback for the polyfill button right click.
Starts drawing a filled polyform.
*/
void Button_Filled_polyform(void);
// Boutons d'ajustement de l'image
/*!
Callback for the adjust picture button.
Start the adjust picture operation.
*/
void Button_Adjust(void);
// Gestion du mode Shade
/*!
Callback for the shade button (in the FX window).
Toogle the shade mode.
*/
void Button_Shade_mode(void);
/*!
Callback for the QSHade button (in the FX window).
Toogle the Quick Shade effect.
*/
void Button_Quick_shade_mode(void);
/*!
Callback for the Shade button (in the FX window) right click.
Displays the shade setup menu.
*/
void Button_Shade_menu(void);
// Gestion du Stencil
/*!
Callback for the Stencil button (in the FX window) left click.
Toogle stencil mode.
*/
void Button_Stencil_mode(void);
/*!
Callback for the Stencil button (in the FX window) right click.
Displays the stencil setup menu.
*/
void Button_Stencil_menu(void);
// Gestion du Masque
/*!
Callback for the Mask button (in the FX window) left click.
Toogles the mask mode/
*/
void Button_Mask_mode(void);
/*!
Callback for the Mask button (in the FX window) right click.
Displays the mask setup menu.
*/
void Button_Mask_menu(void);
// Mode grille (Snap)
/*!
Callback for the Grid button (in the FX window) left click.
Toogle the grid.
*/
void Button_Snap_mode(void);
/*!
Callback for the Grid button (in the FX window) right click.
Displays the grid setup menu.
*/
void Button_Grid_menu(void);
/*!
Callback to toggle the grid visible in the magnified view.
*/
void Button_Show_grid(void);
// Mode trame (Sieve)
/*!
In the sieve window, copy one of the presets patterns to the current one.
@param index Index of the pattern to copy
*/
void Copy_preset_sieve(byte index);
/*!
In the sieve window, swaps black and white in the current pattern.
*/
void Invert_trame(void);
/*!
Callback for the Sieve button (in the FX window) left click.
Toogle sieve mode.
*/
void Button_Sieve_mode(void);
/*!
Callback for the Sieve button (in the FX window) right click.
Displays the sieve setup menu.
*/
void Button_Sieve_menu(void);
// Mode Smooth
/*!
Callback for the smooth button (in the FX window) left click.
Toogles smooth mode.
*/
void Button_Smooth_mode(void);
/*!
Callback for the Smooth button (in the FX window) right click.
Displays the smooth setup menu.
*/
void Button_Smooth_mode(void);
// Boutons relatifs au mode Colorize
/*!
Computes the tables used by the transparency/colorize mode.
These tables are used to match the drawing color*picture color to the color that is painted on screen.
*/
void Compute_colorize_table(void);
/*!
Callback for the Tranparency button (in the FX window) left click.
Toogles transparent drawing mode.
*/
void Button_Colorize_mode(void);
/*!
Callback for the Transparency button (in the FX window) right click.
Displays the tranparency setup menu.
*/
void Button_Colorize_menu(void);
// Boutons relatifs au mode Tiling
/*!
Callback for the Tiling button (in the FX window) left click.
Toogles tiling mode.
*/
void Button_Tiling_mode(void);
/*!
Callback for the Tiling button (in the FX window) right click.
Displays the tiling setup menu.
*/
void Button_Tiling_menu(void);
/*!
Callback for the command that turns off all drawaing effects.
*/
void Effects_off(void);
// Menu des effets
/*!
Callback for the effects button click.
Displays the effect selection menu.
*/
void Button_Effects(void);
// Prise de brosse
/*!
Callback for the brush button left click.
Start the brush picking operation.
*/
void Button_Brush(void);
/*!
Callback for the brush button right click.
Activates the last captured custom brush.
*/
void Button_Restore_brush(void);
/*!
Disables the custom brush and set back a regular one.
*/
void Button_Unselect_brush(void);
// Prise de brosse au lasso
/*!
Callback for the freehand brush pick button left click.
Starts freehand brush picking operation.
*/
void Button_Lasso(void);
/*!
Disables the custom freehand brush and set back a regular one.
*/
void Button_Unselect_lasso(void);
// Button relatifs à la pipette
/*!
Starts the color picking operation.
*/
void Button_Colorpicker(void);
/*!
Disables the color picker button and get back to the previously selected drawing mode.
*/
void Button_Unselect_colorpicker(void);
/*!
Swap fore- and background colors.
*/
void Button_Invert_foreback(void);
// Mode loupe
/*!
Enters magnify mode.
*/
void Button_Magnify(void);
/*!
Displays magnify menu.
*/
void Button_Magnify_menu(void);
/*!
Exit magnify mode.
*/
void Button_Unselect_magnifier(void);
// Les différents effets sur la brosse
/*!
Display the Brush effects window.
*/
void Button_Brush_FX(void);
// Boutons relatifs aux différentes pages
/*!
Swap main and spare drawing pages.
*/
void Button_Page(void);
/*!
Copy main page to spare page.
*/
void Button_Copy_page(void);
/*!
Copy only pixel data from main page to spare page (no palette copy).
*/
void Copy_image_only(void);
/*!
Kill (free from memory) the current page.
*/
void Button_Kill(void);
// Boutons relatifs aux changements de résolution et de taille d'image
/*!
Display the screenmode menu.
*/
void Button_Resolution(void);
/*!
Set the screen to the "safe resolution" (320x200 pixel window).
*/
void Button_Safety_resolution(void);
// Boutons relatifs aux chargements et sauvegardes
/*!
Opens the load file dialog.
*/
void Button_Load(void);
/*!
Reload current picture from disk.
*/
void Button_Reload(void);
/*!
Open the save file dialog.
*/
void Button_Save(void);
/*!
Saves the current file without asking for a new name.
*/
void Button_Autosave(void);
// Réglage des paramètres de l'utilisateur
/*!
Display the setting menu.
*/
void Button_Settings(void);
/*!
Display the skin selector window.
*/
void Button_Skins(void);
// Annulation de la dernière modification
/*!
Undo the last modification to the picture.
*/
void Button_Undo(void);
/*!
Redo an operation that has been undone.
*/
void Button_Redo(void);
// Boutons relatifs aux effacements d'images
/*!
Clear the whole screen with black (color index 0).
*/
void Button_Clear(void);
/*!
Clear the screen with the selected backcolor.
*/
void Button_Clear_with_backcolor(void);
// Quitter le programme
/*!
Quits the program. Display a requester to save the changes to the picture before exiting if the pic was modified since last save.
*/
void Button_Quit(void);
// Cacher le menu
/*!
Hides the menubar.
*/
void Button_Hide_menu(void);
/*!
Shows a dropdown panel where you can choose which toolbars are visible
*/
void Button_Toggle_toolbar(void);
/*!
Hides all toolbars (except status) or shows them again
*/
void Button_Toggle_all_toolbars(void);
/*!
Load picture from file.
*/
void Load_picture(byte image);
/*!
Save picture to file.
*/
void Save_picture(byte image);
/*!
Generic color tagging menu, for various effects.
*/
void Menu_tag_colors(char * window_title, byte * table, byte * mode, byte can_cancel, const char *help_section, word close_shortcut );
/*!
Display the menu for the smooth effect.
*/
void Button_Smooth_menu(void);
/*!
Toogles the smear mode.
*/
void Button_Smear_mode(void);
void Button_Brush_container(void);
byte Store_paintbrush(int index);
void Select_paintbrush(int index);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,529 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 const.h
/// Constants (preprocessor defines) and enumerations used anywhere.
//////////////////////////////////////////////////////////////////////////////
#ifndef _CONST_H_
#define _CONST_H_
#ifndef M_2PI
#define M_2PI 6.28318530717958647692528676656 ///< Hmm, pie...
#endif
#define VERSION1 2 ///< Version number for gfx2.cfg (1/4)
#define VERSION2 0 ///< Version number for gfx2.cfg (2/4)
#define BETA1 98 ///< Version number for gfx2.cfg (3/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 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_HEIGHT 44 ///< Height of the menu.
#define NB_CURSOR_SPRITES 8 ///< Number of available mouse cursor sprites.
#define CURSOR_SPRITE_WIDTH 15 ///< Width 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 MENU_SPRITE_WIDTH 16 ///< Width of a menu sprite in pixels
#define MENU_SPRITE_HEIGHT 16 ///< 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_HEIGHT 10 ///< Height of a layer button in pixels
#define PAINTBRUSH_WIDTH 16 ///< Width of a preset paintbrush sprite
#define PAINTBRUSH_HEIGHT 16 ///< Height of a preset paintbrush sprite
#define MAX_PAINTBRUSH_SIZE 127 ///< Max size for a resizable paintbrush
#define ICON_SPRITE_WIDTH 8 ///< Width of an icon in pixels
#define ICON_SPRITE_HEIGHT 8 ///< Height of an icon in pixels
#define NB_PAINTBRUSH_SPRITES 48 ///< Number of preset paintbrushes
#define NB_PRESET_SIEVE 12 ///< Number of preset sieve patterns
#define OPERATION_STACK_SIZE 16 ///< Max number of parameters in the operation stack.
#define MAX_DISPLAYABLE_PATH 37 ///< Max number of characters to display directory name, in Save/Load screens.
#define COMMENT_SIZE 32 ///< Max number of characters for a comment in PKM or PNG file.
#define NB_MAX_PAGES_UNDO 99 ///< Max number of undo pages
#define DEFAULT_ZOOM_FACTOR 4 ///< Initial zoom factor for the magnifier.
#define MAX_PATH_CHARACTERS 260 ///< Number of characters for a file+complete path. Adapt to your OS...
#define NB_BOOKMARKS 4 ///< Number of bookmark buttons in Save/Load screen.
// Character to show a right arrow, used when editing long strings. It's present in ::Gfx->System_font
#define RIGHT_TRIANGLE_CHARACTER 16
// Character to show a left arrow, used when editing long strings. It's present in ::Gfx->System_font
#define LEFT_TRIANGLE_CHARACTER 17
/// Character to display in menus for an ellipsis.
#define ELLIPSIS_CHARACTER '…'
#define NB_LAYERS 1 ///< Initial number of layers for a new image
#define MAX_NB_LAYERS 16 ///< Maximum number of layers that can be used in grafx2. Note that 32 is upper limit because of a few bit fields.
#define BRUSH_CONTAINER_PREVIEW_WIDTH 16 ///< Size for preview of a brush in Brush container
#define BRUSH_CONTAINER_PREVIEW_HEIGHT 16 ///< Size for preview of a brush in Brush container
#define BRUSH_CONTAINER_COLUMNS 4 ///< Number of columns in the Brush container
#define BRUSH_CONTAINER_ROWS 3 ///< Number of rows in the Brush container
///
/// We force the dynamic backup page allocation to leave a minimum of
/// 256Kb of free memory, to allow the rest of the program to work safely.
/// Note: This is a remainder of the DOS version. This system might not work
/// so well on other OSes, where the "available memory" changes due to external
/// factors.
#define MINIMAL_MEMORY_TO_RESERVE (256*1024)
#define LEFT_SIDE 1 ///< Indicates a left side or left-click
#define RIGHT_SIDE 2 ///< Indicates a right side or right-click
#define SEPARATOR_WIDTH 6 ///< Width of the separator between the normal and the zoomed view
#define INITIAL_SEPARATOR_PROPORTION 0.3 ///< Proportion of the normal view width, relative to the whole screen width.
#define NB_ZOOMED_PIXELS_MIN 4 ///< Minimal number of pixel shown (in width) by the zoomed view. (Note: below 4, you can't scroll!)
#if defined(__MORPHOS__) || defined(__amigaos4__) || defined(__amigaos__)
#define PARENT_DIR "/"
#else
/// Filename that means "parent directory" for your operating system.
#define PARENT_DIR ".."
#endif
/// List of file formats recognized by grafx2
enum FILE_FORMATS
{
FORMAT_ALL_IMAGES=0, ///< This is not really a file format, it's reserverd for a compilation of all file extensions
FORMAT_ALL_FILES=1, ///< This is not really a file format, it's reserverd for the "*.*" filter option.
FORMAT_PNG,
FORMAT_GIF,
FORMAT_BMP,
FORMAT_PCX,
FORMAT_PKM,
FORMAT_LBM,
FORMAT_IMG,
FORMAT_SCx,
FORMAT_PI1,
FORMAT_PC1,
FORMAT_CEL,
FORMAT_NEO,
FORMAT_C64,
FORMAT_KCF,
FORMAT_PAL,
FORMAT_SCR,
FORMAT_XPM,
FORMAT_MISC, ///< Must be last of enum: others formats recognized by SDL_image
};
/// Default format for 'save as'
#define DEFAULT_FILEFORMAT FORMAT_GIF
/// Error codes for ::Error()
enum ERROR_CODES
{
ERROR_WARNING=0, ///< Red flash on screen, non-fatal error
ERROR_GUI_MISSING, ///< The graphics file is missing
ERROR_GUI_CORRUPTED, ///< The graphics file cannot be parsed for GUI elements
ERROR_INI_MISSING, ///< File gfx2def.ini is missing
ERROR_CFG_MISSING, ///< File gfx2.cfg is missing (non-fatal)
ERROR_CFG_CORRUPTED, ///< File gfx2.cfg couldn't be parsed (non-fatal)
ERROR_CFG_OLD, ///< Unknown version of gfx2.cfg : either VERY old or wrong file (non-fatal)
ERROR_MEMORY, ///< Out of memory
ERROR_COMMAND_LINE, ///< Error in command-line arguments (syntax, or couldn't find the file to open)
ERROR_FORBIDDEN_MODE, ///< Graphics mode requested is not supported
ERROR_SAVING_CFG, ///< Error while writing gfx2.cfg
ERROR_MISSING_DIRECTORY, ///< Unable to return to the original "current directory" on program exit
ERROR_INI_CORRUPTED, ///< File gfx2.ini couldn't be parsed
ERROR_SAVING_INI, ///< Error while writing gfx2.ini
ERROR_SORRY_SORRY_SORRY ///< (Page allocation error that shouldn't ever happen, now)
};
/// Available pixel scalers
enum PIXEL_RATIO
{
PIXEL_SIMPLE=0, ///< Use real pixels
PIXEL_WIDE, ///< Use wide pixels (2x1) like on Amstrad CPC mode 0
PIXEL_TALL, ///< Use tall pixels (1x2) like on Amstrad CPC mode 2
PIXEL_DOUBLE, ///< Use big pixels (2x2) if your LCD screen can't do lowres by itself
PIXEL_TRIPLE, ///< Use really big pixels (3x3)
PIXEL_WIDE2, ///< Use big wide pixels (4x2)
PIXEL_TALL2, ///< Use big tall pixels (2x4)
PIXEL_QUAD, ///< Use really giant pixels (4x4). You need to have a screen resolution at least 1280x800 to use this one
PIXEL_MAX ///< Number of elements in enum
};
/// Different kinds of menu button behavior.
enum FAMILY_OF_BUTTONS
{
FAMILY_TOOL=1, ///< Drawing tools (example : Freehand draw)
FAMILY_INTERRUPTION, ///< Temporary operation (example : choosing paintbrush) > Interrupts the current operation to do something, then come back.
FAMILY_INSTANT, ///< Single-click action (example : choose a color in palette) > It will be over as soon as we exit the called function.
FAMILY_TOOLBAR, ///< Hide/show the menu
FAMILY_EFFECTS ///< Effects
};
/// The different kinds of buttons in menus or windows.
enum BUTTON_SHAPES
{
BUTTON_SHAPE_NO_FRAME, ///< Ex: the palette
BUTTON_SHAPE_RECTANGLE, ///< Ex: Most buttons.
BUTTON_SHAPE_TRIANGLE_TOP_LEFT, ///< Ex: Empty rectangles.
BUTTON_SHAPE_TRIANGLE_BOTTOM_RIGHT ///< Ex: Filled rectangles.
};
/// The different "mouse cursor" shapes
enum CURSOR_SHAPES
{
CURSOR_SHAPE_ARROW,
CURSOR_SHAPE_TARGET, ///< This one uses the paintbrush
CURSOR_SHAPE_COLORPICKER, ///< This one uses the paintbrush
CURSOR_SHAPE_HOURGLASS,
CURSOR_SHAPE_MULTIDIRECTIONAL,
CURSOR_SHAPE_HORIZONTAL,
CURSOR_SHAPE_THIN_TARGET, ///< This one uses the paintbrush
CURSOR_SHAPE_THIN_COLORPICKER, ///< This one uses the paintbrush
CURSOR_SHAPE_XOR_TARGET,
CURSOR_SHAPE_XOR_RECTANGLE,
CURSOR_SHAPE_XOR_ROTATION
};
/// The different shapes that can be used as a paintbrush (paintbrush types go in the beginning)
enum PAINTBRUSH_SHAPES
{
PAINTBRUSH_SHAPE_ROUND,
PAINTBRUSH_SHAPE_SQUARE,
PAINTBRUSH_SHAPE_HORIZONTAL_BAR,
PAINTBRUSH_SHAPE_VERTICAL_BAR,
PAINTBRUSH_SHAPE_SLASH,
PAINTBRUSH_SHAPE_ANTISLASH,
PAINTBRUSH_SHAPE_RANDOM, ///< Random pixels in a circle shape, like an airbrush.
PAINTBRUSH_SHAPE_CROSS,
PAINTBRUSH_SHAPE_PLUS,
PAINTBRUSH_SHAPE_DIAMOND,
PAINTBRUSH_SHAPE_SIEVE_ROUND,
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_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_COLOR_BRUSH, ///< User's brush, in color mode
PAINTBRUSH_SHAPE_MONO_BRUSH, ///< User's brush, in mono mode
PAINTBRUSH_SHAPE_MAX ///< Upper limit.
};
/// Normal resting state for a menu button.
#define BUTTON_RELEASED 0
/// State of a menu button that is being pressed.
#define BUTTON_PRESSED 1
/// State of a button temporarily highligted
#define BUTTON_HIGHLIGHTED 2
/// The different modes of the Shade
enum SHADE_MODES
{
SHADE_MODE_NORMAL,
SHADE_MODE_LOOP,
SHADE_MODE_NOSAT
};
/// Identifiers for the chunks (data blocks) of gfx2.cfg
enum CHUNKS_CFG
{
CHUNK_KEYS = 0, ///< Shortcut keys definitions
CHUNK_VIDEO_MODES = 1, ///< List of video modes
CHUNK_SHADE = 2, ///< Shade settings
CHUNK_MASK = 3, ///< Mask settings
CHUNK_STENCIL = 4, ///< Stencil settings
CHUNK_GRADIENTS = 5, ///< Gradients
CHUNK_SMOOTH = 6, ///< Smooth effect settings
CHUNK_EXCLUDE_COLORS = 7, ///< List of excluded colors
CHUNK_QUICK_SHADE = 8, ///< QShade effect settings
CHUNK_GRID = 9, ///< Grid settings
CHUNK_BRUSH =10, ///< Paintbrushes
CHUNK_SCRIPTS =11, ///< Callable scripts
CHUNK_MAX
};
/// Identifiers for the 8x8 icons of ::Gfx->Icon_sprite (most are unused now)
enum ICON_TYPES
{
ICON_FLOPPY_3_5=0, ///< 3.5 Floppy disk
ICON_FLOPPY_5_25, ///< 5.25 Floppy disk
ICON_HDD, ///< Hard disk drive
ICON_CDROM, ///< CD-ROM
ICON_NETWORK, ///< "Network" drive
ICON_STAR, ///< Star (favorite)
ICON_DROPDOWN, ///< Dropdown arrow
NB_ICON_SPRITES, ///< Number of 8x8 icons
ICON_NONE ///< None of the above
};
/// Identifiers for the buttons in the menu.
enum BUTTON_NUMBERS
{
// Status bar
BUTTON_HIDE = 0,
// Layer bar
BUTTON_LAYER_MENU,
BUTTON_LAYER_COLOR,
BUTTON_LAYER_MERGE,
BUTTON_LAYER_ADD,
BUTTON_LAYER_REMOVE,
BUTTON_LAYER_UP,
BUTTON_LAYER_DOWN,
BUTTON_LAYER_SELECT,
// Main menu
BUTTON_PAINTBRUSHES,
BUTTON_ADJUST,
BUTTON_DRAW,
BUTTON_CURVES,
BUTTON_LINES,
BUTTON_AIRBRUSH,
BUTTON_FLOODFILL,
BUTTON_POLYGONS,
BUTTON_POLYFILL,
BUTTON_RECTANGLES,
BUTTON_FILLRECT,
BUTTON_CIRCLES,
BUTTON_FILLCIRC,
BUTTON_GRADRECT,
BUTTON_SPHERES,
BUTTON_BRUSH,
BUTTON_POLYBRUSH,
BUTTON_BRUSH_EFFECTS,
BUTTON_EFFECTS,
BUTTON_TEXT,
BUTTON_MAGNIFIER,
BUTTON_COLORPICKER,
BUTTON_RESOL,
BUTTON_PAGE,
BUTTON_SAVE,
BUTTON_LOAD,
BUTTON_SETTINGS,
BUTTON_CLEAR,
BUTTON_HELP,
BUTTON_UNDO,
BUTTON_KILL,
BUTTON_QUIT,
BUTTON_PALETTE,
BUTTON_PAL_LEFT,
BUTTON_PAL_RIGHT,
BUTTON_CHOOSE_COL,
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.
/// They are special in the sense that there's no button in the menu for them,
/// so it requires a specific handling.
enum SPECIAL_ACTIONS
{
SPECIAL_MOUSE_UP=0,
SPECIAL_MOUSE_DOWN,
SPECIAL_MOUSE_LEFT,
SPECIAL_MOUSE_RIGHT,
SPECIAL_CLICK_LEFT,
SPECIAL_CLICK_RIGHT,
SPECIAL_NEXT_FORECOLOR,
SPECIAL_PREVIOUS_FORECOLOR,
SPECIAL_NEXT_BACKCOLOR,
SPECIAL_PREVIOUS_BACKCOLOR,
SPECIAL_SMALLER_PAINTBRUSH,
SPECIAL_BIGGER_PAINTBRUSH,
SPECIAL_NEXT_USER_FORECOLOR,
SPECIAL_PREVIOUS_USER_FORECOLOR,
SPECIAL_NEXT_USER_BACKCOLOR,
SPECIAL_PREVIOUS_USER_BACKCOLOR,
SPECIAL_SCROLL_UP,
SPECIAL_SCROLL_DOWN,
SPECIAL_SCROLL_LEFT,
SPECIAL_SCROLL_RIGHT,
SPECIAL_SCROLL_UP_FAST,
SPECIAL_SCROLL_DOWN_FAST,
SPECIAL_SCROLL_LEFT_FAST,
SPECIAL_SCROLL_RIGHT_FAST,
SPECIAL_SCROLL_UP_SLOW,
SPECIAL_SCROLL_DOWN_SLOW,
SPECIAL_SCROLL_LEFT_SLOW,
SPECIAL_SCROLL_RIGHT_SLOW,
SPECIAL_SHOW_HIDE_CURSOR,
SPECIAL_DOT_PAINTBRUSH,
SPECIAL_CONTINUOUS_DRAW,
SPECIAL_FLIP_X,
SPECIAL_FLIP_Y,
SPECIAL_ROTATE_90,
SPECIAL_ROTATE_180,
SPECIAL_STRETCH,
SPECIAL_DISTORT,
SPECIAL_OUTLINE,
SPECIAL_NIBBLE,
SPECIAL_GET_BRUSH_COLORS,
SPECIAL_RECOLORIZE_BRUSH,
SPECIAL_ROTATE_ANY_ANGLE,
SPECIAL_BRUSH_DOUBLE,
SPECIAL_BRUSH_DOUBLE_WIDTH,
SPECIAL_BRUSH_DOUBLE_HEIGHT,
SPECIAL_BRUSH_HALVE,
SPECIAL_LOAD_BRUSH,
SPECIAL_SAVE_BRUSH,
SPECIAL_INVERT_SIEVE,
SPECIAL_ZOOM_IN,
SPECIAL_ZOOM_OUT,
SPECIAL_CENTER_ATTACHMENT,
SPECIAL_TOP_LEFT_ATTACHMENT,
SPECIAL_TOP_RIGHT_ATTACHMENT,
SPECIAL_BOTTOM_LEFT_ATTACHMENT,
SPECIAL_BOTTOM_RIGHT_ATTACHMENT,
SPECIAL_EXCLUDE_COLORS_MENU,
SPECIAL_SHADE_MODE,
SPECIAL_SHADE_MENU,
SPECIAL_QUICK_SHADE_MODE, ///< This must be the first of the "effects" family
SPECIAL_QUICK_SHADE_MENU,
SPECIAL_STENCIL_MODE,
SPECIAL_STENCIL_MENU,
SPECIAL_MASK_MODE,
SPECIAL_MASK_MENU,
SPECIAL_GRID_MODE,
SPECIAL_GRID_MENU,
SPECIAL_SIEVE_MODE,
SPECIAL_SIEVE_MENU,
SPECIAL_COLORIZE_MODE,
SPECIAL_COLORIZE_MENU,
SPECIAL_SMOOTH_MODE,
SPECIAL_SMOOTH_MENU,
SPECIAL_SMEAR_MODE,
SPECIAL_EFFECTS_OFF,
SPECIAL_TILING_MODE,
SPECIAL_TRANSPARENCY_1,
SPECIAL_TRANSPARENCY_2,
SPECIAL_TRANSPARENCY_3,
SPECIAL_TRANSPARENCY_4,
SPECIAL_TRANSPARENCY_5,
SPECIAL_TRANSPARENCY_6,
SPECIAL_TRANSPARENCY_7,
SPECIAL_TRANSPARENCY_8,
SPECIAL_TRANSPARENCY_9,
SPECIAL_TRANSPARENCY_0,
SPECIAL_TILING_MENU, ///< This must be the last of the "effects" family
SPECIAL_ZOOM_1,
SPECIAL_ZOOM_2,
SPECIAL_ZOOM_3,
SPECIAL_ZOOM_4,
SPECIAL_ZOOM_5,
SPECIAL_ZOOM_6,
SPECIAL_ZOOM_8,
SPECIAL_ZOOM_10,
SPECIAL_ZOOM_12,
SPECIAL_ZOOM_14,
SPECIAL_ZOOM_16,
SPECIAL_ZOOM_18,
SPECIAL_ZOOM_20,
SPECIAL_SHOW_GRID,
SPECIAL_LAYER1_SELECT,
SPECIAL_LAYER1_TOGGLE,
SPECIAL_LAYER2_SELECT,
SPECIAL_LAYER2_TOGGLE,
SPECIAL_LAYER3_SELECT,
SPECIAL_LAYER3_TOGGLE,
SPECIAL_LAYER4_SELECT,
SPECIAL_LAYER4_TOGGLE,
SPECIAL_LAYER5_SELECT,
SPECIAL_LAYER5_TOGGLE,
SPECIAL_LAYER6_SELECT,
SPECIAL_LAYER6_TOGGLE,
SPECIAL_LAYER7_SELECT,
SPECIAL_LAYER7_TOGGLE,
SPECIAL_LAYER8_SELECT,
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,
NB_SPECIAL_SHORTCUTS ///< Number of special shortcuts
};
/// Identifiers of the operations, ie tools you use on the image.
enum OPERATIONS
{
OPERATION_CONTINUOUS_DRAW=0, ///< Freehand continuous draw
OPERATION_DISCONTINUOUS_DRAW,///< Freehand discontinuous draw
OPERATION_POINT_DRAW, ///< Freehand point-by-point draw
OPERATION_FILLED_CONTOUR, ///< Filled contour
OPERATION_LINE, ///< Lines
OPERATION_K_LINE, ///< Linked lines
OPERATION_CENTERED_LINES, ///< Centered lines
OPERATION_EMPTY_RECTANGLE, ///< Empty rectangle
OPERATION_FILLED_RECTANGLE, ///< Filled rectangle
OPERATION_EMPTY_CIRCLE, ///< Empty circle
OPERATION_FILLED_CIRCLE, ///< Filled circle
OPERATION_EMPTY_ELLIPSE, ///< Empty ellipse
OPERATION_FILLED_ELLIPSE, ///< Filled ellipse
OPERATION_FILL, ///< Fill
OPERATION_REPLACE, ///< Color replacer
OPERATION_GRAB_BRUSH, ///< Rectangular brush grabbing
OPERATION_POLYBRUSH, ///< Polygonal brush grabbing
OPERATION_COLORPICK, ///< Colorpicker
OPERATION_MAGNIFY, ///< Position the magnify window
OPERATION_3_POINTS_CURVE, ///< Curve with 3 control points
OPERATION_4_POINTS_CURVE, ///< Curve with 4 control points
OPERATION_AIRBRUSH, ///< Airbrush
OPERATION_POLYGON, ///< Polygon
OPERATION_POLYFORM, ///< Polyform
OPERATION_POLYFILL, ///< Filled polygon
OPERATION_FILLED_POLYFORM, ///< Filled polyform
OPERATION_SCROLL, ///< Scroll (pan)
OPERATION_GRAD_CIRCLE, ///< Gradient-filled circle
OPERATION_GRAD_ELLIPSE, ///< Gradient-filled ellipse
OPERATION_ROTATE_BRUSH, ///< Rotate brush
OPERATION_STRETCH_BRUSH, ///< Stretch brush
OPERATION_DISTORT_BRUSH, ///< Distort brush
OPERATION_GRAD_RECTANGLE, ///< Gradient-filled rectangle
OPERATION_RMB_COLORPICK, ///< Colorpick on right mouse button
NB_OPERATIONS ///< Number of operations handled by the engine
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,123 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 engine.h
/// Utility functions for the menu and all windows.
//////////////////////////////////////////////////////////////////////////////
#ifndef __ENGINE_H__
#define __ENGINE_H__
#include "struct.h"
void Main_handler (void);
void Draw_menu_button (byte btn_number,byte pressed);
void Unselect_button (int btn_number);
void Select_button (int btn_number,byte click);
void Open_window (word width,word height, const char * title);
void Close_window (void);
void Open_popup (word x_pos, word y_pos, word width, word height);
void Close_popup (void);
void Window_draw_normal_bouton(word x_pos,word y_pos,word width,word height,
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_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 Compute_slider_cursor_length(T_Scroller_button * button);
void Window_draw_slider(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_clear_input_button(T_Special_button * button);
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,
word width, word height, const char * title, byte undersc_letter,
byte clickable, word shortcut);
T_Normal_button * Window_set_repeatable_button(word x_pos, word y_pos,
word width, word height, const char * title, byte undersc_letter,
byte clickable, word shortcut);
T_Palette_button * Window_set_palette_button(word x_pos, word y_pos);
void Window_clear_tags(void);
void Tag_color_range(byte start, byte end);
T_Scroller_button * Window_set_scroller_button(word x_pos, word y_pos,
word height, word nb_elements, word nb_elements_visible,
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,
word height);
T_Special_button * Window_set_input_button(word x_pos, word y_pos,
word width_in_characters);
T_Dropdown_button * Window_set_dropdown_button(word x_pos, word y_pos,
word width, word height, word dropdown_width, const char *label,
byte display_choice, byte display_centered, byte display_arrow,
byte active_button,byte bottom_up);
/// Adds an item to a dropdown menu
void Window_dropdown_add_item(T_Dropdown_button * dropdown, word btn_number,
const char *label);
void Window_dropdown_clear_items(T_Dropdown_button * dropdown);
///
/// Displays a dropped-down menu and handles the UI logic until the user
/// releases a mouse button.
/// This function then clears the dropdown and returns the selected item,
/// or NULL if the user wasn't highlighting an item when he closed.
T_Dropdown_choice * Dropdown_activate(T_Dropdown_button *button, short off_x, short off_y);
T_List_button * Window_set_list_button(T_Special_button * entry_button,
T_Scroller_button * scroller, Func_draw_list_item draw_list_item, byte color_index);
void Window_redraw_list(T_List_button * list);
byte Window_click_in_rectangle(short start_x, short start_y, short end_x,
short end_y);
short Wait_click_in_palette(T_Palette_button * button);
short Window_normal_button_onclick(word x_pos, word y_pos, word width, word height, short btn_number);
void Get_color_behind_window(byte * color, byte * click);
short Window_clicked_button(void);
int Button_under_mouse(void);
short Window_get_clicked_button(void);
void Remap_window_backgrounds(byte * conversion_table, int Min_Y, int Max_Y);
void Pixel_background(int x_pos, int y_pos, byte color);
///
/// Updates the status bar line with a color number.
/// Used when hovering the menu palette.
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

View File

@@ -0,0 +1,54 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 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 errors.h
/// Functions and macros for tracing and error reporting.
//////////////////////////////////////////////////////////////////////////////
#ifdef __VBCC__
#define __func__ "stupid compiler !"
#endif
/// Prints the source filename, line number, function name, a string and an integer.
#define DEBUG(y,z) printf("%s %d %s | %s : %d###\n",__FILE__,__LINE__,__func__,y,(unsigned int)z)
/// Same as ::DEBUG but in hexadecimal
#define DEBUGX(y,z) printf("%s %d %s | %s : %X###\n",__FILE__,__LINE__,__func__,y,(unsigned int)z)
/// Helper function used by the macro ::Error
void Error_function(int error_code, const char *filename, int line_number, const char *function_name);
///
/// Report a run-time error: It will print to standard output some information
/// about the calling function, and then:
/// - If the error code is 0, just do a red screen flash and resume.
/// - If the error code is non-zero, abort the program.
#define Error(n) Error_function(n, __FILE__,__LINE__,__func__)
/// Helper function used by the macro ::Warning
void Warning_function(const char *message, const char *filename, int line_number, const char *function_name);
///
/// Report a run-time abnormal condition : It will print to standard output
/// some information about the calling function, and then resume silently.
/// This is most useful in debugger so you can put a breakpoint on
/// ::Warning_function and examine the stack trace.
#define Warning(msg) Warning_function(msg, __FILE__,__LINE__,__func__)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
/* vim:expandtab:ts=2 sw=2:
*/
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);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,59 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 filesel.h
/// Fileselector window, used for loading and saving images and brushes.
//////////////////////////////////////////////////////////////////////////////
#ifndef __FILESEL_H__
#define __FILESEL_H__
#include "struct.h"
#include "loadsave.h"
byte Button_Load_or_Save(byte load, T_IO_Context *context);
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).
/// The returned value is a pointer to a single static buffer of maximum 40 characters
/// including the '\\0'.
char * Format_filename(const char * fname, word max_length, int type);
void Free_fileselector_list(T_Fileselector *list);
void Sort_list_of_files(T_Fileselector *list);
void Recount_files(T_Fileselector *list);
T_Fileselector_item * Get_item_by_index(T_Fileselector *list, short index);
void Read_list_of_drives(T_Fileselector *list, byte name_length);
short Find_file_in_fileselector(T_Fileselector *list, const char * fname);
void Locate_list_item(T_List_button * list, short selected_item);
int Quicksearch_list(T_List_button * list, T_Fileselector * selector);
void Reset_quicksearch(void);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,123 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007-2008 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 graph.h
/// Graphic functions that target the screen and/or image.
//////////////////////////////////////////////////////////////////////////////
void Shade_list_to_lookup_tables(word * list, short step, byte mode, byte * table_inc,
byte * table_dec
);
void Transform_point(short x, short y,
float cos_a, float sin_a, short * rx, short * ry);
int Init_mode_video(int width, int height, int fullscreen,int pixel_ratio);
byte No_effect(word x,word y,byte color);
byte Effect_shade(word x,word y,byte color);
byte Effect_quick_shade(word x,word y,byte color);
byte Effect_tiling(word x,word y,byte color);
byte Effect_smooth(word x,word y,byte color);
void Display_foreback(void);
void Display_pixel(word x,word y,byte color);
void Display_paintbrush(short x,short y,byte color,byte is_preview);
void Hide_paintbrush(short x,short y);
void Resize_image(word chosen_width,word chosen_height);
void Fill_general(byte fill_color);
void Replace(byte New_color);
void Pixel_figure_preview (word x_pos,word y_pos,byte color);
void Pixel_figure_preview_auto(word x_pos,word y_pos);
void Pixel_figure_preview_xor(word x_pos,word y_pos,byte color);
void Pixel_figure_preview_xorback(word x_pos,word y_pos,byte color);
void Pixel_figure_in_brush(word x_pos,word y_pos,byte color);
void Draw_empty_circle_general(short center_x,short center_y,short radius,byte color);
void Draw_empty_circle_permanent(short center_x,short center_y,short radius,byte color);
void Draw_empty_circle_preview (short center_x,short center_y,short radius,byte color);
void Hide_empty_circle_preview (short center_x,short center_y,short radius);
void Draw_empty_circle_general(short center_x,short center_y,short radius,byte color);
void Draw_filled_circle (short center_x,short center_y,short radius,byte color);
void Draw_empty_ellipse_permanent(short center_x,short center_y,short horizontal_radius,short vertical_radius,byte color);
void Draw_empty_ellipse_preview (short center_x,short center_y,short horizontal_radius,short vertical_radius,byte color);
void Hide_empty_ellipse_preview (short center_x,short center_y,short horizontal_radius,short vertical_radius);
void Draw_filled_ellipse (short center_x,short center_y,short horizontal_radius,short vertical_radius,byte color);
void Clamp_coordinates_regular_angle(short ax, short ay, short* bx, short* by);
void Draw_line_general(short start_x,short start_y,short end_x,short end_y, byte color);
void Draw_line_permanent (short start_x,short start_y,short end_x,short end_y,byte color);
void Draw_line_preview (short start_x,short start_y,short end_x,short end_y,byte color);
void Draw_line_preview_xor(short start_x,short start_y,short end_x,short end_y,byte color);
void Draw_line_preview_xorback(short start_x,short start_y,short end_x,short end_y,byte color);
void Hide_line_preview (short start_x,short start_y,short end_x,short end_y);
void Draw_empty_rectangle(short start_x,short start_y,short end_x,short end_y,byte color);
void Draw_filled_rectangle(short start_x,short start_y,short end_x,short end_y,byte color);
void Draw_curve_permanent(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, byte color);
void Draw_curve_preview (short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, byte color);
void Hide_curve_preview (short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, byte color);
void Airbrush(short clicked_button);
void Gradient_basic (long index,short x_pos,short y_pos);
void Gradient_dithered (long index,short x_pos,short y_pos);
void Gradient_extra_dithered(long index,short x_pos,short y_pos);
void Degrade_aleatoire (long index,short x_pos,short y_pos);
void Draw_grad_circle (short center_x,short center_y,short radius,short spot_x,short spot_y);
void Draw_grad_ellipse(short center_x,short center_y,short horizontal_radius,short vertical_radius,short spot_x,short spot_y);
void Draw_grad_rectangle(short rax,short ray,short rbx,short rby,short vax,short vay, short vbx, short vby);
void Polyfill_general(int vertices, short * points, int color);
void Polyfill(int vertices, short * points, int color);
/// Remap the spare page according to the main page's palette
void Remap_spare(void);
///
/// All the figure-drawing functions work by calling this function for each
/// pixel to draw. Before calling these functions, you should assign
/// ::Pixel_figure depending on what you where you want to draw:
/// - ::Pixel_figure_preview : On screen.
/// - ::Pixel_figure_preview_xor : On screen, XORing the color.
/// - ::Pixel_figure_permanent : On screen and in the image.
/// - ::Pixel_figure_clear_preview : On screen, reverting to the image's pixels.
extern Func_pixel Pixel_figure;
void Update_part_of_screen(short x, short y, short width, short height);
void Redraw_grid(short x, short y, unsigned short w, unsigned short h);
void Pixel_in_current_screen (word x,word y,byte color,int with_preview);
void Pixel_in_current_layer(word x,word y, byte color);
byte Read_pixel_from_current_screen (word x,word y);
byte Read_pixel_from_current_layer(word x,word y);

View File

@@ -0,0 +1,8 @@
#include "struct.h"
#ifndef __HAIKU_H
#define __HAIKU_H
qword haiku_get_free_space(char* path);
#endif

View File

@@ -0,0 +1,863 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Peter Gordon
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#include <stdio.h>
#include <string.h>
#if defined(__WIN32__)
#include <windows.h>
#elif defined(__macosx__) || defined(__FreeBSD__)
#include <sys/param.h>
#include <sys/mount.h>
#elif defined (__linux__)
#include <sys/vfs.h>
#elif defined(__HAIKU__)
#include "haiku.h"
#elif defined (__MINT__)
#include <mint/sysbind.h>
#include <mint/osbind.h>
#include <mint/ostruct.h>
#endif
#include "const.h"
#include "struct.h"
#include "global.h"
#include "misc.h"
#include "engine.h"
#include "helpfile.h"
#include "help.h"
#include "sdlscreen.h"
#include "text.h"
#include "keyboard.h"
#include "windows.h"
#include "input.h"
#include "hotkeys.h"
#include "errors.h"
#include "pages.h"
extern char Program_version[]; // generated in pversion.c
extern char SVN_revision[]; // generated in pversion.c
// Recherche un raccourci clavier:
word * Shortcut(word shortcut_number)
{
if (shortcut_number & 0x100)
return &(Buttons_Pool[shortcut_number & 0xFF].Left_shortcut[0]);
if (shortcut_number & 0x200)
return &(Buttons_Pool[shortcut_number & 0xFF].Right_shortcut[0]);
return &(Config_Key[shortcut_number & 0xFF][0]);
}
// 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)
{
static char shortcuts_name[80];
word * pointer = Shortcut(shortcut_number);
if (pointer == NULL)
return "(Problem)";
else
{
if (pointer[0] == 0 && pointer[1] == 0)
return "None";
if (pointer[0] != 0 && pointer[1] == 0)
return Key_name(pointer[0]);
if (pointer[0] == 0 && pointer[1] != 0)
return Key_name(pointer[1]);
strcpy(shortcuts_name, Key_name(pointer[0]));
strcat(shortcuts_name, " or ");
strcat(shortcuts_name, Key_name(pointer[1]));
return shortcuts_name;
}
}
void Redefine_control(word *shortcut, int x_pos, int y_pos)
{
Hide_cursor();
Print_in_window(x_pos,y_pos,"*PRESS KEY OR BUTTON*",MC_Black,MC_Light);
Display_cursor();
while (1)
{
Get_input(20);
if (Key==KEY_ESC)
return;
if (Key!=0)
{
*shortcut=Key;
return;
}
}
}
void Window_set_shortcut(int action_id)
{
short clicked_button;
short order_index;
short config_index;
short redraw_controls=1;
word * shortcut_ptr=NULL;
word backup_shortcut[2];
shortcut_ptr=Shortcut(action_id);
backup_shortcut[0]=shortcut_ptr[0];
backup_shortcut[1]=shortcut_ptr[1];
// Recherche dans hotkeys
order_index=0;
while (Ordering[order_index]!=action_id)
{
order_index++;
if (order_index>=NB_SHORTCUTS)
{
Error(0);
return;
}
}
/*
config_index=0;
while (ConfigKey[config_index].Number!=order_index)
{
config_index++;
if (config_index>=NB_SHORTCUTS)
{
Error(0);
return;
}
}
*/
config_index=order_index; // Comprends pas... ça devrait pas marcher
Open_window(302,131,"Keyboard shortcut");
Window_set_normal_button(181,111,55,14,"Cancel",0,1,KEY_ESC); // 1
Window_set_normal_button(241,111,55,14,"OK",0,1,SDLK_RETURN); // 2
Window_set_normal_button(6,111,111,14,"Reset default",0,1,KEY_NONE); // 3
// Titre
Block(Window_pos_X+(Menu_factor_X*5),
Window_pos_Y+(Menu_factor_Y*16),
Menu_factor_X*292,Menu_factor_Y*11,MC_Black);
Print_in_window(7,18,ConfigKey[config_index].Label,MC_White,MC_Black);
// Zone de description
Window_display_frame_in(5,68,292,37);
Print_in_window(8,70,ConfigKey[config_index].Explanation1,MC_Black,MC_Light);
Print_in_window(8,78,ConfigKey[config_index].Explanation2,MC_Black,MC_Light);
Print_in_window(8,86,ConfigKey[config_index].Explanation3,MC_Black,MC_Light);
// Shortcut 0
Window_set_normal_button(27,30,177,14,"",0,1,KEY_NONE); // 4
Window_set_normal_button(209,30,56,14,"Remove",0,1,KEY_NONE); // 5
// Shortcut 1
Window_set_normal_button(27,49,177,14,"",0,1,KEY_NONE); // 6
Window_set_normal_button(209,49,56,14,"Remove",0,1,KEY_NONE); // 7
Display_cursor();
do
{
if (redraw_controls)
{
Hide_cursor();
Block(Window_pos_X+(Menu_factor_X*32),
Window_pos_Y+(Menu_factor_Y*33),
Menu_factor_X*21*8,Menu_factor_Y*8,MC_Light);
Print_in_window_limited(32,33,Key_name(shortcut_ptr[0]),21,MC_Black,MC_Light);
Block(Window_pos_X+(Menu_factor_X*32),
Window_pos_Y+(Menu_factor_Y*52),
Menu_factor_X*21*8,Menu_factor_Y*8,MC_Light);
Print_in_window_limited(32,52,Key_name(shortcut_ptr[1]),21,MC_Black,MC_Light);
Update_rect(Window_pos_X,Window_pos_Y,302*Menu_factor_X,131*Menu_factor_Y);
Display_cursor();
redraw_controls=0;
}
clicked_button=Window_clicked_button();
switch (clicked_button)
{
case -1:
case 0:
break;
case 4: // Change 0
Redefine_control(&shortcut_ptr[0], 32, 33);
redraw_controls=1;
break;
case 6: // Change 1
Redefine_control(&shortcut_ptr[1], 32, 52);
redraw_controls=1;
break;
case 5: // Remove 0
shortcut_ptr[0]=0;
redraw_controls=1;
break;
case 7: // Remove 1
shortcut_ptr[1]=0;
redraw_controls=1;
break;
case 3: // Defaults
shortcut_ptr[0]=ConfigKey[config_index].Key;
shortcut_ptr[1]=ConfigKey[config_index].Key2;
redraw_controls=1;
break;
case 1: // Cancel
shortcut_ptr[0]=backup_shortcut[0];
shortcut_ptr[1]=backup_shortcut[1];
case 2: // OK
// Replace twice by single
if (shortcut_ptr[0]==shortcut_ptr[1])
shortcut_ptr[1]=0;
// Remove all other shortcuts that use same keys
if (!Config.Allow_multi_shortcuts)
{
int n;
for (n=0; n<2; n++)
{
if (shortcut_ptr[n]!=0)
{
int i;
for(i=0; i<NB_SHORTCUTS; i++)
{
word * other_shortcut_ptr;
if (Ordering[i]==action_id)
continue;
other_shortcut_ptr=Shortcut(Ordering[i]);
if (other_shortcut_ptr[0]==shortcut_ptr[n])
other_shortcut_ptr[0]=0;
if (other_shortcut_ptr[1]==shortcut_ptr[n])
other_shortcut_ptr[1]=0;
}
}
}
}
default:
break;
}
}
while ((clicked_button!=1) && (clicked_button!=2) && (Key!=SDLK_RETURN));
Key=0;
Close_window();
Display_cursor();
}
///
/// Browse the complete list of shortcuts and ensure that a key only triggers
/// one of them.
void Remove_duplicate_shortcuts(void)
{
int action_1;
// This algorithm favors shortcuts that are first in the list.
// The idea is that we, coders, append new shortcuts at the end with default
// values; they should be discarded if user has chosen the key first.
for (action_1=0; action_1<NB_SHORTCUTS-1; action_1++)
{
int n;
word *shortcut_1 = Shortcut(Ordering[action_1]);
for (n=0; n<2; n++)
{
int action_2;
for (action_2=action_1+1; action_2<NB_SHORTCUTS; action_2++)
{
if (shortcut_1[n]!=0)
{
int i;
for(i=0; i<NB_SHORTCUTS; i++)
{
word *shortcut_2 = Shortcut(Ordering[action_2]);
if (shortcut_2[0]==shortcut_1[n])
shortcut_2[0]=0;
if (shortcut_2[1]==shortcut_1[n])
shortcut_2[1]=0;
}
}
}
}
}
}
///
/// 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)
{
short width; // Largeur physique d'une ligne de texte
short x; // Indices d'affichage d'un caractère
short y;
short x_position; // Parcours de remplissage du buffer de ligne
short char_index; // Parcours des caractères d'une ligne
byte * char_pixel;
short repeat_menu_x_factor;
short repeat_menu_y_factor;
short real_x_pos;
short real_y_pos;
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
// -: Ligne inférieur de sous-titre
const char * line;
char buffer[45]; // buffer texte utilisé pour formater les noms de
// raccourcis clavier
short link_position=0; // Position du premier caractère "variable"
short link_size=0; // Taille de la partie variable
short width;
for (line_index=0;line_index<16;line_index++)
{
// Shortcut au cas ou la section fait moins de 16 lignes
if (line_index >= Help_section[Current_help_section].Length)
{
Window_rectangle (x_pos,
y_pos + line_index*8,
44*6,
// 44 = Nb max de char (+1 pour éviter les plantages en mode X
// causés par une largeur = 0)
(16 - line_index)*8,
MC_Black);
break;
}
// On affiche la ligne
line = Help_section[Current_help_section].Help_table[start_line + line_index].Text;
line_type = Help_section[Current_help_section].Help_table[start_line + line_index].Line_type;
// Si c'est une sous-ligne de titre, on utilise le texte de la ligne précédente
if (line_type == '-' && (start_line + line_index > 0))
line = Help_section[Current_help_section].Help_table[start_line + line_index - 1].Text;
else if (line_type == 'K')
{
const char *hyperlink;
const char * escaped_percent_pos;
// Determine link position:
link_position = strstr(line,"%s") - line;
// Adjust for any escaped %% that would precede it.
escaped_percent_pos = line;
do
{
escaped_percent_pos = strstr(escaped_percent_pos,"%%");
if (escaped_percent_pos && escaped_percent_pos - line < link_position)
{
link_position--;
escaped_percent_pos+=2;
}
} while (escaped_percent_pos);
//
hyperlink=Keyboard_shortcut_value(Help_section[Current_help_section].Help_table[start_line + line_index].Line_parameter);
link_size=strlen(hyperlink);
snprintf(buffer, 44, line, hyperlink);
if (strlen(line)+link_size-2>44)
{
buffer[43]=ELLIPSIS_CHARACTER;
buffer[44]='\0';
}
line = buffer;
}
width=Print_help(x_pos, y_pos+(line_index<<3), line, line_type, link_position, link_size);
// On efface la fin de la ligne:
if (width<44)
Window_rectangle (x_pos+width*6,
y_pos+(line_index<<3),
(44-width)*6,
8,
MC_Black);
}
Update_window_area(x_pos,y_pos,44*6,16*8);
}
void Scroll_help(T_Scroller_button * scroller)
{
Hide_cursor();
scroller->Position=Help_position;
Compute_slider_cursor_length(scroller);
Window_draw_slider(scroller);
Display_help();
Display_cursor();
}
void Button_Help(void)
{
short btn_number;
// Aide contextuelle
if (Key!=0)
{
btn_number = Button_under_mouse();
if (btn_number != -1)
{
Window_help(btn_number, NULL);
return;
}
}
Window_help(-1, NULL);
}
// Ouvre l'ecran d'aide. Passer -1 pour la section par défaut (ou derniere,)
// Ou un nombre de l'enumération BUTTON_NUMBERS pour l'aide contextuelle.
void Window_help(int section, const char *sub_section)
{
short clicked_button;
short nb_lines;
T_Scroller_button * scroller;
if (section!=-1)
{
Current_help_section = 4 + section;
Help_position = 0;
}
nb_lines=Help_section[Current_help_section].Length;
if (section!=-1 && sub_section!=NULL)
{
int index=0;
for (index=0; index<nb_lines; index++)
if (Help_section[Current_help_section].Help_table[index].Line_type == 'T' &&
!strcmp(Help_section[Current_help_section].Help_table[index].Text, sub_section))
{
Help_position = index;
break;
}
}
Open_window(310,175,"Help / About...");
// dessiner de la fenêtre où va défiler le texte
Window_display_frame_in(8,17,274,132);
Block(Window_pos_X+(Menu_factor_X*9),
Window_pos_Y+(Menu_factor_Y*18),
Menu_factor_X*272,Menu_factor_Y*130,MC_Black);
Window_set_normal_button(266,153,35,14,"Exit",0,1,KEY_ESC); // 1
scroller=Window_set_scroller_button(290,18,130,nb_lines,
16,Help_position); // 2
Window_set_normal_button( 9,154, 6*8,14,"About" ,1,1,SDLK_a); // 3
Window_set_normal_button( 9+6*8+4,154, 8*8,14,"License",1,1,SDLK_l); // 4
Window_set_normal_button( 9+6*8+4+8*8+4,154, 5*8,14,"Help",1,1,SDLK_h); // 5
Window_set_normal_button(9+6*8+4+8*8+4+5*8+4,154, 8*8,14,"Credits",1,1,SDLK_c); // 6
Window_set_special_button(9,18,272,130); // 7
Display_help();
Update_rect(Window_pos_X,Window_pos_Y,310*Menu_factor_X,175*Menu_factor_Y);
Display_cursor();
do
{
clicked_button=Window_clicked_button();
switch (clicked_button)
{
case -1:
case 0:
case 1:
break;
case 7: // Zone de texte
{
int line = ((Mouse_Y-Window_pos_Y)/Menu_factor_Y - 18)/8;
Wait_end_of_click();
if (line == ((Mouse_Y-Window_pos_Y)/Menu_factor_Y - 18)/8)
{
if (Help_position+line<nb_lines)
{
switch (Help_section[Current_help_section].Help_table[Help_position+line].Line_type)
{
case 'K':
Window_set_shortcut(Help_section[Current_help_section].Help_table[Help_position+line].Line_parameter);
break;
// Ici on peut gérer un cas 'lien hypertexte'
default:
break;
}
Hide_cursor();
Display_help();
Display_cursor();
}
}
break;
}
default:
Hide_cursor();
if (clicked_button>2)
{
Current_help_section=clicked_button-3;
Help_position=0;
nb_lines=Help_section[Current_help_section].Length;
scroller->Position=0;
scroller->Nb_elements=nb_lines;
Compute_slider_cursor_length(scroller);
Window_draw_slider(scroller);
}
else
Help_position=Window_attribute2;
Display_help();
Display_cursor();
}
// Gestion des touches de déplacement dans la liste
switch (Key)
{
case SDLK_UP : // Haut
if (Help_position>0)
Help_position--;
Scroll_help(scroller);
Key=0;
break;
case SDLK_DOWN : // Bas
if (Help_position<nb_lines-16)
Help_position++;
Scroll_help(scroller);
Key=0;
break;
case SDLK_PAGEUP : // PageUp
if (Help_position>15)
Help_position-=15;
else
Help_position=0;
Scroll_help(scroller);
Key=0;
break;
case (KEY_MOUSEWHEELUP) : // WheelUp
if (Help_position>3)
Help_position-=3;
else
Help_position=0;
Scroll_help(scroller);
Key=0;
break;
case SDLK_PAGEDOWN : // PageDown
if (nb_lines>16)
{
if (Help_position<nb_lines-16-15)
Help_position+=15;
else
Help_position=nb_lines-16;
Scroll_help(scroller);
Key=0;
}
break;
case (KEY_MOUSEWHEELDOWN) : // Wheeldown
if (nb_lines>16)
{
if (Help_position<nb_lines-16-3)
Help_position+=3;
else
Help_position=nb_lines-16;
Scroll_help(scroller);
Key=0;
}
break;
case SDLK_HOME : // Home
Help_position=0;
Scroll_help(scroller);
Key=0;
break;
case SDLK_END : // End
if (nb_lines>16)
{
Help_position=nb_lines-16;
Scroll_help(scroller);
Key=0;
}
break;
}
if (Is_shortcut(Key,0x100+BUTTON_HELP))
clicked_button=1;
}
while ((clicked_button!=1) && (Key!=SDLK_RETURN));
Key=0;
Close_window();
Unselect_button(BUTTON_HELP);
Display_cursor();
}
#define STATS_TITLE_COLOR MC_White
#define STATS_DATA_COLOR MC_Light
void Button_Stats(void)
{
short clicked_button;
char buffer[37];
dword color_usage[256];
unsigned long long freeRam;
qword mem_size = 0;
Open_window(310,174,"Statistics");
// Dessin de la fenetre ou va s'afficher le texte
Window_display_frame_in(8,17,294,132);
Block(Window_pos_X+(Menu_factor_X*9),
Window_pos_Y+(Menu_factor_Y*18),
Menu_factor_X*292,Menu_factor_Y*130,MC_Black);
Window_set_normal_button(120,153,70,14,"OK",0,1,KEY_ESC); // 1
// Affichage du numéro de version
Print_in_window(10,19,"Program version:",STATS_TITLE_COLOR,MC_Black);
sprintf(buffer,"%s.%s",Program_version, SVN_revision);
Print_in_window(146,19,buffer,STATS_DATA_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);
#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
Print_in_window(10,51,"Free memory: ",STATS_TITLE_COLOR,MC_Black);
freeRam = Memory_free();
if(freeRam > (100ULL*1024*1024*1024))
sprintf(buffer,"%u Gigabytes",(unsigned int)(freeRam/(1024*1024*1024)));
else if(freeRam > (100*1024*1024))
sprintf(buffer,"%u Megabytes",(unsigned int)(freeRam/(1024*1024)));
else if(freeRam > 100*1024)
sprintf(buffer,"%u Kilobytes",(unsigned int)(freeRam/1024));
else
sprintf(buffer,"%u bytes",(unsigned int)freeRam);
Print_in_window(114,51,buffer,STATS_DATA_COLOR,MC_Black);
#endif
// Used memory
Print_in_window(10,59,"Used memory pages: ",STATS_TITLE_COLOR,MC_Black);
if(Stats_pages_memory > (100LL*1024*1024*1024))
sprintf(buffer,"%ld (%lld Gb)",Stats_pages_number, Stats_pages_memory/(1024*1024*1024));
else if(Stats_pages_memory > (100*1024*1024))
sprintf(buffer,"%ld (%lld Mb)",Stats_pages_number, Stats_pages_memory/(1024*1024));
else
sprintf(buffer,"%ld (%lld Kb)",Stats_pages_number, Stats_pages_memory/1024);
Print_in_window(162,59,buffer,STATS_DATA_COLOR,MC_Black);
// Affichage de l'espace disque libre
sprintf(buffer,"Free space on %c:",Main_current_directory[0]);
Print_in_window(10,67,buffer,STATS_TITLE_COLOR,MC_Black);
#if defined(__WIN32__)
{
ULARGE_INTEGER tailleU;
GetDiskFreeSpaceEx(Main_current_directory,&tailleU,NULL,NULL);
mem_size = tailleU.QuadPart;
}
#elif defined(__linux__) || defined(__macosx__) || defined(__FreeBSD__)
// Note: under MacOSX, both macros are defined anyway.
{
struct statfs disk_info;
statfs(Main_current_directory,&disk_info);
mem_size=(qword) disk_info.f_bfree * (qword) disk_info.f_bsize;
}
#elif defined(__HAIKU__)
mem_size = haiku_get_free_space(Main_current_directory);
#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
// Free disk space is only for shows. Other platforms can display 0.
#warning "Missing code for your platform !!! Check and correct please :)"
mem_size=0;
#endif
if(mem_size > (100ULL*1024*1024*1024))
sprintf(buffer,"%u Gigabytes",(unsigned int)(mem_size/(1024*1024*1024)));
else if(mem_size > (100*1024*1024))
sprintf(buffer,"%u Megabytes",(unsigned int)(mem_size/(1024*1024)));
else if(mem_size > (100*1024))
sprintf(buffer,"%u Kilobytes",(unsigned int)(mem_size/1024));
else
sprintf(buffer,"%u bytes",(unsigned int)mem_size);
Print_in_window(146,67,buffer,STATS_DATA_COLOR,MC_Black);
// Affichage des informations sur l'image
Print_in_window(10,83,"Picture info.:",STATS_TITLE_COLOR,MC_Black);
// Affichage des dimensions de l'image
Print_in_window(18,91,"Dimensions :",STATS_TITLE_COLOR,MC_Black);
sprintf(buffer,"%dx%d",Main_image_width,Main_image_height);
Print_in_window(122,91,buffer,STATS_DATA_COLOR,MC_Black);
// Affichage du nombre de couleur utilisé
Print_in_window(18,99,"Colors used:",STATS_TITLE_COLOR,MC_Black);
memset(color_usage,0,sizeof(color_usage));
sprintf(buffer,"%d",Count_used_colors(color_usage));
Print_in_window(122,99,buffer,STATS_DATA_COLOR,MC_Black);
// Affichage des dimensions de l'écran
Print_in_window(10,115,"Resolution:",STATS_TITLE_COLOR,MC_Black);
sprintf(buffer,"%dx%d",Screen_width,Screen_height);
Print_in_window(106,115,buffer,STATS_DATA_COLOR,MC_Black);
Update_rect(Window_pos_X,Window_pos_Y,Menu_factor_X*310,Menu_factor_Y*174);
Display_cursor();
do
{
clicked_button=Window_clicked_button();
if (Is_shortcut(Key,0x200+BUTTON_HELP))
clicked_button=1;
}
while ( (clicked_button!=1) && (Key!=SDLK_RETURN) );
if(Key==SDLK_RETURN)Key=0;
Close_window();
Unselect_button(BUTTON_HELP);
Display_cursor();
}

View File

@@ -0,0 +1,66 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 help.h
/// Functions related to the help browser. The help data is in helpfile.h
//////////////////////////////////////////////////////////////////////////////
#ifndef __HELP_H_
#define __HELP_H_
/*!
Called to open the help window with the keyboard shortcut.
If the mouse is over a button, its contextual help will be displayed.
Else, the default helpscreen will be shown.
*/
void Button_Help(void);
/*!
Displays and runs the "Statistics" window
*/
void Button_Stats(void);
/*!
Displays and runs the "Help / About..." window
@param section Number of the help section page to display (equals the button number the mouse was hovering for the contextual help), -1 for the main help page.
@param sub_section Help sub-section title (the page will be scrolled so this title is at the top).
*/
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);
///
/// Browse the complete list of shortcuts and ensure that a key only triggers
/// one of them.
void Remove_duplicate_shortcuts(void);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,60 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2008 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 hotkeys.h
/// Definition of the tables used by the keyboard shortcuts.
/// The actual data is in hotkeys.c
//////////////////////////////////////////////////////////////////////////////
#if !defined(__VBCC__)
#include <stdbool.h>
#else
#define bool char
#endif
#include <SDL.h>
#define NB_SHORTCUTS 198 ///< Number of actions that can have a key combination associated to it.
/*** Types definitions and structs ***/
typedef struct
{
word Number; ///< Identifier for shortcut. This is a number starting from 0, which matches ::T_Config_shortcut_info.Number
char Label[36]; ///< Text to show in the screen where you can edit the shortcut.
char Explanation1[37]; ///< Explanation text (1/3) to show in the screen where you can edit the shortcut.
char Explanation2[37]; ///< Explanation text (2/3) to show in the screen where you can edit the shortcut.
char Explanation3[37]; ///< Explanation text (3/3) to show in the screen where you can edit the shortcut.
bool Suppr; ///< Boolean, true if the shortcut can be removed.
word Key; ///< Primary shortcut. Value is a keycode, see keyboard.h
word Key2; ///< Secondary shortcut. Value is a keycode, see keyboard.h
} T_Key_config;
/// Table with all the configurable shortcuts, whether they are for a menu button or a special action.
extern T_Key_config ConfigKey[NB_SHORTCUTS];
///
/// Translation table from a shortcut index to a shortcut identifier.
/// The value is either:
/// - 0x000 + special shortcut number
/// - 0x100 + button number (left click)
/// - 0x200 + button number (right click)
extern word Ordering[NB_SHORTCUTS];

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 init.h
/// Initialization (and some de-initialization) functions.
//////////////////////////////////////////////////////////////////////////////
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 Init_buttons(void);
void Init_operations(void);
void Init_brush_container(void);
int Load_CFG(int reload_all);
int Save_CFG(void);
void Set_all_video_modes(void);
void Set_config_defaults(void);
void Init_sighandler(void);
void Init_paintbrushes(void);
/// Set application icon(s)
void Define_icon(void);
extern char Gui_loading_error_message[512];
///
/// Loads a 8x8 monochrome font, the kind used in all menus and screens.
/// This function allocates the memory, and returns a pointer to it when
/// successful.
/// If an error is encountered, it frees what needs it, prints an error message
/// in ::Gui_loading_error_message, and returns NULL.
byte * Load_font(const char * font_name);
///
/// Based on which toolbars are visible, updates their offsets and
/// computes ::Menu_height and ::Menu_Y
void Compute_menu_offsets(void);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 input.h
/// Functions for mouse, keyboard and joystick input.
/// Joystick input is used to emulate mouse on platforms that don't have a
/// pointing device, ie: the GP2X.
//////////////////////////////////////////////////////////////////////////////
///
/// This is the keyboard/mouse/joystick input polling function.
/// Returns 1 if a significant changed occurred, such as a mouse button pressed
/// or depressed, or a new keypress was in the keyboard buffer.
/// 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
/// on subsequent calls to ::Get_input().
int Get_input(int sleep_time);
/// Returns true if the keycode has been set as a keyboard shortcut for the 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)
void Adjust_mouse_sensitivity(word fullscreen);
void Set_mouse_position(void);
///
/// This holds the ID of the GUI control that the mouse
/// is manipulating. The input system will reset it to zero
/// when mouse button is released, but it's the engine
/// that will record and retrieve a real control ID.
extern int Input_sticky_control;
/// Allows locking movement to X or Y axis: 0=normal, 1=lock on next move, 2=locked horizontally, 3=locked vertically.
extern int Snap_axis;
/// For the :Snap_axis mode, sets the origin's point (in image coordinates)
extern int Snap_axis_origin_X;
/// For the :Snap_axis mode, sets the origin's point (in image coordinates)
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

@@ -0,0 +1,498 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
// Fonctions de lecture/ecriture file, gèrent les systèmes big-endian et
// little-endian.
#define _XOPEN_SOURCE 500
#include <SDL_endian.h>
#include <string.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
#include <proto/dos.h>
#include <sys/types.h>
#include <dirent.h>
#elif defined(__WIN32__)
#include <dirent.h>
#include <windows.h>
//#include <commdlg.h>
#elif defined(__MINT__)
#include <mint/osbind.h>
#include <mint/sysbind.h>
#include <dirent.h>
#else
#include <dirent.h>
#endif
#include "struct.h"
#include "io.h"
#include "realpath.h"
// Lit un octet
// Renvoie -1 si OK, 0 en cas d'erreur
int Read_byte(FILE *file, byte *dest)
{
return fread(dest, 1, 1, file) == 1;
}
// Ecrit un octet
// Renvoie -1 si OK, 0 en cas d'erreur
int Write_byte(FILE *file, byte b)
{
return fwrite(&b, 1, 1, file) == 1;
}
// Lit des octets
// Renvoie -1 si OK, 0 en cas d'erreur
int Read_bytes(FILE *file, void *dest, size_t size)
{
return fread(dest, 1, size, file) == size;
}
// Ecrit des octets
// Renvoie -1 si OK, 0 en cas d'erreur
int Write_bytes(FILE *file, void *src, size_t size)
{
return fwrite(src, 1, size, file) == size;
}
// Lit un word (little-endian)
// Renvoie -1 si OK, 0 en cas d'erreur
int Read_word_le(FILE *file, word *dest)
{
if (fread(dest, 1, sizeof(word), file) != sizeof(word))
return 0;
#if SDL_BYTEORDER != SDL_LIL_ENDIAN
*dest = SDL_Swap16(*dest);
#endif
return -1;
}
// Ecrit un word (little-endian)
// Renvoie -1 si OK, 0 en cas d'erreur
int Write_word_le(FILE *file, word w)
{
#if SDL_BYTEORDER != SDL_LIL_ENDIAN
w = SDL_Swap16(w);
#endif
return fwrite(&w, 1, sizeof(word), file) == sizeof(word);
}
// Lit un word (big-endian)
// Renvoie -1 si OK, 0 en cas d'erreur
int Read_word_be(FILE *file, word *dest)
{
if (fread(dest, 1, sizeof(word), file) != sizeof(word))
return 0;
#if SDL_BYTEORDER != SDL_BIG_ENDIAN
*dest = SDL_Swap16(*dest);
#endif
return -1;
}
// Ecrit un word (big-endian)
// Renvoie -1 si OK, 0 en cas d'erreur
int Write_word_be(FILE *file, word w)
{
#if SDL_BYTEORDER != SDL_BIG_ENDIAN
w = SDL_Swap16(w);
#endif
return fwrite(&w, 1, sizeof(word), file) == sizeof(word);
}
// Lit un dword (little-endian)
// Renvoie -1 si OK, 0 en cas d'erreur
int Read_dword_le(FILE *file, dword *dest)
{
if (fread(dest, 1, sizeof(dword), file) != sizeof(dword))
return 0;
#if SDL_BYTEORDER != SDL_LIL_ENDIAN
*dest = SDL_Swap32(*dest);
#endif
return -1;
}
// Ecrit un dword (little-endian)
// Renvoie -1 si OK, 0 en cas d'erreur
int Write_dword_le(FILE *file, dword dw)
{
#if SDL_BYTEORDER != SDL_LIL_ENDIAN
dw = SDL_Swap32(dw);
#endif
return fwrite(&dw, 1, sizeof(dword), file) == sizeof(dword);
}
// Lit un dword (big-endian)
// Renvoie -1 si OK, 0 en cas d'erreur
int Read_dword_be(FILE *file, dword *dest)
{
if (fread(dest, 1, sizeof(dword), file) != sizeof(dword))
return 0;
#if SDL_BYTEORDER != SDL_BIG_ENDIAN
*dest = SDL_Swap32(*dest);
#endif
return -1;
}
// Ecrit un dword (big-endian)
// Renvoie -1 si OK, 0 en cas d'erreur
int Write_dword_be(FILE *file, dword dw)
{
#if SDL_BYTEORDER != SDL_BIG_ENDIAN
dw = SDL_Swap32(dw);
#endif
return fwrite(&dw, 1, sizeof(dword), file) == sizeof(dword);
}
// Détermine la position du dernier '/' ou '\\' dans une chaine,
// typiquement pour séparer le nom de file d'un chemin.
// Attention, sous Windows, il faut s'attendre aux deux car
// par exemple un programme lancé sous GDB aura comme argv[0]:
// d:\Data\C\GFX2\grafx2/grafx2.exe
char * Find_last_slash(const char * str)
{
const char * position = NULL;
for (; *str != '\0'; str++)
if (*str == PATH_SEPARATOR[0]
#ifdef __WIN32__
|| *str == '/'
#endif
)
position = str;
return (char *)position;
}
// Récupère la partie "nom de file seul" d'un chemin
void Extract_filename(char *dest, const char *source)
{
const char * position = Find_last_slash(source);
if (position)
strcpy(dest,position+1);
else
strcpy(dest,source);
}
// Récupère la partie "répertoire+/" d'un chemin.
void Extract_path(char *dest, const char *source)
{
char * position=NULL;
Realpath(source,dest);
position = Find_last_slash(dest);
if (position)
*(position+1) = '\0';
else
strcat(dest, PATH_SEPARATOR);
}
///
/// Appends a file or directory name to an existing directory name.
/// As a special case, when the new item is equal to PARENT_DIR, this
/// will remove the rightmost directory name.
/// reverse_path is optional, if it's non-null, the function will
/// write there :
/// - if filename is ".." : The name of eliminated directory/file
/// - else: ".."
void Append_path(char *path, const char *filename, char *reverse_path)
{
// Parent
if (!strcmp(filename, PARENT_DIR))
{
// Going up one directory
long len;
char * slash_pos;
// Remove trailing slash
len=strlen(path);
if (len && (!strcmp(path+len-1,PATH_SEPARATOR)
#ifdef __WIN32__
|| path[len-1]=='/'
#endif
))
path[len-1]='\0';
slash_pos=Find_last_slash(path);
if (slash_pos)
{
if (reverse_path)
strcpy(reverse_path, slash_pos+1);
*slash_pos='\0';
}
else
{
if (reverse_path)
strcpy(reverse_path, path);
path[0]='\0';
}
#if defined(__WIN32__)
// Roots of drives need a pending antislash
if (path[0]!='\0' && path[1]==':' && path[2]=='\0')
{
strcat(path, PATH_SEPARATOR);
}
#endif
}
else
// Sub-directory
{
long len;
// Add trailing slash if needed
len=strlen(path);
if (len && (strcmp(path+len-1,PATH_SEPARATOR)
#ifdef __WIN32__
&& path[len-1]!='/'
#endif
))
{
strcpy(path+len, PATH_SEPARATOR);
len+=strlen(PATH_SEPARATOR);
}
strcat(path, filename);
if (reverse_path)
strcpy(reverse_path, PARENT_DIR);
}
}
int File_exists(char * fname)
// Détermine si un file passé en paramètre existe ou non dans le
// répertoire courant.
{
struct stat buf;
int result;
result=stat(fname,&buf);
if (result!=0)
return(errno!=ENOENT);
else
return 1;
}
int Directory_exists(char * directory)
// Détermine si un répertoire passé en paramètre existe ou non dans le
// répertoire courant.
{
DIR* entry; // Structure de lecture des éléments
if (strcmp(directory,PARENT_DIR)==0)
return 1;
else
{
// On va chercher si le répertoire existe à l'aide d'un Opendir. S'il
// renvoie NULL c'est que le répertoire n'est pas accessible...
entry=opendir(directory);
if (entry==NULL)
return 0;
else
{
closedir(entry);
return 1;
}
}
}
#if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__) || defined(__MINT__)
#define FILE_IS_HIDDEN_ATTRIBUTE __attribute__((unused))
#else
#define FILE_IS_HIDDEN_ATTRIBUTE
#endif
/// Check if a file or directory is hidden.
int File_is_hidden(FILE_IS_HIDDEN_ATTRIBUTE const char *fname, const char *full_name)
{
#if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__) || defined(__MINT__)
// False (unable to determine, or irrrelevent for platform)
return 0;
#elif defined(__WIN32__)
unsigned long att;
if (full_name!=NULL)
att = GetFileAttributesA(full_name);
else
att = GetFileAttributesA(fname);
if (att==INVALID_FILE_ATTRIBUTES)
return 0;
return (att&FILE_ATTRIBUTE_HIDDEN)?1:0;
#else
return fname[0]=='.';
#endif
}
// Taille de fichier, en octets
int File_length(const char * fname)
{
struct stat infos_fichier;
if (stat(fname,&infos_fichier))
return 0;
return infos_fichier.st_size;
}
int File_length_file(FILE * file)
{
struct stat infos_fichier;
if (fstat(fileno(file),&infos_fichier))
return 0;
return infos_fichier.st_size;
}
void For_each_file(const char * directory_name, void Callback(const char *))
{
// 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);
if (S_ISREG(Infos_enreg.st_mode))
{
Callback(full_filename);
}
}
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(full_filename);
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),
File_is_hidden(entry->d_name, full_filename));
}
closedir(current_directory);
}
void Get_full_filename(char * output_name, char * file_name, char * directory_name)
{
strcpy(output_name,directory_name);
if (output_name[0] != '\0')
{
// Append a separator at the end of path, if there isn't one already.
// This handles the case of directory variables which contain one,
// as well as directories like "/" on Unix.
if (output_name[strlen(output_name)-1]!=PATH_SEPARATOR[0])
strcat(output_name,PATH_SEPARATOR);
}
strcat(output_name,file_name);
}
/// Lock file used to prevent several instances of grafx2 from harming each others' backups
#ifdef __WIN32__
HANDLE Lock_file_handle = INVALID_HANDLE_VALUE;
#else
int Lock_file_handle = -1;
#endif
byte Create_lock_file(const char *file_directory)
{
#if defined (__amigaos__)||(__AROS__)||(ANDROID)
#warning "Missing code for your platform, please check and correct!"
#else
char lock_filename[MAX_PATH_CHARACTERS];
strcpy(lock_filename,file_directory);
strcat(lock_filename,"gfx2.lck");
#ifdef __WIN32__
// Windowzy method for creating a lock file
Lock_file_handle = CreateFile(
lock_filename,
GENERIC_WRITE,
0, // No sharing
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (Lock_file_handle == INVALID_HANDLE_VALUE)
{
return -1;
}
#else
// Unixy method for lock file
Lock_file_handle = open(lock_filename,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR);
if (Lock_file_handle == -1)
{
// Usually write-protected media
return -1;
}
if (lockf(Lock_file_handle, F_TLOCK, 0)==-1)
{
close(Lock_file_handle);
// Usually write-protected media
return -1;
}
#endif
#endif // __amigaos__ or __AROS__
return 0;
}
void Release_lock_file(const char *file_directory)
{
char lock_filename[MAX_PATH_CHARACTERS];
#ifdef __WIN32__
if (Lock_file_handle != INVALID_HANDLE_VALUE)
{
CloseHandle(Lock_file_handle);
}
#else
if (Lock_file_handle != -1)
{
close(Lock_file_handle);
Lock_file_handle = -1;
}
#endif
// Actual deletion
strcpy(lock_filename,file_directory);
strcat(lock_filename,"gfx2.lck");
remove(lock_filename);
}

View File

@@ -0,0 +1,125 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Yves Rizoud
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 io.h
/// Low-level endian-neutral file operations, and also some filesystem operations.
/// Many of these may seem trivial, but the wrappers eliminate the need for a
/// forest of preprocessor defines in each file.
/// You MUST use the functions in this file instead of:
/// - fread() and fwrite()
/// - stat()
/// - fstat()
/// - opendir()
/// - readdir()
/// - Also, don't assume "/" or "\\", use PATH_SEPARATOR
/// If you don't, you break another platform.
//////////////////////////////////////////////////////////////////////////////
/// Reads a single byte from an open file. Returns true if OK, false if a file i/o error occurred.
int Read_byte(FILE *file, byte *dest);
/// Writes a single byte to an open file. Returns true if OK, false if a file i/o error occurred.
int Write_byte(FILE *file, byte b);
/// Reads several bytes from an open file. Returns true if OK, false if a file i/o error occurred.
int Read_bytes(FILE *file, void *dest, size_t size);
/// Writes several bytes to an open file. Returns true if OK, false if a file i/o error occurred.
int Write_bytes(FILE *file, void *dest, size_t size);
/// Reads a 16-bit Low-Endian word from an open file. Returns true if OK, false if a file i/o error occurred.
int Read_word_le(FILE *file, word *dest);
/// Writes a 16-bit Low-Endian word to an open file. Returns true if OK, false if a file i/o error occurred.
int Write_word_le(FILE *file, word w);
/// Reads a 32-bit Low-Endian dword from an open file. Returns true if OK, false if a file i/o error occurred.
int Read_dword_le(FILE *file, dword *dest);
/// Writes a 32-bit Low-Endian dword to an open file. Returns true if OK, false if a file i/o error occurred.
int Write_dword_le(FILE *file, dword dw);
/// Reads a 16-bit Big-Endian word from an open file. Returns true if OK, false if a file i/o error occurred.
int Read_word_be(FILE *file, word *dest);
/// Writes a 16-bit Big-Endian word to an open file. Returns true if OK, false if a file i/o error occurred.
int Write_word_be(FILE *file, word w);
/// Reads a 32-bit Big-Endian dword from an open file. Returns true if OK, false if a file i/o error occurred.
int Read_dword_be(FILE *file, dword *dest);
/// Writes a 32-bit Big-Endian dword to an open file. Returns true if OK, false if a file i/o error occurred.
int Write_dword_be(FILE *file, dword dw);
/// Extracts the filename part from a full file name.
void Extract_filename(char *dest, const char *source);
/// Extracts the directory from a full file name.
void Extract_path(char *dest, const char *source);
/// Finds the rightmost path separator in a full filename. Used to separate directory from file.
char * Find_last_slash(const char * str);
#if defined(__WIN32__)
#define PATH_SEPARATOR "\\"
#elif defined(__MINT__)
#define PATH_SEPARATOR "\\"
#else
#define PATH_SEPARATOR "/"
#endif
/// Size of a file, in bytes. Returns 0 in case of error.
int File_length(const char *fname);
/// Size of a file, in bytes. Takes an open file as argument, returns 0 in case of error.
int File_length_file(FILE * file);
/// Returns true if a file passed as a parameter exists in the current directory.
int File_exists(char * fname);
/// Returns true if a directory passed as a parameter exists in the current directory.
int Directory_exists(char * directory);
/// Check if a file or directory is hidden. Full name (with directories) is optional.
int File_is_hidden(const char *fname, const char *full_name);
/// Scans a directory, calls Callback for each file in it,
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.
/// The point is simply to insert a PATH_SEPARATOR when needed.
void Get_full_filename(char * output_name, char * file_name, char * directory_name);
///
/// Appends a file or directory name to an existing directory name.
/// As a special case, when the new item is equal to PARENT_DIR, this
/// will remove the rightmost directory name.
/// reverse_path is optional, if it's non-null, the function will
/// write there :
/// - if filename is ".." : The name of eliminated directory/file
/// - else: ".."
void Append_path(char *path, const char *filename, char *reverse_path);
///
/// Creates a lock file, to check if an other instance of Grafx2 is running.
/// @return 0 on success (first instance), -1 on failure (others are running)
byte Create_lock_file(const char *file_directory);
///
/// Release a lock file created by ::Create_Lock_file
void Release_lock_file(const char *file_directory);

View File

@@ -0,0 +1,713 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2010 Alexander Filyanov
Copyright 2009 Franck Charlet
Copyright 2008 Yves Rizoud
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#include <string.h>
#include <ctype.h>
#include "global.h"
#include "keyboard.h"
// Table de correspondance des scancode de clavier IBM PC AT vers
// les symboles de touches SDL (sym).
// La correspondance est bonne si le clavier est QWERTY US, ou si
// l'utilisateur est sous Windows.
// Dans l'ordre des colonnes: Normal, +Shift, +Control, +Alt
const word Scancode_to_sym[256][4] =
{
/* 00 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 01 Esc */ { SDLK_ESCAPE ,SDLK_ESCAPE ,SDLK_ESCAPE ,SDLK_ESCAPE },
/* 02 1 ! */ { SDLK_1 ,SDLK_1 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 03 2 @ */ { SDLK_2 ,SDLK_2 ,SDLK_2 ,SDLK_UNKNOWN },
/* 04 3 # */ { SDLK_3 ,SDLK_3 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 05 4 $ */ { SDLK_4 ,SDLK_4 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 06 5 % */ { SDLK_5 ,SDLK_5 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 07 6 ^ */ { SDLK_6 ,SDLK_6 ,SDLK_6 ,SDLK_UNKNOWN },
/* 08 7 & */ { SDLK_7 ,SDLK_7 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 09 8 * */ { SDLK_8 ,SDLK_8 ,SDLK_8 ,SDLK_UNKNOWN },
/* 0A 9 ( */ { SDLK_9 ,SDLK_9 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 0B 0 ) */ { SDLK_0 ,SDLK_0 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 0C - _ */ { SDLK_MINUS ,SDLK_MINUS ,SDLK_MINUS ,SDLK_UNKNOWN },
/* 0D = + */ { SDLK_EQUALS ,SDLK_EQUALS ,SDLK_EQUALS ,SDLK_UNKNOWN },
/* 0E BkSpc */ { SDLK_BACKSPACE ,SDLK_BACKSPACE ,SDLK_BACKSPACE ,SDLK_BACKSPACE },
/* 0F Tab */ { SDLK_TAB ,SDLK_TAB ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 10 Q */ { SDLK_q ,SDLK_q ,SDLK_q ,SDLK_q },
/* 11 W */ { SDLK_w ,SDLK_w ,SDLK_w ,SDLK_w },
/* 12 E */ { SDLK_e ,SDLK_e ,SDLK_e ,SDLK_e },
/* 13 R */ { SDLK_r ,SDLK_r ,SDLK_r ,SDLK_r },
/* 14 T */ { SDLK_t ,SDLK_t ,SDLK_t ,SDLK_t },
/* 15 Y */ { SDLK_y ,SDLK_y ,SDLK_y ,SDLK_y },
/* 16 U */ { SDLK_u ,SDLK_u ,SDLK_u ,SDLK_u },
/* 17 I */ { SDLK_i ,SDLK_i ,SDLK_i ,SDLK_i },
/* 18 O */ { SDLK_o ,SDLK_o ,SDLK_o ,SDLK_o },
/* 19 P */ { SDLK_p ,SDLK_p ,SDLK_p ,SDLK_p },
/* 1A [ */ { SDLK_LEFTBRACKET ,SDLK_LEFTBRACKET ,SDLK_LEFTBRACKET ,SDLK_LEFTBRACKET },
/* 1B ] */ { SDLK_RIGHTBRACKET,SDLK_RIGHTBRACKET,SDLK_RIGHTBRACKET,SDLK_RIGHTBRACKET},
/* 1C Retrn */ { SDLK_RETURN ,SDLK_RETURN ,SDLK_RETURN ,SDLK_RETURN },
/* 1D ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 1E A */ { SDLK_a ,SDLK_a ,SDLK_a ,SDLK_a },
/* 1F S */ { SDLK_s ,SDLK_s ,SDLK_s ,SDLK_s },
/* 20 D */ { SDLK_d ,SDLK_d ,SDLK_d ,SDLK_d },
/* 21 F */ { SDLK_f ,SDLK_f ,SDLK_f ,SDLK_f },
/* 22 G */ { SDLK_g ,SDLK_g ,SDLK_g ,SDLK_g },
/* 23 H */ { SDLK_h ,SDLK_h ,SDLK_h ,SDLK_h },
/* 24 J */ { SDLK_j ,SDLK_j ,SDLK_j ,SDLK_j },
/* 25 K */ { SDLK_k ,SDLK_k ,SDLK_k ,SDLK_k },
/* 26 L */ { SDLK_l ,SDLK_l ,SDLK_l ,SDLK_l },
/* 27 ; : */ { SDLK_SEMICOLON ,SDLK_SEMICOLON ,SDLK_SEMICOLON ,SDLK_SEMICOLON },
/* 28 ' */ { SDLK_QUOTE ,SDLK_QUOTE ,SDLK_UNKNOWN ,SDLK_QUOTE },
/* 29 ` ~ */ { SDLK_BACKQUOTE ,SDLK_BACKQUOTE ,SDLK_UNKNOWN ,SDLK_BACKQUOTE },
/* 2A ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 2B \\ */ { SDLK_BACKSLASH ,SDLK_BACKSLASH ,SDLK_BACKSLASH ,SDLK_BACKSLASH },
/* 2C Z */ { SDLK_z ,SDLK_z ,SDLK_z ,SDLK_z },
/* 2D X */ { SDLK_x ,SDLK_x ,SDLK_x ,SDLK_x },
/* 2E C */ { SDLK_c ,SDLK_c ,SDLK_c ,SDLK_c },
/* 2F V */ { SDLK_v ,SDLK_v ,SDLK_v ,SDLK_v },
/* 30 B */ { SDLK_b ,SDLK_b ,SDLK_b ,SDLK_b },
/* 31 N */ { SDLK_n ,SDLK_n ,SDLK_n ,SDLK_n },
/* 32 M */ { SDLK_m ,SDLK_m ,SDLK_m ,SDLK_m },
/* 33 , < */ { SDLK_COMMA ,SDLK_COMMA ,SDLK_UNKNOWN ,SDLK_COMMA },
/* 34 . > */ { SDLK_PERIOD ,SDLK_PERIOD ,SDLK_UNKNOWN ,SDLK_PERIOD },
/* 35 / ? */ { SDLK_SLASH ,SDLK_SLASH ,SDLK_UNKNOWN ,SDLK_SLASH },
/* 36 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 37 Grey* */ { SDLK_KP_MULTIPLY ,SDLK_KP_MULTIPLY ,SDLK_UNKNOWN ,SDLK_KP_MULTIPLY },
/* 38 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 39 Space */ { SDLK_SPACE ,SDLK_SPACE ,SDLK_SPACE ,SDLK_SPACE },
/* 3A ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 3B F1 */ { SDLK_F1 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 3C F2 */ { SDLK_F2 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 3D F3 */ { SDLK_F3 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 3E F4 */ { SDLK_F4 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 3F F5 */ { SDLK_F5 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 40 F6 */ { SDLK_F6 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 41 F7 */ { SDLK_F7 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 42 F8 */ { SDLK_F8 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 43 F9 */ { SDLK_F9 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 44 F10 */ { SDLK_F10 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 45 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 46 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 47 Home */ { SDLK_HOME ,SDLK_HOME ,SDLK_UNKNOWN ,SDLK_HOME },
/* 48 Up */ { SDLK_UP ,SDLK_UP ,SDLK_UNKNOWN ,SDLK_UP },
/* 49 PgUp */ { SDLK_PAGEUP ,SDLK_PAGEUP ,SDLK_UNKNOWN ,SDLK_PAGEUP },
/* 4A Grey- */ { SDLK_KP_MINUS ,SDLK_KP_MINUS ,SDLK_UNKNOWN ,SDLK_KP_MINUS },
/* 4B Left */ { SDLK_LEFT ,SDLK_LEFT ,SDLK_UNKNOWN ,SDLK_LEFT },
/* 4C Kpad5 */ { SDLK_KP5 ,SDLK_KP5 ,SDLK_UNKNOWN ,SDLK_KP5 },
/* 4D Right */ { SDLK_RIGHT ,SDLK_RIGHT ,SDLK_UNKNOWN ,SDLK_RIGHT },
/* 4E Grey+ */ { SDLK_KP_PLUS ,SDLK_KP_PLUS ,SDLK_UNKNOWN ,SDLK_KP_PLUS },
/* 4F End */ { SDLK_END ,SDLK_END ,SDLK_UNKNOWN ,SDLK_END },
/* 50 Down */ { SDLK_DOWN ,SDLK_DOWN ,SDLK_UNKNOWN ,SDLK_DOWN },
/* 51 PgDn */ { SDLK_PAGEDOWN ,SDLK_PAGEDOWN ,SDLK_UNKNOWN ,SDLK_PAGEDOWN },
/* 52 Ins */ { SDLK_INSERT ,SDLK_INSERT ,SDLK_UNKNOWN ,SDLK_INSERT },
/* 53 Del */ { SDLK_DELETE ,SDLK_DELETE ,SDLK_UNKNOWN ,SDLK_DELETE },
/* 54 ??? */ { SDLK_UNKNOWN ,SDLK_F1 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 55 ??? */ { SDLK_UNKNOWN ,SDLK_F2 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 56 Lft| */ { SDLK_UNKNOWN ,SDLK_F3 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 57 ??? */ { SDLK_UNKNOWN ,SDLK_F4 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 58 ??? */ { SDLK_UNKNOWN ,SDLK_F5 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 59 ??? */ { SDLK_UNKNOWN ,SDLK_F6 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 5A ??? */ { SDLK_UNKNOWN ,SDLK_F7 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 5B ??? */ { SDLK_UNKNOWN ,SDLK_F8 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 5C ??? */ { SDLK_UNKNOWN ,SDLK_F9 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 5D ??? */ { SDLK_UNKNOWN ,SDLK_F10 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 5E ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F1 ,SDLK_UNKNOWN },
/* 5F ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F2 ,SDLK_UNKNOWN },
/* 60 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F3 ,SDLK_UNKNOWN },
/* 61 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F4 ,SDLK_UNKNOWN },
/* 62 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F5 ,SDLK_UNKNOWN },
/* 63 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F6 ,SDLK_UNKNOWN },
/* 64 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F7 ,SDLK_UNKNOWN },
/* 65 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F8 ,SDLK_UNKNOWN },
/* 66 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F9 ,SDLK_UNKNOWN },
/* 67 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F10 ,SDLK_UNKNOWN },
/* 68 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F1 },
/* 69 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F2 },
/* 6A ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F3 },
/* 6B ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F4 },
/* 6C ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F5 },
/* 6D ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F6 },
/* 6E ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F7 },
/* 6F ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F8 },
/* 70 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F9 },
/* 71 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F10 },
/* 72 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 73 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_LEFT ,SDLK_UNKNOWN },
/* 74 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_RIGHT ,SDLK_UNKNOWN },
/* 75 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_END ,SDLK_UNKNOWN },
/* 76 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_PAGEDOWN ,SDLK_UNKNOWN },
/* 77 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_HOME ,SDLK_UNKNOWN },
/* 78 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_1 },
/* 79 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_2 },
/* 7A ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_3 },
/* 7B ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_4 },
/* 7C ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_5 },
/* 7D ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_6 },
/* 7E ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_7 },
/* 7F ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_8 },
/* 80 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_9 },
/* 81 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_0 },
/* 82 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_MINUS },
/* 83 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_EQUALS },
/* 84 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_PAGEUP ,SDLK_UNKNOWN },
/* 85 F11 */ { SDLK_F11 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 86 F12 */ { SDLK_F12 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 87 ??? */ { SDLK_UNKNOWN ,SDLK_F11 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 88 ??? */ { SDLK_UNKNOWN ,SDLK_F12 ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 89 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F11 ,SDLK_UNKNOWN },
/* 8A ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F12 ,SDLK_UNKNOWN },
/* 8B ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F11 },
/* 8C ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F12 },
/* 8D ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UP ,SDLK_UNKNOWN },
/* 8E ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP_MINUS ,SDLK_UNKNOWN },
/* 8F ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP5 ,SDLK_UNKNOWN },
/* 90 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP_PLUS ,SDLK_UNKNOWN },
/* 91 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_DOWN ,SDLK_UNKNOWN },
/* 92 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_INSERT ,SDLK_UNKNOWN },
/* 93 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_DELETE ,SDLK_UNKNOWN },
/* 94 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_TAB ,SDLK_UNKNOWN },
/* 95 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP_DIVIDE ,SDLK_UNKNOWN },
/* 96 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP_MULTIPLY ,SDLK_UNKNOWN },
/* 97 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_HOME },
/* 98 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UP },
/* 99 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_PAGEUP },
/* 9A ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 9B ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_LEFT },
/* 9C ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 9D ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_RIGHT },
/* 9E ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* 9F ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_END },
/* A0 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_DOWN },
/* A1 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_PAGEUP },
/* A2 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_INSERT },
/* A3 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_DELETE },
/* A4 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP_DIVIDE },
/* A5 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_TAB },
/* A6 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP_ENTER },
/* A7 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* A8 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* A9 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* AA ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* AB ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* AC ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* AD ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* AE ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* AF ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* B0 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* B1 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* B2 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* B3 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* B4 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* B5 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* B6 Win L */ { SDLK_LSUPER ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* B7 Win R */ { SDLK_RSUPER ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* B8 Win M */ { SDLK_MENU ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* B9 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* BA ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* BB ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* BC ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* BD ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* BE ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* BF ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* C0 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* C1 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* C2 ??? */ { SDLK_UNKNOWN ,SDLK_LSUPER ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* C3 ??? */ { SDLK_UNKNOWN ,SDLK_RSUPER ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* C4 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* C5 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* C6 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* C7 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* C8 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* C9 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* CA ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* CB ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* CC ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* CD ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* CE ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_LSUPER ,SDLK_UNKNOWN },
/* CF ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_RSUPER ,SDLK_UNKNOWN },
/* D0 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_MENU ,SDLK_UNKNOWN },
/* D1 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* D2 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* D3 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* D4 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* D5 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* D6 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* D7 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* D8 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* D9 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* DA ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_LSUPER },
/* DB ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_RSUPER },
/* DC ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_MENU },
/* DD ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* DE ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* DF ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* E0 Enter */ { SDLK_KP_ENTER ,SDLK_KP_ENTER ,SDLK_KP_ENTER ,SDLK_UNKNOWN },
/* E1 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* E2 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* E3 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* E4 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* E5 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* E6 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* E7 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* E8 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* E9 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* EA ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* EB ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* EC ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* ED ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* EE ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* EF ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* F0 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* F1 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* F2 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* F3 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* F4 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* F5 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* F6 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* F7 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* F8 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* F9 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* FA ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* FB ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* FC ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* FD ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* FE ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
/* FF ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN },
};
// Conversion de l'ancien codage des touches:
// 0x00FF le scancode (maintenant code sym sur 0x0FFF)
// 0x0100 shift (maintenant 0x1000)
// 0x0200 control (maintenant 0x2000)
// 0x0400 alt (maintenant 0x4000)
word Key_for_scancode(word scancode)
{
if (scancode & 0x0400)
return Scancode_to_sym[scancode & 0xFF][3] |
(scancode & 0x0700) << 4;
else if (scancode & 0x0200)
return Scancode_to_sym[scancode & 0xFF][2] |
(scancode & 0x0700) << 4;
else if (scancode & 0x0100)
return Scancode_to_sym[scancode & 0xFF][1] |
(scancode & 0x0700) << 4;
else
return Scancode_to_sym[scancode & 0xFF][0];
}
// Convertit des modificateurs de touches SDL en modificateurs GrafX2
word Key_modifiers(SDLMod mod)
{
word modifiers=0;
if (mod & KMOD_CTRL )
modifiers|=MOD_CTRL;
if (mod & KMOD_SHIFT )
modifiers|=MOD_SHIFT;
if (mod & (KMOD_ALT|KMOD_MODE))
modifiers|=MOD_ALT;
if (mod & (KMOD_META))
modifiers|=MOD_META;
return modifiers;
}
word Keysym_to_keycode(SDL_keysym keysym)
{
word key_code = 0;
word mod;
// On ignore shift, alt et control isolés.
if (keysym.sym == SDLK_RSHIFT || keysym.sym == SDLK_LSHIFT ||
keysym.sym == SDLK_RCTRL || keysym.sym == SDLK_LCTRL ||
keysym.sym == SDLK_RALT || keysym.sym == SDLK_LALT ||
keysym.sym == SDLK_RMETA || keysym.sym == SDLK_LMETA ||
keysym.sym == SDLK_MODE) // AltGr
return 0;
// Les touches qui n'ont qu'une valeur unicode (très rares)
// seront codées sur 11 bits, le 12e bit est mis à 1 (0x0800)
if (keysym.sym != 0)
key_code = keysym.sym;
else if (keysym.scancode != 0)
{
key_code = (keysym.scancode & 0x07FF) | 0x0800;
}
// Normally I should test keysym.mod here, but on windows the implementation
// is buggy: if you release a modifier key, the following keys (when they repeat)
// still name the original modifiers.
mod=Key_modifiers(SDL_GetModState());
// SDL_GetModState() seems to get the right up-to-date info.
key_code |= mod;
return key_code;
}
const char * Key_name(word key)
{
typedef struct
{
word keysym;
char *Key_name;
} T_key_label;
T_key_label key_labels[] =
{
{ SDLK_BACKSPACE , "Backspace" },
{ SDLK_TAB , "Tab" },
{ SDLK_CLEAR , "Clear" },
{ SDLK_RETURN , "Return" },
{ SDLK_PAUSE , "Pause" },
{ SDLK_ESCAPE , "Esc" },
{ SDLK_DELETE , "Del" },
{ SDLK_KP0 , "KP 0" },
{ SDLK_KP1 , "KP 1" },
{ SDLK_KP2 , "KP 2" },
{ SDLK_KP3 , "KP 3" },
{ SDLK_KP4 , "KP 4" },
{ SDLK_KP5 , "KP 5" },
{ SDLK_KP6 , "KP 6" },
{ SDLK_KP7 , "KP 7" },
{ SDLK_KP8 , "KP 8" },
{ SDLK_KP9 , "KP 9" },
{ SDLK_KP_PERIOD , "KP ." },
{ SDLK_KP_DIVIDE , "KP /" },
{ SDLK_KP_MULTIPLY, "KP *" },
{ SDLK_KP_MINUS , "KP -" },
{ SDLK_KP_PLUS , "KP +" },
{ SDLK_KP_ENTER , "KP Enter" },
{ SDLK_KP_EQUALS , "KP =" },
{ SDLK_UP , "Up" },
{ SDLK_DOWN , "Down" },
{ SDLK_RIGHT , "Right" },
{ SDLK_LEFT , "Left" },
{ SDLK_INSERT , "Ins" },
{ SDLK_HOME , "Home" },
{ SDLK_END , "End" },
{ SDLK_PAGEUP , "PgUp" },
{ SDLK_PAGEDOWN , "PgDn" },
{ SDLK_F1 , "F1" },
{ SDLK_F2 , "F2" },
{ SDLK_F3 , "F3" },
{ SDLK_F4 , "F4" },
{ SDLK_F5 , "F5" },
{ SDLK_F6 , "F6" },
{ SDLK_F7 , "F7" },
{ SDLK_F8 , "F8" },
{ SDLK_F9 , "F9" },
{ SDLK_F10 , "F10" },
{ SDLK_F11 , "F11" },
{ SDLK_F12 , "F12" },
{ SDLK_F13 , "F13" },
{ SDLK_F14 , "F14" },
{ SDLK_F15 , "F15" },
{ SDLK_NUMLOCK , "NumLock" },
{ SDLK_CAPSLOCK , "CapsLck" },
{ SDLK_SCROLLOCK , "ScrlLock" },
{ SDLK_RSHIFT , "RShift" },
{ SDLK_LSHIFT , "LShift" },
{ SDLK_RCTRL , "RCtrl" },
{ SDLK_LCTRL , "LCtrl" },
{ SDLK_RALT , "RAlt" },
{ SDLK_LALT , "LAlt" },
{ SDLK_RMETA , "RMeta" },
{ SDLK_LMETA , "LMeta" },
{ SDLK_LSUPER , "LWin" },
{ SDLK_RSUPER , "RWin" },
{ SDLK_MODE , "AltGr" },
{ SDLK_COMPOSE , "Comp" },
{ SDLK_HELP , "Help" },
{ SDLK_PRINT , "Print" },
{ SDLK_SYSREQ , "SysReq" },
{ SDLK_BREAK , "Break" },
{ SDLK_MENU , "Menu" },
{ SDLK_POWER , "Power" },
{ SDLK_EURO , "Euro" },
{ SDLK_UNDO , "Undo" },
{ KEY_MOUSEMIDDLE, "Mouse3" },
{ KEY_MOUSEWHEELUP, "WheelUp" },
{ KEY_MOUSEWHEELDOWN, "WheelDown" }
};
int index;
static char buffer[41];
buffer[0] = '\0';
if (key == SDLK_UNKNOWN)
return "None";
if (key & MOD_CTRL)
strcat(buffer, "Ctrl+");
if (key & MOD_ALT)
strcat(buffer, "Alt+");
if (key & MOD_SHIFT)
strcat(buffer, "Shift+");
if (key & MOD_META)
strcat(buffer, "\201");
// Note: Apple's "command" character is not present in the ANSI table, so we
// recycled an ANSI value that doesn't have any displayable character
// associated.
key=key & ~(MOD_CTRL|MOD_ALT|MOD_SHIFT);
// 99 is only a sanity check
if (key>=KEY_JOYBUTTON && key<=KEY_JOYBUTTON+99)
{
char *button_name;
switch(key-KEY_JOYBUTTON)
{
#ifdef JOY_BUTTON_UP
case JOY_BUTTON_UP: button_name="[UP]"; break;
#endif
#ifdef JOY_BUTTON_DOWN
case JOY_BUTTON_DOWN: button_name="[DOWN]"; break;
#endif
#ifdef JOY_BUTTON_LEFT
case JOY_BUTTON_LEFT: button_name="[LEFT]"; break;
#endif
#ifdef JOY_BUTTON_RIGHT
case JOY_BUTTON_RIGHT: button_name="[RIGHT]"; break;
#endif
#ifdef JOY_BUTTON_UPLEFT
case JOY_BUTTON_UPLEFT: button_name="[UP-LEFT]"; break;
#endif
#ifdef JOY_BUTTON_UPRIGHT
case JOY_BUTTON_UPRIGHT: button_name="[UP-RIGHT]"; break;
#endif
#ifdef JOY_BUTTON_DOWNLEFT
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);
return buffer;
}
if (key & 0x800)
{
sprintf(buffer+strlen(buffer), "[%d]", key & 0x7FF);
return buffer;
}
key = key & 0x7FF;
// Touches ASCII
if (key>=' ' && key < 127)
{
sprintf(buffer+strlen(buffer), "'%c'", toupper(key));
return buffer;
}
// Touches 'World'
if (key>=SDLK_WORLD_0 && key <= SDLK_WORLD_95)
{
sprintf(buffer+strlen(buffer), "w%d", key - SDLK_WORLD_0);
return buffer;
}
// Touches au libellé connu
for (index=0; index < (long)sizeof(key_labels)/(long)sizeof(T_key_label);index++)
{
if (key == key_labels[index].keysym)
{
sprintf(buffer+strlen(buffer), "%s", key_labels[index].Key_name);
return buffer;
}
}
// Autres touches inconnues
sprintf(buffer+strlen(buffer), "0x%X", key & 0x7FF);
return buffer;
}
// Obtient le caractère ANSI tapé, à partir d'un keysym.
// (Valeur 32 à 255)
// Renvoie 0 s'il n'y a pas de caractère associé (shift, backspace, etc)
word Keysym_to_ANSI(SDL_keysym keysym)
{
// This part was removed from the MacOSX port, but I put it back for others
// as on Linux and Windows, it's what allows editing a text line with the keys
// SDLK_LEFT, SDLK_RIGHT, SDLK_HOME, SDLK_END etc.
#if !(defined(__macosx__) || defined(__FreeBSD__))
if ( keysym.unicode == 0)
{
switch(keysym.sym)
{
case SDLK_DELETE:
case SDLK_LEFT:
case SDLK_RIGHT:
case SDLK_HOME:
case SDLK_END:
case SDLK_BACKSPACE:
case KEY_ESC:
return keysym.sym;
case SDLK_RETURN:
// Case alt-enter
if (SDL_GetModState() & (KMOD_ALT|KMOD_META))
return '\n';
return keysym.sym;
default:
return 0;
}
}
#endif
//
if ( keysym.unicode > 32 && keysym.unicode < 127)
{
return keysym.unicode; // Pas de souci, on est en ASCII standard
}
// Quelques conversions Unicode-ANSI
switch(keysym.unicode)
{
case 0x8100:
return 'ü'; // ü
case 0x1A20:
return 'é'; // é
case 0x201A:
return 'è'; // è
case 0x9201:
return 'â'; // â
case 0x1E20:
return 'ä'; // ä
case 0x2620:
return 'à'; // à
case 0x2020:
return 'å'; // å
case 0x2120:
return 'ç'; // ç
case 0xC602:
return 'ê'; // ê
case 0x3020:
return 'ë'; // ë
case 0x6001:
return 'è'; // è
case 0x3920:
return 'ï'; // ï
case 0x5201:
return 'î'; // î
case 0x8D00:
return 'ì'; // ì
case 0x1C20:
return 'ô'; // ô
case 0x1D20:
return 'ö'; // ö
case 0x2220:
return 'ò'; // ò
case 0x1320:
return 'û'; // û
case 0x1420:
return 'ù'; // ù
case 0xDC02:
return 'ÿ'; // ÿ
case 0x5301:
return '£'; // £
case 0xA000:
return 'á'; // á
case 0xA100:
return 'í'; // í
case 0xA200:
return 'ó'; // ó
case 0xA300:
return 'ú'; // ú
case 0xA400:
return 'ñ'; // ñ
case 0xA700:
return 'º'; // º
case 0xC600:
return 'ã'; // ã
}
// Key entre 127 et 255
if (keysym.unicode<256)
{
#if defined(__macosx__) || defined(__FreeBSD__)
// fc: Looks like there's a mismatch with delete & backspace
// i don't why SDLK_DELETE was returned instead of SDLK_BACKSPACE
if(keysym.unicode == 127)
{
return(SDLK_BACKSPACE);
}
// We don't make any difference between return & enter in the app context.
if(keysym.unicode == 3)
{
return(SDLK_RETURN);
}
#endif
return keysym.unicode;
}
// Sinon c'est une touche spéciale, on retourne son scancode
return keysym.sym;
}

View File

@@ -0,0 +1,77 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 keyboard.h
/// Functions to convert bewteen the SDL key formats and the keycode we use
/// in grafx2.
/// The keycode we're using is generalized to handle mouse and joystick shortcuts
/// as well. The format can be broken down as:
/// - 0x0000 + a number between 0 and SDLK_LAST (about 324) : the SDL "sym" key number.
/// - 0x0000 + SDLK_LAST+1: Mouse middle button.
/// - 0x0000 + SDLK_LAST+2: Mouse wheel up.
/// - 0x0000 + SDLK_LAST+3: Mouse wheel down.
/// - 0x0000 + SDLK_LAST+4+B : Joystick button number "B", starting at B=0.
/// - 0x0800 + a number between 0 and 0x7FF: The scancode key number, for keys which have no "sym", such as keys from multimedia keyboards, and "fn" and "Thinkpad" key for a laptop.
/// Add 0x1000 for the Shift modifier MOD_SHIFT
/// Add 0x2000 for the Control modifier ::MOD_CONTROL
/// Add 0x4000 for the Alt modifier ::MOD_ALT
/// Add 0x8000 for the "Meta" modifier ::MOD_META (On MacOS X it's the CMD key)
//////////////////////////////////////////////////////////////////////////////
/*!
Convert an SDL keysym to an ANSI/ASCII character.
This is used to type text and numeric values in input boxes.
@param keysym SDL symbol to convert
*/
word Keysym_to_ANSI(SDL_keysym keysym);
/*!
Convert an SDL keysym to an internal keycode number.
This is needed because SDL tends to split the information across the unicode sym, the regular sym, and the raw keycode.
We also need to differenciate 1 (keypad) and 1 (regular keyboard), and some other things.
See the notice at the beginning of keyboard.h for the format of a keycode.
@param keysym SDL symbol to convert
*/
word Keysym_to_keycode(SDL_keysym keysym);
/*!
Helper function to convert between SDL system and the old coding for PC keycodes.
This is only used to convert configuration files from the DOS version of
Grafx2, where keyboard codes are in in the IBM PC AT form.
@param scancode Scancode to convert
*/
word Key_for_scancode(word scancode);
/*!
Returns key name in a string. Used to display them in the helpscreens and in the keymapper window.
@param Key keycode of the key to translate, including modifiers
*/
const char * Key_name(word key);
/*!
Gets the modifiers in our format from the SDL_Mod information.
Returns a combination of ::MOD_SHIFT, ::MOD_ALT, ::MOD_CONTROL
@param mod SDL modifiers state
*/
word Key_modifiers(SDLMod mod);

View File

@@ -0,0 +1,391 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2009 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#include "const.h"
#include "struct.h"
#include "global.h"
#include "windows.h"
#include "engine.h"
#include "pages.h"
#include "sdlscreen.h"
#include "input.h"
#include "help.h"
#include "misc.h"
void Layer_activate(byte layer, short side)
{
word old_layers;
if (layer >= Main_backups->Pages->Nb_layers)
return;
// Keep a copy of which layers were visible
old_layers = Main_layers_visible;
#ifndef NOLAYERS
if (side == RIGHT_SIDE)
{
// Right-click on current layer
if (Main_current_layer == layer)
{
if (Main_layers_visible == (dword)(1<<layer))
{
// Set all layers visible
Main_layers_visible = 0xFFFFFFFF;
}
else
{
// Set only this one visible
Main_layers_visible = 1<<layer;
}
}
else
{
// Right-click on an other layer : toggle its visibility
Main_layers_visible ^= 1<<layer;
}
}
else
{
// Left-click on any layer
Main_current_layer = layer;
Main_layers_visible |= 1<<layer;
}
#else
// Handler for limited layers support: only allow one visible at a time
if (side == LEFT_SIDE)
{
Main_current_layer = layer;
Main_layers_visible = 1<<layer;
Update_screen_targets();
}
#endif
Hide_cursor();
if (Main_layers_visible != old_layers)
Redraw_layered_image();
else
Update_depth_buffer(); // Only need the depth buffer
//Download_infos_page_main(Main_backups->Pages);
//Update_FX_feedback(Config.FX_Feedback);
Display_all_screen();
Display_layerbar();
Display_cursor();
}
void Button_Layer_add(void)
{
Hide_cursor();
if (Main_backups->Pages->Nb_layers < MAX_NB_LAYERS)
{
// Backup with unchanged layers
Backup_layers(0);
if (!Add_layer(Main_backups,Main_current_layer+1))
{
Update_depth_buffer();
Display_all_screen();
Display_layerbar();
End_of_modification();
}
}
Unselect_button(BUTTON_LAYER_ADD);
Display_cursor();
}
void Button_Layer_remove(void)
{
Hide_cursor();
if (Main_backups->Pages->Nb_layers > 1)
{
// Backup with unchanged layers
Backup_layers(0);
if (!Delete_layer(Main_backups,Main_current_layer))
{
Update_screen_targets();
Redraw_layered_image();
Display_all_screen();
Display_layerbar();
End_of_modification();
}
}
Unselect_button(BUTTON_LAYER_REMOVE);
Display_cursor();
}
void Button_Layer_select(void)
{
short layer;
// Determine which button is clicked according to mouse position
layer = (Mouse_X/Menu_factor_X - Menu_bars[MENUBAR_LAYERS].Skin_width)
/ Layer_button_width;
// Safety required because the mouse cursor can have slided outside button.
if (layer < 0)
layer=0;
else if (layer > Main_backups->Pages->Nb_layers-1)
layer=Main_backups->Pages->Nb_layers-1;
Layer_activate(layer, LEFT_SIDE);
}
void Button_Layer_toggle(void)
{
short layer;
// Determine which button is clicked according to mouse position
layer = (Mouse_X/Menu_factor_X - Menu_bars[MENUBAR_LAYERS].Skin_width)
/ Layer_button_width;
// Safety required because the mouse cursor can have slided outside button.
if (layer < 0)
layer=0;
else if (layer > Main_backups->Pages->Nb_layers-1)
layer=Main_backups->Pages->Nb_layers-1;
Layer_activate(layer, RIGHT_SIDE);
}
static void Draw_transparent_color(byte color)
{
char buf[4];
Num2str(color, buf, 3);
Print_in_window(63,39,buf,MC_Black,MC_Light);
Window_rectangle(90,39,13,7,color);
}
static void Draw_transparent_background(byte background)
{
Print_in_window(99,57,background?"X":" ",MC_Black,MC_Light);
}
void Button_Layer_menu(void)
{
byte transparent_color = Main_backups->Pages->Transparent_color;
byte transparent_background = Main_backups->Pages->Background_transparent;
short clicked_button;
byte color;
byte click;
Open_window(122,100,"Layers");
Window_display_frame_in( 6, 21,110, 52);
Print_in_window(14,18,"Transparency",MC_Dark,MC_Light);
Print_in_window(11,38,"Color",MC_Black,MC_Light);
Window_set_normal_button(54, 36, 56,13,"" , 0,1,KEY_NONE); // 1
Draw_transparent_color(transparent_color);
Print_in_window(11,57,"Background",MC_Black,MC_Light);
Window_set_normal_button(95, 54, 15,13,"" , 0,1,KEY_NONE); // 2
Draw_transparent_background(transparent_background);
Window_set_normal_button( 7, 78, 51,14,"OK" , 0,1,SDLK_RETURN); // 3
Window_set_normal_button(63, 78, 51,14,"Cancel", 0,1,KEY_ESC); // 4
Update_window_area(0,0,Window_width, Window_height);
do
{
clicked_button=Window_clicked_button();
if (Is_shortcut(Key,0x100+BUTTON_HELP))
Window_help(BUTTON_LAYER_MENU, NULL);
switch(clicked_button)
{
case 1: // color
Get_color_behind_window(&color,&click);
if (click && transparent_color!=color)
{
transparent_color=color;
Hide_cursor();
Draw_transparent_color(transparent_color);
Display_cursor();
Wait_end_of_click();
}
break;
case 2: // background
transparent_background = !transparent_background;
Hide_cursor();
Draw_transparent_background(transparent_background);
Display_cursor();
break;
}
}
while (clicked_button<3);
// On exit
Hide_cursor();
Close_window();
if (clicked_button==3)
{
// Accept changes
if (Main_backups->Pages->Transparent_color != transparent_color ||
Main_backups->Pages->Background_transparent != transparent_background)
{
Backup_layers(-1);
Main_backups->Pages->Transparent_color = transparent_color;
Main_backups->Pages->Background_transparent = transparent_background;
Redraw_layered_image();
Display_all_screen();
End_of_modification();
}
}
Unselect_button(BUTTON_LAYER_MENU);
Display_cursor();
}
void Button_Layer_set_transparent(void)
{
Hide_cursor();
if (Main_backups->Pages->Transparent_color != Back_color)
{
Backup_layers(-1);
Main_backups->Pages->Transparent_color = Back_color;
Redraw_layered_image();
Display_all_screen();
End_of_modification();
}
Unselect_button(BUTTON_LAYER_COLOR);
Display_cursor();
}
void Button_Layer_get_transparent(void)
{
Hide_cursor();
if (Main_backups->Pages->Transparent_color != Back_color)
{
Set_back_color(Main_backups->Pages->Transparent_color);
}
Unselect_button(BUTTON_LAYER_COLOR);
Display_cursor();
}
void Button_Layer_merge(void)
{
Hide_cursor();
if (Main_current_layer>0)
{
// Backup layer below the current
Backup_layers(1<<(Main_current_layer-1));
Merge_layer();
Update_screen_targets();
Redraw_layered_image();
Display_all_screen();
Display_layerbar();
End_of_modification();
}
Unselect_button(BUTTON_LAYER_MERGE);
Display_cursor();
}
void Button_Layer_up(void)
{
Hide_cursor();
if (Main_current_layer < (Main_backups->Pages->Nb_layers-1))
{
byte * tmp;
dword layer_flags;
// Backup with unchanged layers
Backup_layers(0);
// swap
tmp = Main_backups->Pages->Image[Main_current_layer];
Main_backups->Pages->Image[Main_current_layer] = Main_backups->Pages->Image[Main_current_layer+1];
Main_backups->Pages->Image[Main_current_layer+1] = tmp;
// Swap visibility indicators
layer_flags = (Main_layers_visible >> Main_current_layer) & 3;
// Only needed if they are different.
if (layer_flags == 1 || layer_flags == 2)
{
// One is on, the other is off. Negating them will
// perform the swap.
Main_layers_visible ^= (3 << Main_current_layer);
}
Main_current_layer++;
Update_screen_targets();
Redraw_layered_image();
Display_all_screen();
Display_layerbar();
End_of_modification();
}
Unselect_button(BUTTON_LAYER_UP);
Display_cursor();
}
void Button_Layer_down(void)
{
Hide_cursor();
if (Main_current_layer > 0)
{
byte * tmp;
dword layer_flags;
// Backup with unchanged layers
Backup_layers(0);
// swap
tmp = Main_backups->Pages->Image[Main_current_layer];
Main_backups->Pages->Image[Main_current_layer] = Main_backups->Pages->Image[Main_current_layer-1];
Main_backups->Pages->Image[Main_current_layer-1] = tmp;
// Swap visibility indicators
layer_flags = (Main_layers_visible >> (Main_current_layer-1)) & 3;
// Only needed if they are different.
if (layer_flags == 1 || layer_flags == 2)
{
// Only needed if they are different.
// One is on, the other is off. Negating them will
// perform the swap.
Main_layers_visible ^= (3 << (Main_current_layer-1));
}
Main_current_layer--;
Update_screen_targets();
Redraw_layered_image();
Display_layerbar();
Display_all_screen();
End_of_modification();
}
Unselect_button(BUTTON_LAYER_DOWN);
Display_cursor();
}

View File

@@ -0,0 +1,35 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2009 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
void Button_Layer_add(void);
void Button_Layer_remove(void);
void Button_Layer_menu(void);
void Button_Layer_set_transparent(void);
void Button_Layer_get_transparent(void);
void Button_Layer_merge(void);
void Button_Layer_up(void);
void Button_Layer_down(void);
void Button_Layer_select(void);
void Button_Layer_toggle(void);
void Layer_activate(byte layer, short side);

View File

@@ -0,0 +1,190 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* GFX2CRTC - libraw2crtc.c
* CloudStrife - 20080921
* Diffusé sous licence libre CeCILL v2
* Voire LICENCE
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "const.h"
#include "global.h"
#include "struct.h"
#include "loadsave.h"
unsigned short addrCalc(unsigned char vcc, unsigned char rcc, unsigned char hcc, unsigned char cclk, unsigned char r1, unsigned char r12, unsigned char r13)
{
unsigned short MA;
unsigned short addr;
//MA = vcc*r1 + hcc + (0x0C)*256;
MA = vcc*r1 + hcc + r12*256 + r13;
addr = cclk | ((MA & 0x03FF) << 1);
addr = addr | ((rcc & 0x07) << 11);
addr = addr | ((MA & 0x3000) << 2);
return addr;
}
unsigned char mode0interlace(T_IO_Context * context, unsigned char x, unsigned char y)
{
unsigned char mode0pixel[] = {0, 64, 4, 68, 16, 80, 20, 84, 1, 65, 5, 69, 17, 81, 21, 85};
return mode0pixel[Get_pixel(context,x,y)] << 1 | mode0pixel[Get_pixel(context,x+1,y)];
}
unsigned char mode1interlace(T_IO_Context * context, unsigned char x, unsigned char y)
{
unsigned char mode1pixel[] = {0, 16, 1, 17};
return mode1pixel[Get_pixel(context,x,y)] << 3 | mode1pixel[Get_pixel(context,x+1,y)] << 2 | mode1pixel[Get_pixel(context,x+2,y)] << 1 | mode1pixel[Get_pixel(context,x+3,y)];
}
unsigned char mode2interlace(T_IO_Context * context, unsigned char x, unsigned char y)
{
unsigned char out = 0;
int i;
for(i = 0; i < 8; i++) out += ((Get_pixel(context,x+7-i,y)&1) << i);
return out;
}
unsigned char mode3interlace(T_IO_Context * context, unsigned char x, unsigned char y)
{
unsigned char mode3pixel[] = {0, 16, 1, 17};
return mode3pixel[Get_pixel(context, x,y)] << 3 | mode3pixel[Get_pixel(context,x+1,y)] << 2;
}
unsigned char (*ptrMode)(T_IO_Context * context, unsigned char x, unsigned char y);
unsigned char *raw2crtc(T_IO_Context *context, unsigned short width, unsigned short height, unsigned char mode, unsigned char r9, unsigned long *outSize, unsigned char *r1, unsigned char r12, unsigned char r13)
{
unsigned char *outBuffer;
unsigned char *tmpBuffer;
unsigned char *allocationBuffer;
unsigned short minAddr = 0;
unsigned char minAddrIsDefined = 0;
unsigned short maxAddr = 0;
unsigned char nbPixPerByte;
int y,x;
unsigned char r6;
unsigned short i;
unsigned char *ptrTmp;
unsigned char *ptrOut;
unsigned char vcc;
unsigned char rcc;
unsigned char hcc;
unsigned char cclk;
switch(mode)
{
case 0:
{
*r1 = (width+3)/4;
nbPixPerByte = 2;
ptrMode = mode0interlace;
break;
}
case 1:
{
*r1 = (width+7)/8;
nbPixPerByte = 4;
ptrMode = mode1interlace;
break;
}
case 2:
{
*r1 = (width+15)/16;
nbPixPerByte = 8;
ptrMode = mode2interlace;
break;
}
case 3:
{
*r1 = (width+3)/4;
nbPixPerByte = 2;
ptrMode = mode3interlace;
break;
}
default:
{
exit(4);
}
}
tmpBuffer = (unsigned char*)malloc(0xFFFF);
if (tmpBuffer == NULL)
{
printf("Allocation tmpBuffer raté\n");
exit(4);
}
allocationBuffer = (unsigned char*)malloc(0xFFFF);
if(allocationBuffer == NULL)
{
printf("Allocation allocationBuffer raté\n");
exit(4);
}
memset(allocationBuffer, 0, 0xFFFF);
r6 = height/(r9+1);
for(vcc = 0; vcc < r6; vcc++)
{
for(rcc = 0; rcc < (r9+1); rcc++)
{
for(hcc = 0; hcc < *r1; hcc++)
{
for(cclk = 0; cclk < 2; cclk++)
{
x = (hcc << 1 | cclk);
y = vcc*(r9+1) + rcc;
*(tmpBuffer + addrCalc(vcc, rcc, hcc, cclk, *r1, r12, r13)) = (*ptrMode)(context,x,y);
*(allocationBuffer + addrCalc(vcc, rcc, hcc, cclk, *r1, r12, r13)) += 1;
}
}
}
}
for(i = 0; i < 0xFFFF; i++)
{
if(*(allocationBuffer + i) > 1)
{
printf("Attention : Ecriture multiple a l'adresse mémoire %d\n",i);
}
if(*(allocationBuffer + i) > 0)
{
maxAddr = i;
}
if((*(allocationBuffer + i) == 1) && (minAddrIsDefined == 0))
{
minAddr = i;
minAddrIsDefined = 1;
}
}
*outSize = (maxAddr + 1) - minAddr;
outBuffer = (unsigned char*)malloc((*outSize));
if (outBuffer == NULL)
{
printf("Allocation outBuffer raté\n");
exit(4);
}
ptrTmp = tmpBuffer + minAddr;
ptrOut = outBuffer;
for(i = minAddr; i <= maxAddr; i++)
{
*(ptrOut++) = *(ptrTmp++);
}
free(tmpBuffer);
tmpBuffer = NULL;
free(allocationBuffer);
allocationBuffer = NULL;
return outBuffer;
}

View File

@@ -0,0 +1,14 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* GFX2CRTC - libraw2crtc.h
* CloudStrife - 20080921
* Diffusé sous licence libre CeCILL v2
* Voire LICENCE
*/
#ifndef LIBRAW2CRTC_H
#define LIBRAW2CRTC_H 1
unsigned char * raw2crtc(unsigned short width, unsigned short height, unsigned char mode, unsigned char r9, unsigned long *outSize, unsigned char *r1, unsigned char r12, unsigned char r13);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,259 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 loadsave.h
/// Saving and loading different picture formats.
/// Also handles showing the preview in fileselectors.
//////////////////////////////////////////////////////////////////////////////
#ifndef __LOADSAVE_H__
#define __LOADSAVE_H__
#include <stdio.h>
#include <SDL_image.h>
enum CONTEXT_TYPE {
CONTEXT_MAIN_IMAGE,
CONTEXT_BRUSH,
CONTEXT_PREVIEW,
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
{
/// Kind of context. Internally used to differentiate the "sub-classes"
enum CONTEXT_TYPE Type;
// File properties
char * File_name;
char * File_directory;
byte Format;
// Image properties
T_Palette Palette;
short Width;
short Height;
byte Nb_layers;
char Comment[COMMENT_SIZE+1];
byte Background_transparent;
byte Transparent_color;
/// Pixel ratio of the image
enum PIXEL_RATIO Ratio;
/// Load/save address of first pixel
byte *Target_address;
/// Pitch: Difference of addresses between one pixel and the one just "below" it
long Pitch;
/// Original file name, stored in GIF file
char * Original_file_name;
/// Original file directory, stored in GIF file
char * Original_file_directory;
byte Color_cycles;
T_Color_cycle Cycle_range[16];
/// Internal: during load, marks which layer is being loaded.
short Current_layer;
/// Internal: Used to mark truecolor images on loading. Only used by preview.
//byte Is_truecolor;
/// Internal: Temporary RGB buffer when loading 24bit images
T_Components *Buffer_image_24b;
/// Internal: Temporary buffer when saving the flattened copy of something
byte *Buffer_image;
// Internal: working data for preview case
short Preview_factor_X;
short Preview_factor_Y;
short Preview_pos_X;
short Preview_pos_Y;
byte *Preview_bitmap;
byte Preview_usage[256];
// Internal: returned surface for SDL_Surface case
SDL_Surface * Surface;
} 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.
typedef void (* Func_IO) (T_IO_Context *);
/*
void Pixel_load_in_current_screen (word x_pos, word y_pos, byte color);
void Pixel_load_in_preview (word x_pos, word y_pos, byte color);
void Pixel_load_in_brush (word x_pos, word y_pos, byte color);
*/
// Setup for loading a preview in fileselector
void Init_context_preview(T_IO_Context * context, char *file_name, char *file_directory);
// Setup for loading/saving the current main image
void Init_context_layered_image(T_IO_Context * context, char *file_name, char *file_directory);
// Setup for loading/saving an intermediate backup
void Init_context_backup_image(T_IO_Context * context, char *file_name, char *file_directory);
// Setup for loading/saving the flattened version of current main image
void Init_context_flat_image(T_IO_Context * context, char *file_name, char *file_directory);
// Setup for loading/saving the user's brush
void Init_context_brush(T_IO_Context * context, char *file_name, char *file_directory);
// Setup for saving an arbitrary undo/redo step, from either the main or spare page.
void Init_context_history_step(T_IO_Context * context, T_Page *page);
// Setup for loading an image into a new SDL surface.
void Init_context_surface(T_IO_Context * context, char *file_name, char *file_directory);
// Cleans up resources (currently: the 24bit buffer)
void Destroy_context(T_IO_Context *context);
///
/// High-level picture loading function.
void Load_image(T_IO_Context *context);
///
/// High-level picture saving function.
void Save_image(T_IO_Context *context);
///
/// Checks if there are any pending safety backups, and then opens them.
/// Returns 0 if there were none
/// Returns non-zero if some backups were loaded.
int Check_recovery(void);
/// Makes a safety backup periodically.
void Rotate_safety_backups(void);
/// Remove safety backups. Need to call on normal program exit.
void Delete_safety_backups(void);
/// Data for an image file format.
typedef struct {
byte Identifier; ///< Identifier for this format in enum :FILE_FORMATS
char *Label; ///< Five-letter label
Func_IO Test; ///< Function which tests if the file is of this format
Func_IO Load; ///< Function which loads an image of this format
Func_IO Save; ///< Function which saves an image of this format
byte Palette_only; ///< Boolean, true if this format saves/loads only the palette.
byte Comment; ///< This file format allows a text comment
byte Supports_layers; ///< Boolean, true if this format preserves layers on saving
char *Default_extension; ///< Default file extension
char *Extensions; ///< List of semicolon-separated file extensions
} T_Format;
/// Array of the known file formats
extern T_Format File_formats[];
///
/// Function which attempts to save backups of the images (main and spare),
/// called in case of SIGSEGV.
/// It will save an image only if it has just one layer... otherwise,
/// the risk of flattening a layered image (or saving just one detail layer)
/// is too high.
void Image_emergency_backup(void);
///
/// Load an arbitrary SDL_Surface.
/// @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);
/*
/// Pixel ratio of last loaded image: one of :PIXEL_SIMPLE, :PIXEL_WIDE or :PIXEL_TALL
extern enum PIXEL_RATIO Ratio_of_loaded_image;
*/
T_Format * Get_fileformat(byte format);
// -- File formats
/// Total number of known file formats
unsigned int Nb_known_formats(void);
// Internal use
/// Generic allocation and similar stuff, done at beginning of image load, as soon as size is known.
void Pre_load(T_IO_Context *context, short width, short height, long file_size, int format, enum PIXEL_RATIO ratio, byte truecolor);
/// Remaps the window. To call after palette (last) changes.
void Palette_loaded(T_IO_Context *context);
/// Generic cleanup done on end of loading (ex: color-conversion from the temporary 24b buffer)
//void Post_load(T_IO_Context *context);
/// Query the color of a pixel (to save)
byte Get_pixel(T_IO_Context *context, short x, short y);
/// Set the color of a pixel (on load)
void Set_pixel(T_IO_Context *context, short x, short y, byte c);
/// Set the color of a 24bit pixel (on load)
void Set_pixel_24b(T_IO_Context *context, short x, short y, byte r, byte g, byte b);
/// Function to call when need to switch layers.
void Set_layer(T_IO_Context *context, byte layer);
// =================================================================
// What follows here are the definitions of functions and data
// useful for fileformats.c, miscfileformats.c etc.
// =================================================================
// This is here and not in fileformats.c because the emergency save uses it...
typedef struct
{
byte Filler1[6];
word Width;
word Height;
byte Filler2[118];
T_Palette Palette;
} T_IMG_Header;
// Data for 24bit loading
/*
typedef void (* Func_24b_display) (short,short,byte,byte,byte);
extern int Image_24b;
extern T_Components * Buffer_image_24b;
extern Func_24b_display Pixel_load_24b;
void Init_preview_24b(short width,short height,long size,int format);
void Pixel_load_in_24b_preview(short x_pos,short y_pos,byte r,byte g,byte b);
*/
//
void Set_file_error(int value);
/*
void Init_preview(short width,short height,long size,int format,enum PIXEL_RATIO ratio);
*/
void Init_write_buffer(void);
void Write_one_byte(FILE *file, byte b);
void End_write(FILE *file);
#endif

View File

@@ -0,0 +1,966 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2009 Pasi Kallinen
Copyright 2008 Peter Gordon
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#define GLOBAL_VARIABLES
// time.h defines timeval which conflicts with the one in amiga SDK
#ifdef __amigaos__
#include <devices/timer.h>
#else
#include <time.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <SDL.h>
#include <SDL_image.h>
// There is no WM on the GP2X...
#if !defined(__GP2X__) && !defined(__WIZ__) && !defined(__CAANOO__)
#include <SDL_syswm.h>
#endif
#include "const.h"
#include "struct.h"
#include "global.h"
#include "graph.h"
#include "misc.h"
#include "init.h"
#include "buttons.h"
#include "engine.h"
#include "pages.h"
#include "loadsave.h"
#include "sdlscreen.h"
#include "errors.h"
#include "readini.h"
#include "saveini.h"
#include "io.h"
#include "text.h"
#include "setup.h"
#include "windows.h"
#include "brush.h"
#include "palette.h"
#include "realpath.h"
#include "input.h"
#include "help.h"
#if defined(__WIN32__)
#include <windows.h>
#include <shlwapi.h>
#define chdir(dir) SetCurrentDirectory(dir)
#elif defined (__MINT__)
#include <mint/osbind.h>
#elif defined(__macosx__)
#import <corefoundation/corefoundation.h>
#import <sys/param.h>
#elif defined(__FreeBSD__)
#import <sys/param.h>
#endif
#if defined (__WIN32__)
// On Windows, SDL_putenv is not present in any compilable header.
// It can be linked anyway, this declaration only avoids
// a compilation warning.
extern DECLSPEC int SDLCALL SDL_putenv(const char *variable);
#endif
extern char Program_version[]; // generated in pversion.c
//--- Affichage de la syntaxe, et de la liste des modes vidéos disponibles ---
void Display_syntax(void)
{
int mode_index;
printf("Syntax: grafx2 [<arguments>] [<picture1>] [<picture2>]\n\n");
printf("<arguments> can be:]\n");
printf("\t-? -h -H -help for this help screen\n");
printf("\t-wide to emulate a video mode with wide pixels (2x1)\n");
printf("\t-tall to emulate a video mode with tall pixels (1x2)\n");
printf("\t-double to emulate a video mode with double pixels (2x2)\n");
printf("\t-wide2 to emulate a video mode with double wide pixels (4x2)\n");
printf("\t-tall2 to emulate a video mode with double tall pixels (2x4)\n");
printf("\t-triple to emulate a video mode with triple pixels (3x3)\n");
printf("\t-quadruple to emulate a video mode with quadruple pixels (4x4)\n");
printf("\t-rgb n to reduce RGB precision from 256 to n levels\n");
printf("\t-skin <filename> to use an alternate file with the menu graphics\n");
printf("\t-mode <videomode> to set a video mode\n");
printf("Arguments can be prefixed either by / - or --\n");
printf("They can also be abbreviated.\n\n");
printf("Available video modes:\n\n");
for (mode_index = 0; mode_index < Nb_video_modes; mode_index += 12)
{
int k;
for (k = 0; k < 6; k++)
{
if (mode_index + k >= Nb_video_modes) break;
printf("%12s",Mode_label(mode_index + k));
}
puts("");
}
}
// ---------------------------- Sortie impromptue ----------------------------
void Warning_function(const char *message, const char *filename, int line_number, const char *function_name)
{
printf("Warning in file %s, line %d, function %s : %s\n", filename, line_number, function_name, message);
}
// ---------------------------- Sortie impromptue ----------------------------
void Error_function(int error_code, const char *filename, int line_number, const char *function_name)
{
T_Palette temp_palette;
int index;
printf("Error number %d occured in file %s, line %d, function %s.\n", error_code, filename,line_number,function_name);
if (error_code==0)
{
// L'erreur 0 n'est pas une vraie erreur, elle fait seulement un flash rouge de l'écran pour dire qu'il y a un problème.
// Toutes les autres erreurs déclenchent toujours une sortie en catastrophe du programme !
memcpy(temp_palette,Main_palette,sizeof(T_Palette));
for (index=0;index<=255;index++)
temp_palette[index].R=255;
Set_palette(temp_palette);
Delay_with_active_mouse(50); // Half a second of red flash
Set_palette(Main_palette);
}
else
{
switch (error_code)
{
case ERROR_GUI_MISSING : printf("Error: File containing the GUI graphics is missing!\n");
printf("This program cannot run without this file.\n");
break;
case ERROR_GUI_CORRUPTED : printf("Error: File containing the GUI graphics couldn't be parsed!\n");
printf("This program cannot run without a correct version of this file.\n");
break;
case ERROR_INI_MISSING : printf("Error: File gfx2def.ini is missing!\n");
printf("This program cannot run without this file.\n");
break;
case ERROR_MEMORY : printf("Error: Not enough memory!\n\n");
printf("You should try exiting other programs to free some bytes for Grafx2.\n\n");
break;
case ERROR_FORBIDDEN_MODE : printf("Error: The requested video mode has been disabled from the resolution menu!\n");
printf("If you want to run the program in this mode, you'll have to start it with an\n");
printf("enabled mode, then enter the resolution menu and enable the mode you want.\n");
printf("Check also if the 'Default_video_mode' parameter in gfx2.ini is correct.\n");
break;
case ERROR_COMMAND_LINE : printf("Error: Invalid parameter or file not found.\n\n");
Display_syntax();
break;
case ERROR_SAVING_CFG : printf("Error: Write error while saving settings!\n");
printf("Settings have not been saved correctly, and the gfx2.cfg file may have been\n");
printf("corrupt. If so, please delete it and Grafx2 will restore default settings.\n");
break;
case ERROR_MISSING_DIRECTORY : printf("Error: Directory you ran the program from not found!\n");
break;
case ERROR_INI_CORRUPTED : printf("Error: File gfx2.ini is corrupt!\n");
printf("It contains bad values at line %d.\n",Line_number_in_INI_file);
printf("You can re-generate it by deleting the file and running GrafX2 again.\n");
break;
case ERROR_SAVING_INI : printf("Error: Cannot rewrite file gfx2.ini!\n");
break;
case ERROR_SORRY_SORRY_SORRY : printf("Error: Sorry! Sorry! Sorry! Please forgive me!\n");
break;
}
SDL_Quit();
exit(error_code);
}
}
enum CMD_PARAMS
{
CMDPARAM_HELP,
CMDPARAM_MODE,
CMDPARAM_PIXELRATIO_TALL,
CMDPARAM_PIXELRATIO_WIDE,
CMDPARAM_PIXELRATIO_DOUBLE,
CMDPARAM_PIXELRATIO_TRIPLE,
CMDPARAM_PIXELRATIO_QUAD,
CMDPARAM_PIXELRATIO_TALL2,
CMDPARAM_PIXELRATIO_WIDE2,
CMDPARAM_RGB,
CMDPARAM_SKIN
};
struct {
const char *param;
int id;
} cmdparams[] = {
{"?", CMDPARAM_HELP},
{"h", CMDPARAM_HELP},
{"H", CMDPARAM_HELP},
{"help", CMDPARAM_HELP},
{"mode", CMDPARAM_MODE},
{"tall", CMDPARAM_PIXELRATIO_TALL},
{"wide", CMDPARAM_PIXELRATIO_WIDE},
{"double", CMDPARAM_PIXELRATIO_DOUBLE},
{"triple", CMDPARAM_PIXELRATIO_TRIPLE},
{"quadruple", CMDPARAM_PIXELRATIO_QUAD},
{"tall2", CMDPARAM_PIXELRATIO_TALL2},
{"wide2", CMDPARAM_PIXELRATIO_WIDE2},
{"rgb", CMDPARAM_RGB},
{"skin", CMDPARAM_SKIN}
};
#define ARRAY_SIZE(x) (int)(sizeof(x) / sizeof(x[0]))
// --------------------- Analyse de la ligne de commande ---------------------
int Analyze_command_line(int argc, char * argv[], char *main_filename, char *main_directory, char *spare_filename, char *spare_directory)
{
char *buffer ;
int index;
int file_in_command_line;
file_in_command_line = 0;
Resolution_in_command_line = 0;
Current_resolution = Config.Default_resolution;
for (index = 1; index<argc; index++)
{
char *s = argv[index];
int is_switch = ((strchr(s,'/') == s) || (strchr(s,'-') == s) || (strstr(s,"--") == s));
int tmpi;
int paramtype = -1;
if (is_switch)
{
int param_matches = 0;
int param_match = -1;
if (*s == '-')
{
s++;
if (*s == '-')
s++;
}
else
s++;
for (tmpi = 0; tmpi < ARRAY_SIZE(cmdparams); tmpi++)
{
if (!strcmp(s, cmdparams[tmpi].param))
{
paramtype = cmdparams[tmpi].id;
break;
}
else if (strstr(cmdparams[tmpi].param, s))
{
param_matches++;
param_match = cmdparams[tmpi].id;
}
}
if (paramtype == -1 && param_matches == 1)
paramtype = param_match;
}
switch (paramtype)
{
case CMDPARAM_HELP:
Display_syntax();
exit(0);
case CMDPARAM_MODE:
index++;
if (index<argc)
{
Resolution_in_command_line = 1;
Current_resolution = Convert_videomode_arg(argv[index]);
if (Current_resolution == -1)
{
Error(ERROR_COMMAND_LINE);
Display_syntax();
exit(0);
}
if ((Video_mode[Current_resolution].State & 0x7F) == 3)
{
Error(ERROR_FORBIDDEN_MODE);
exit(0);
}
}
else
{
Error(ERROR_COMMAND_LINE);
Display_syntax();
exit(0);
}
break;
case CMDPARAM_PIXELRATIO_TALL:
Pixel_ratio = PIXEL_TALL;
break;
case CMDPARAM_PIXELRATIO_WIDE:
Pixel_ratio = PIXEL_WIDE;
break;
case CMDPARAM_PIXELRATIO_DOUBLE:
Pixel_ratio = PIXEL_DOUBLE;
break;
case CMDPARAM_PIXELRATIO_TRIPLE:
Pixel_ratio = PIXEL_TRIPLE;
break;
case CMDPARAM_PIXELRATIO_QUAD:
Pixel_ratio = PIXEL_QUAD;
break;
case CMDPARAM_PIXELRATIO_TALL2:
Pixel_ratio = PIXEL_TALL2;
break;
case CMDPARAM_PIXELRATIO_WIDE2:
Pixel_ratio = PIXEL_WIDE2;
break;
case CMDPARAM_RGB:
// echelle des composants RGB
index++;
if (index<argc)
{
int scale;
scale = atoi(argv[index]);
if (scale < 2 || scale > 256)
{
Error(ERROR_COMMAND_LINE);
Display_syntax();
exit(0);
}
Set_palette_RGB_scale(scale);
}
else
{
Error(ERROR_COMMAND_LINE);
Display_syntax();
exit(0);
}
break;
case CMDPARAM_SKIN:
// GUI skin file
index++;
if (index<argc)
{
strcpy(Config.Skin_file,argv[index]);
}
else
{
Error(ERROR_COMMAND_LINE);
Display_syntax();
exit(0);
}
break;
default:
// Si ce n'est pas un paramètre, c'est le nom du fichier à ouvrir
if (file_in_command_line > 1)
{
// Il y a déjà 2 noms de fichiers et on vient d'en trouver un 3ème
Error(ERROR_COMMAND_LINE);
Display_syntax();
exit(0);
}
else if (File_exists(argv[index]))
{
file_in_command_line ++;
buffer = Realpath(argv[index], NULL);
if (file_in_command_line == 1)
{
// Separate path from filename
Extract_path(main_directory, buffer);
Extract_filename(main_filename, buffer);
}
else
{
// Separate path from filename
Extract_path(spare_directory, buffer);
Extract_filename(spare_filename, buffer);
}
free(buffer);
buffer = NULL;
}
else
{
Error(ERROR_COMMAND_LINE);
Display_syntax();
exit(0);
}
break;
}
}
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 -------------------------
// Returns 0 on fail
int Init_program(int argc,char * argv[])
{
int temp;
int starting_videomode;
static char program_directory[MAX_PATH_CHARACTERS];
T_Gui_skin *gfx;
int file_in_command_line;
T_Gradient_array initial_gradients;
static char main_filename [MAX_PATH_CHARACTERS];
static char main_directory[MAX_PATH_CHARACTERS];
static char spare_filename [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
// principale et la page de brouillon afin que leurs champs ne soient pas
// invalide lors des appels aux multiples fonctions manipulées à
// l'initialisation du programme.
Main_backups=(T_List_of_pages *)malloc(sizeof(T_List_of_pages));
Spare_backups=(T_List_of_pages *)malloc(sizeof(T_List_of_pages));
Init_list_of_pages(Main_backups);
Init_list_of_pages(Spare_backups);
// Determine the executable directory
Set_program_directory(argv[0],program_directory);
// Choose directory for data (read only)
Set_data_directory(program_directory,Data_directory);
// Choose directory for settings (read/write)
Set_config_directory(program_directory,Config_directory);
#if defined(__MINT__)
strcpy(Main_current_directory,program_directory);
#else
// On détermine le répertoire courant:
getcwd(Main_current_directory,256);
#endif
// On en profite pour le mémoriser dans le répertoire principal:
strcpy(Initial_directory,Main_current_directory);
// On initialise les données sur le nom de fichier de l'image de brouillon:
strcpy(Spare_current_directory,Main_current_directory);
Main_fileformat=DEFAULT_FILEFORMAT;
Spare_fileformat =Main_fileformat;
strcpy(Brush_current_directory,Main_current_directory);
strcpy(Brush_file_directory,Main_current_directory);
strcpy(Brush_filename ,"NO_NAME.GIF");
Brush_fileformat =Main_fileformat;
// On initialise ce qu'il faut pour que les fileselects ne plantent pas:
Main_fileselector_position=0; // Au début, le fileselect est en haut de la liste des fichiers
Main_fileselector_offset=0; // Au début, le fileselect est en haut de la liste des fichiers
Main_format=FORMAT_ALL_IMAGES;
Main_current_layer=0;
Main_layers_visible=0xFFFFFFFF;
Spare_current_layer=0;
Spare_layers_visible=0xFFFFFFFF;
Spare_fileselector_position=0;
Spare_fileselector_offset=0;
Spare_format=FORMAT_ALL_IMAGES;
Brush_fileselector_position=0;
Brush_fileselector_offset=0;
Brush_format=FORMAT_ALL_IMAGES;
// On initialise les commentaires des images à des chaînes vides
Main_comment[0]='\0';
Brush_comment[0]='\0';
// On initialise d'ot' trucs
Main_offset_X=0;
Main_offset_Y=0;
Main_separator_position=0;
Main_X_zoom=0;
Main_separator_proportion=INITIAL_SEPARATOR_PROPORTION;
Main_magnifier_mode=0;
Main_magnifier_factor=DEFAULT_ZOOM_FACTOR;
Main_magnifier_height=0;
Main_magnifier_width=0;
Main_magnifier_offset_X=0;
Main_magnifier_offset_Y=0;
Spare_offset_X=0;
Spare_offset_Y=0;
Spare_separator_position=0;
Spare_X_zoom=0;
Spare_separator_proportion=INITIAL_SEPARATOR_PROPORTION;
Spare_magnifier_mode=0;
Spare_magnifier_factor=DEFAULT_ZOOM_FACTOR;
Spare_magnifier_height=0;
Spare_magnifier_width=0;
Spare_magnifier_offset_X=0;
Spare_magnifier_offset_Y=0;
Keyboard_click_allowed = 1;
Main_safety_backup_prefix = SAFETYBACKUP_PREFIX_A[0];
Spare_safety_backup_prefix = SAFETYBACKUP_PREFIX_B[0];
Main_time_of_safety_backup = 0;
Spare_time_of_safety_backup = 0;
// SDL
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0)
{
// The program can't continue without that anyway
printf("Couldn't initialize SDL.\n");
return(0);
}
Joystick = SDL_JoystickOpen(0);
SDL_EnableKeyRepeat(250, 32);
SDL_EnableUNICODE(SDL_ENABLE);
SDL_WM_SetCaption("GrafX2","GrafX2");
Define_icon();
// Texte
Init_text();
// On initialise tous les modes vidéo
Set_all_video_modes();
Pixel_ratio=PIXEL_SIMPLE;
// On initialise les données sur l'état du programme:
// Donnée sur la sortie du programme:
Quit_is_required=0;
Quitting=0;
// Données sur l'état du menu:
Menu_is_visible=1;
// Données sur les couleurs et la palette:
First_color_in_palette=0;
// Données sur le curseur:
Cursor_shape=CURSOR_SHAPE_TARGET;
Cursor_hidden=0;
// Données sur le pinceau:
Paintbrush_X=0;
Paintbrush_Y=0;
Paintbrush_hidden=0;
// On initialise tout ce qui concerne les opérations et les effets
Operation_stack_size=0;
Selected_freehand_mode=OPERATION_CONTINUOUS_DRAW;
Selected_line_mode =OPERATION_LINE;
Selected_curve_mode =OPERATION_3_POINTS_CURVE;
Effect_function=No_effect;
// On initialise les infos de la loupe:
Main_magnifier_mode=0;
Main_magnifier_factor=DEFAULT_ZOOM_FACTOR;
Main_separator_proportion=INITIAL_SEPARATOR_PROPORTION;
Spare_separator_proportion=INITIAL_SEPARATOR_PROPORTION;
// On initialise les infos du mode smear:
Smear_mode=0;
Smear_brush_width=PAINTBRUSH_WIDTH;
Smear_brush_height=PAINTBRUSH_HEIGHT;
// On initialise les infos du mode smooth:
Smooth_mode=0;
// On initialise les infos du mode shade:
Shade_mode=0; // Les autres infos du Shade sont chargées avec la config
Quick_shade_mode=0; // idem
// On initialise les infos sur les dégradés:
Gradient_pixel =Display_pixel; // Les autres infos sont chargées avec la config
// On initialise les infos de la grille:
Snap_mode=0;
Snap_width=8;
Snap_height=8;
Snap_offset_X=0;
Snap_offset_Y=0;
// On initialise les infos du mode Colorize:
Colorize_mode=0; // Mode colorize inactif par défaut
Colorize_opacity=50; // Une interpolation de 50% par défaut
Colorize_current_mode=0; // Par défaut, la méthode par interpolation
Compute_colorize_table();
// On initialise les infos du mode Tiling:
Tiling_mode=0; // Pas besoin d'initialiser les décalages car ça se fait
// en prenant une brosse (toujours mis à 0).
// On initialise les infos du mode Mask:
Mask_mode=0;
// Infos du Spray
Airbrush_mode=1; // Mode Mono
Airbrush_size=31;
Airbrush_delay=1;
Airbrush_mono_flow=10;
memset(Airbrush_multi_flow,0,256);
srand(time(NULL)); // On randomize un peu tout ça...
// Initialisation des boutons
Init_buttons();
// Initialisation des opérations
Init_operations();
// Initialize the brush container
Init_brush_container();
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
Set_config_defaults();
switch(Load_CFG(1))
{
case ERROR_CFG_MISSING:
// Pas un problème, on a les valeurs par défaut.
break;
case ERROR_CFG_CORRUPTED:
DEBUG("Corrupted CFG file.",0);
break;
case ERROR_CFG_OLD:
DEBUG("Unknown CFG file version, not loaded.",0);
break;
}
// Charger la configuration du .INI
temp=Load_INI(&Config);
if (temp)
Error(temp);
if(!Config.Allow_multi_shortcuts)
{
Remove_duplicate_shortcuts();
}
Compute_menu_offsets();
file_in_command_line=Analyze_command_line(argc, argv, main_filename, main_directory, spare_filename, spare_directory);
Current_help_section=0;
Help_position=0;
// Load sprites, palette etc.
gfx = Load_graphics(Config.Skin_file, &initial_gradients);
if (gfx == NULL)
{
gfx = Load_graphics(DEFAULT_SKIN_FILENAME, &initial_gradients);
if (gfx == NULL)
{
printf("%s", Gui_loading_error_message);
Error(ERROR_GUI_MISSING);
}
}
Set_current_skin(Config.Skin_file, gfx);
// Override colors
// Gfx->Default_palette[MC_Black]=Config.Fav_menu_colors[0];
// Gfx->Default_palette[MC_Dark] =Config.Fav_menu_colors[1];
// Gfx->Default_palette[MC_Light]=Config.Fav_menu_colors[2];
// Gfx->Default_palette[MC_White]=Config.Fav_menu_colors[3];
// 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)
Sieve_mode=0;
Copy_preset_sieve(0);
// Font
if (!(Menu_font=Load_font(Config.Font_file)))
if (!(Menu_font=Load_font(DEFAULT_FONT_FILENAME)))
{
printf("Unable to open the default font file: %s\n", DEFAULT_FONT_FILENAME);
Error(ERROR_GUI_MISSING);
}
memcpy(Main_palette, Gfx->Default_palette, sizeof(T_Palette));
Fore_color=Best_color_nonexcluded(255,255,255);
Back_color=Best_color_nonexcluded(0,0,0);
// Allocation de mémoire pour la brosse
if (!(Brush =(byte *)malloc( 1* 1))) Error(ERROR_MEMORY);
if (!(Smear_brush =(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE))) Error(ERROR_MEMORY);
starting_videomode=Current_resolution;
Horizontal_line_buffer=NULL;
Screen_width=Screen_height=Current_resolution=0;
Init_mode_video(
Video_mode[starting_videomode].Width,
Video_mode[starting_videomode].Height,
Video_mode[starting_videomode].Fullscreen,
Pixel_ratio);
// Windows only: move back the window to its original position.
#if defined(__WIN32__)
if (!Video_mode[starting_videomode].Fullscreen)
{
if (Config.Window_pos_x != 9999 && Config.Window_pos_y != 9999)
{
//RECT r;
static SDL_SysWMinfo pInfo;
SDL_VERSION(&pInfo.version);
SDL_GetWMInfo(&pInfo);
//GetWindowRect(pInfo.window, &r);
SetWindowPos(pInfo.window, 0, Config.Window_pos_x, Config.Window_pos_y, 0, 0, SWP_NOSIZE);
}
}
// Open a console for debugging...
//ActivateConsole();
#endif
Main_image_width=Screen_width/Pixel_width;
Main_image_height=Screen_height/Pixel_height;
Spare_image_width=Screen_width/Pixel_width;
Spare_image_height=Screen_height/Pixel_height;
// Allocation de mémoire pour les différents écrans virtuels (et brosse)
if (Init_all_backup_lists(Screen_width,Screen_height)==0)
Error(ERROR_MEMORY);
// Nettoyage de l'écran virtuel (les autres recevront celui-ci par copie)
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:
Compute_magnifier_data();
Compute_limits();
Compute_paintbrush_coordinates();
// On affiche le menu:
Display_paintbrush_in_menu();
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:
Display_cursor();
Spare_image_is_modified=0;
Main_image_is_modified=0;
// Gestionnaire de signaux, quand il ne reste plus aucun espoir
Init_sighandler();
// Le programme débute en mode de dessin à la main
Select_button(BUTTON_DRAW,LEFT_SIDE);
// On initialise la brosse initiale à 1 pixel blanc:
Brush_width=1;
Brush_height=1;
for (temp=0;temp<256;temp++)
Brush_colormap[temp]=temp;
Capture_brush(0,0,0,0,0);
*Brush=MC_White;
*Brush_original_pixels=MC_White;
// Test de recuperation de fichiers sauvés
switch (Check_recovery())
{
T_IO_Context context;
default:
// Some files were loaded from last crash-exit.
// Do not load files from command-line, nor show splash screen.
Compute_optimal_menu_colors(Main_palette);
Display_all_screen();
Display_menu();
Display_cursor();
Verbose_message("Images recovered",
"Grafx2 has recovered images from\n"
"last session, before a crash or\n"
"shutdown. Browse the history using\n"
"the Undo/Redo button, and when\n"
"you find a state that you want to\n"
"save, use the 'Save as' button to\n"
"save the image.\n"
"Some backups can be present in\n"
"the spare page too.\n");
break;
case -1: // Unable to write lock file
Verbose_message("Warning",
"Safety backups (every minute) are\n"
"disabled because Grafx2 is running\n"
"from a read-only device, or other\n"
"instances are running.");
break;
case 0:
switch (file_in_command_line)
{
case 0:
if (Config.Opening_message)
Button_Message_initial();
break;
case 2:
// Load this file
Init_context_layered_image(&context, spare_filename, spare_directory);
Load_image(&context);
Destroy_context(&context);
Redraw_layered_image();
End_of_modification();
Button_Page();
// no break ! proceed with the other file now
case 1:
Init_context_layered_image(&context, main_filename, main_directory);
Load_image(&context);
Destroy_context(&context);
Redraw_layered_image();
End_of_modification();
Hide_cursor();
Compute_optimal_menu_colors(Main_palette);
Display_all_screen();
Display_menu();
Display_cursor();
Resolution_in_command_line = 0;
break;
default:
break;
}
}
Allow_drag_and_drop(1);
return(1);
}
// ------------------------- Fermeture du programme --------------------------
void Program_shutdown(void)
{
int return_code;
// Windows only: Recover the window position.
#if defined(__WIN32__)
{
RECT r;
static SDL_SysWMinfo pInfo;
SDL_GetWMInfo(&pInfo);
GetWindowRect(pInfo.window, &r);
Config.Window_pos_x = r.left;
Config.Window_pos_y = r.top;
}
#else
// All other targets: irrelevant dimensions.
// Do not attempt to force them back on next program run.
Config.Window_pos_x = 9999;
Config.Window_pos_y = 9999;
#endif
// Remove the safety backups, this is normal exit
Delete_safety_backups();
// On libère le buffer de gestion de lignes
free(Horizontal_line_buffer);
Horizontal_line_buffer = NULL;
// On libère le pinceau spécial
free(Paintbrush_sprite);
Paintbrush_sprite = NULL;
// On libère les différents écrans virtuels et brosse:
free(Brush);
Brush = NULL;
Set_number_of_backups(0);
// Free the skin (Gui graphics) data
free(Gfx);
Gfx=NULL;
// On prend bien soin de passer dans le répertoire initial:
if (chdir(Initial_directory)!=-1)
{
// On sauvegarde les données dans le .CFG et dans le .INI
if (Config.Auto_save)
{
return_code=Save_CFG();
if (return_code)
Error(return_code);
return_code=Save_INI(&Config);
if (return_code)
Error(return_code);
}
}
else
Error(ERROR_MISSING_DIRECTORY);
SDL_Quit();
#if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__)
chdir("/usr/gp2x");
execl("/usr/gp2x/gp2xmenu", "/usr/gp2x/gp2xmenu", NULL);
#endif
}
// -------------------------- Procédure principale ---------------------------
int main(int argc,char * argv[])
{
if(!Init_program(argc,argv))
{
Program_shutdown();
return 0;
}
Main_handler();
Program_shutdown();
return 0;
}

View File

@@ -0,0 +1,880 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#include <SDL.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <math.h>
#include "struct.h"
#include "sdlscreen.h"
#include "global.h"
#include "errors.h"
#include "buttons.h"
#include "engine.h"
#include "misc.h"
#include "keyboard.h"
#include "sdlscreen.h"
#include "windows.h"
#include "palette.h"
#include "input.h"
#include "graph.h"
#include "pages.h"
///Count used palette indexes in the whole picture
///Return the total number of different colors
///Fill in "usage" with the count for each color
word Count_used_colors(dword* usage)
{
int nb_pixels = 0;
Uint8* current_pixel;
Uint8 color;
word nb_colors = 0;
int i;
int layer;
for (i = 0; i < 256; i++) usage[i]=0;
// Compute total number of pixels in the picture
nb_pixels = Main_image_height * Main_image_width;
// For each layer
for (layer = 0; layer < Main_backups->Pages->Nb_layers; layer++)
{
current_pixel = Main_backups->Pages->Image[layer];
// For each pixel in picture
for (i = 0; i < nb_pixels; i++)
{
color=*current_pixel; // get color in picture for this pixel
usage[color]++; // add it to the counter
// go to next pixel
current_pixel++;
}
}
// count the total number of unique used colors
for (i = 0; i < 256; i++)
{
if (usage[i]!=0)
nb_colors++;
}
return nb_colors;
}
/// Same as ::Count_used_colors, but use a block screen memory instead of
/// picture data. Used to count colors in the loading screen.
word Count_used_colors_screen_area(dword* usage, word start_x, word start_y,
word width, word height)
{
Uint8 color;
word x, y;
word nb_colors = 0;
int i;
// Init usage table
for (i = 0; i < 256; i++) usage[i]=0;
// For each pixel in screen area
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
// Get color in screen memory
color=*(Screen_pixels+((start_x + x)+(start_y + y) * Screen_width
* Pixel_height) * Pixel_width);
usage[color]++; //Un point de plus pour cette couleur
}
}
//On va maintenant compter dans la table les couleurs utilisées:
for (i = 0; i < 256; i++)
{
if (usage[i]!=0)
nb_colors++;
}
return nb_colors;
}
/// Same as ::Count_used_colors, but for a given rectangle in the picture only.
/// Used bu the C64 block constraint checker.
word Count_used_colors_area(dword* usage, word start_x, word start_y,
word width, word height)
{
Uint8 color;
word x, y;
word nb_colors = 0;
int i;
// Init usage table
for (i = 0; i < 256; i++) usage[i]=0;
// On parcourt l'écran courant pour compter les utilisations des couleurs
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
// Get color from picture
color=*(Main_screen+((start_x + x)+(start_y + y)*Main_image_width));
usage[color]++; //Un point de plus pour cette couleur
}
}
//On va maintenant compter dans la table les couleurs utilisées:
for (i = 0; i < 256; i++)
{
if (usage[i]!=0)
nb_colors++;
}
return nb_colors;
}
void Set_palette(T_Palette palette)
{
register int i;
SDL_Color PaletteSDL[256];
for(i=0;i<256;i++)
{
PaletteSDL[i].r=(palette[i].R=Round_palette_component(palette[i].R));
PaletteSDL[i].g=(palette[i].G=Round_palette_component(palette[i].G));
PaletteSDL[i].b=(palette[i].B=Round_palette_component(palette[i].B));
}
SDL_SetPalette(Screen_SDL, SDL_PHYSPAL | SDL_LOGPAL, PaletteSDL,0,256);
}
void Set_color(byte color, byte red, byte green, byte blue)
{
SDL_Color comp;
comp.r=red;
comp.g=green;
comp.b=blue;
SDL_SetPalette(Screen_SDL, SDL_PHYSPAL | SDL_LOGPAL, &comp, color, 1);
}
void Wait_end_of_click(void)
{
// On désactive tous les raccourcis clavier
while(Mouse_K)
Get_input(20);
}
void Clear_current_image_with_stencil(byte color, byte * stencil)
//Effacer l'image courante avec une certaine couleur en mode Stencil
{
int nb_pixels=0; //ECX
//al=color
//edi=Screen_pixels
byte* pixel=Main_backups->Pages->Image[Main_current_layer];
int i;
nb_pixels=Main_image_height*Main_image_width;
for(i=0;i<nb_pixels;i++)
{
if (stencil[*pixel]==0)
*pixel=color;
pixel++;
}
}
void Clear_current_image(byte color)
// Effacer l'image courante avec une certaine couleur
{
memset(
Main_backups->Pages->Image[Main_current_layer],
color ,
Main_image_width * Main_image_height
);
}
void Init_chrono(dword delay)
// Démarrer le chrono
{
Timer_delay = delay;
Timer_start = SDL_GetTicks()/55;
return;
}
void Pixel_in_brush (word x, word y, byte color)
{
*(Brush + y * Brush_width + x)=color;
}
byte Read_pixel_from_brush (word x, word y)
{
return *(Brush + y * Brush_width + x);
}
void Replace_a_color(byte old_color, byte new_color)
{
word x;
word y;
// Update all pixels
for (y=0; y<Main_image_height; y++)
for (x=0; x<Main_image_width; x++)
if (Read_pixel_from_current_layer(x,y) == old_color)
Pixel_in_current_screen(x,y,new_color,0);
Update_rect(0,0,0,0); // On peut TOUT a jour
// C'est pas un problème car il n'y a pas de preview
}
// FIXME: move to graph.c, it's the only caller
void Ellipse_compute_limites(short horizontal_radius,short vertical_radius)
{
Ellipse_horizontal_radius_squared =
(long)horizontal_radius * horizontal_radius;
Ellipse_vertical_radius_squared =
(long)vertical_radius * vertical_radius;
Ellipse_limit = (qword)Ellipse_horizontal_radius_squared * Ellipse_vertical_radius_squared;
}
// FIXME: move to graph.c, it's the only caller
byte Pixel_in_ellipse(void)
{
qword ediesi = (qword)Ellipse_cursor_X * Ellipse_cursor_X * Ellipse_vertical_radius_squared +
(qword)Ellipse_cursor_Y * Ellipse_cursor_Y * Ellipse_horizontal_radius_squared;
if((ediesi) <= Ellipse_limit) return 255;
return 0;
}
// FIXME: move to graph.c, it's the only caller
byte Pixel_in_circle(void)
{
if(Circle_cursor_X * Circle_cursor_X +
Circle_cursor_Y * Circle_cursor_Y <= Circle_limit)
return 255;
return 0;
}
void Copy_part_of_image_to_another(byte * source,word source_x,word source_y,word width,word height,word source_width,byte * dest,word dest_x,word dest_y,word destination_width)
{
// ESI = adresse de la source en (S_Pox_X,source_y)
byte* esi = source + source_y * source_width + source_x;
// EDI = adresse de la destination (dest_x,dest_y)
byte* edi = dest + dest_y * destination_width + dest_x;
int line;
// Pour chaque ligne
for (line=0;line < height; line++)
{
memcpy(edi,esi,width);
// Passe à la ligne suivante
esi+=source_width;
edi+=destination_width;
}
}
byte Read_pixel_from_spare_screen(word x,word y)
{
// return *(Spare_screen+y*Spare_image_width+x);
// Clipping is required as this can be called with coordinates from main image
// (can be a bigger or smaller image)
if (x>=Spare_image_width || y>=Spare_image_height)
return Spare_backups->Pages->Transparent_color;
#ifndef NOLAYERS
return *(Spare_visible_image.Image + y*Spare_image_width + x);
#else
return *(Spare_backups->Pages->Image[Spare_current_layer] + y*Spare_image_width + x);
#endif
}
void Rotate_90_deg_lowlevel(byte * source, byte * dest, short width, short height)
{
word x,y;
for(y=0;y<height;y++)
{
for(x=0;x<width;x++)
{
*(dest+height*(width-1-x)+y)=*source;
source++;
}
}
}
void Rotate_270_deg_lowlevel(byte * source, byte * dest, short width, short height)
{
word x,y;
for(y=0;y<height;y++)
{
for(x=0;x<width;x++)
{
*(dest+(height-1-y)+x*height)=*source;
source++;
}
}
}
// Replace une couleur par une autre dans un buffer
void Remap_general_lowlevel(byte * conversion_table,byte * in_buffer, byte *out_buffer,short width,short height,short buffer_width)
{
int dx,cx;
// Pour chaque ligne
for(dx=height;dx>0;dx--)
{
// Pour chaque pixel
for(cx=width;cx>0;cx--)
{
*out_buffer = conversion_table[*in_buffer];
in_buffer++;
out_buffer++;
}
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)
{
byte* src=start_y*image_width+start_x+Main_backups->Pages->Image[Main_current_layer]; //Adr départ image (ESI)
byte* dest=Brush_original_pixels; //Adr dest brosse (EDI)
int dx;
for (dx=Brush_height;dx!=0;dx--)
//Pour chaque ligne
{
// On fait une copie de la ligne
memcpy(dest,src,Brush_width);
// On passe à la ligne suivante
src+=image_width;
dest+=Brush_width;
}
}
byte Read_pixel_from_feedback_screen (word x,word y)
{
return *(FX_feedback_screen+y*Main_image_width+x);
}
dword Round_div(dword numerator,dword divisor)
{
return numerator/divisor;
}
byte Effect_sieve(word x,word y)
{
return Sieve[x % Sieve_width][y % Sieve_height];
}
void Replace_colors_within_limits(byte * replace_table)
{
int y;
int x;
byte* pixel;
// Pour chaque ligne :
for(y = Limit_top;y <= Limit_bottom; y++)
{
// Pour chaque pixel sur la ligne :
for (x = Limit_left;x <= Limit_right;x ++)
{
pixel = Main_backups->Pages->Image[Main_current_layer]+y*Main_image_width+x;
*pixel = replace_table[*pixel];
}
}
}
byte Read_pixel_from_backup_screen (word x,word y)
{
return *(Screen_backup + x + Main_image_width * y);
}
void Palette_256_to_64(T_Palette palette)
{
int i;
for(i=0;i<256;i++)
{
palette[i].R = palette[i].R >> 2;
palette[i].G = palette[i].G >> 2;
palette[i].B = palette[i].B >> 2;
}
}
void Palette_64_to_256(T_Palette palette)
{
int i;
for(i=0;i<256;i++)
{
palette[i].R = (palette[i].R << 2)|(palette[i].R >> 4);
palette[i].G = (palette[i].G << 2)|(palette[i].G >> 4);
palette[i].B = (palette[i].B << 2)|(palette[i].B >> 4);
}
}
byte Effect_interpolated_colorize (word x,word y,byte color)
{
// factor_a = 256*(100-Colorize_opacity)/100
// factor_b = 256*( Colorize_opacity)/100
//
// (Couleur_dessous*factor_a+color*facteur_B)/256
//
// On place dans ESI 3*Couleur_dessous ( = position de cette couleur dans la
// palette des teintes) et dans EDI, 3*color.
byte color_under = Read_pixel_from_feedback_screen(x,y);
byte blue_under=Main_palette[color_under].B;
byte blue=Main_palette[color].B;
byte green_under=Main_palette[color_under].G;
byte green=Main_palette[color].G;
byte red_under=Main_palette[color_under].R;
byte red=Main_palette[color].R;
// On récupère les 3 composantes RVB
// blue
blue = (Factors_inv_table[blue]
+ Factors_table[blue_under]) / 256;
green = (Factors_inv_table[green]
+ Factors_table[green_under]) / 256;
red = (Factors_inv_table[red]
+ Factors_table[red_under]) / 256;
return Best_color(red,green,blue);
}
byte Effect_additive_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;
byte blue=Main_palette[color].B;
byte green=Main_palette[color].G;
byte red=Main_palette[color].R;
return Best_color(
red>red_under?red:red_under,
green>green_under?green:green_under,
blue>blue_under?blue:blue_under);
}
byte Effect_substractive_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;
byte blue=Main_palette[color].B;
byte green=Main_palette[color].G;
byte red=Main_palette[color].R;
return Best_color(
red<red_under?red:red_under,
green<green_under?green:green_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)
{
if((SDL_GetTicks()/55)-Timer_delay>Timer_start) Timer_state=1;
}
void Flip_Y_lowlevel(byte *src, short width, short height)
{
// ESI pointe sur la partie haute de la brosse
// EDI sur la partie basse
byte* ESI = src ;
byte* EDI = src + (height - 1) *width;
byte tmp;
word cx;
while(ESI < EDI)
{
// Il faut inverser les lignes pointées par ESI et
// EDI ("Brush_width" octets en tout)
for(cx = width;cx>0;cx--)
{
tmp = *ESI;
*ESI = *EDI;
*EDI = tmp;
ESI++;
EDI++;
}
// On change de ligne :
// ESI pointe déjà sur le début de la ligne suivante
// EDI pointe sur la fin de la ligne en cours, il
// doit pointer sur le début de la précédente...
EDI -= 2 * width; // On recule de 2 lignes
}
}
void Flip_X_lowlevel(byte *src, short width, short height)
{
// ESI pointe sur la partie gauche et EDI sur la partie
// droite
byte* ESI = src;
byte* EDI = src + width - 1;
byte* line_start;
byte* line_end;
byte tmp;
word cx;
while(ESI<EDI)
{
line_start = ESI;
line_end = EDI;
// On échange par colonnes
for(cx=height;cx>0;cx--)
{
tmp=*ESI;
*ESI=*EDI;
*EDI=tmp;
EDI+=width;
ESI+=width;
}
// On change de colonne
// ESI > colonne suivante
// EDI > colonne précédente
ESI = line_start + 1;
EDI = line_end - 1;
}
}
// Rotate a pixel buffer 180º on itself.
void Rotate_180_deg_lowlevel(byte *src, short width, short height)
{
// ESI pointe sur la partie supérieure de la brosse
// EDI pointe sur la partie basse
byte* ESI = src;
byte* EDI = src + height*width - 1;
// EDI pointe sur le dernier pixel de la derniere ligne
byte tmp;
word cx;
// In case of odd height, the algorithm in this function would
// miss the middle line, so we do it this way:
if (height & 1)
{
Flip_X_lowlevel(src, width, height);
Flip_Y_lowlevel(src, width, height);
return;
}
while(ESI < EDI)
{
// On échange les deux lignes pointées par EDI et
// ESI (Brush_width octets)
// En même temps, on échange les pixels, donc EDI
// pointe sur la FIN de sa ligne
for(cx=width;cx>0;cx--)
{
tmp = *ESI;
*ESI = *EDI;
*EDI = tmp;
EDI--; // Attention ici on recule !
ESI++;
}
}
}
void Rescale(byte *src_buffer, short src_width, short src_height, byte *dst_buffer, short dst_width, short dst_height, short x_flipped, short y_flipped)
{
int offset,line,column;
int x_pos_in_brush; // Position courante dans l'ancienne brosse
int y_pos_in_brush;
int delta_x_in_brush; // "Vecteur incrémental" du point précédent
int delta_y_in_brush;
int initial_x_pos; // Position X de début de parcours de ligne
// Calcul du "vecteur incrémental":
delta_x_in_brush=(src_width<<16) * (x_flipped?-1:1) / (dst_width);
delta_y_in_brush=(src_height<<16) * (y_flipped?-1:1) / (dst_height);
offset=0;
// Calcul de la valeur initiale de y_pos:
if (y_flipped)
y_pos_in_brush=(src_height<<16)-1; // Inversion en Y de la brosse
else
y_pos_in_brush=0; // Pas d'inversion en Y de la brosse
// Calcul de la valeur initiale de x_pos pour chaque ligne:
if (x_flipped)
initial_x_pos = (src_width<<16)-1; // Inversion en X de la brosse
else
initial_x_pos = 0; // Pas d'inversion en X de la brosse
// Pour chaque ligne
for (line=0;line<dst_height;line++)
{
// On repart du début de la ligne:
x_pos_in_brush=initial_x_pos;
// Pour chaque colonne:
for (column=0;column<dst_width;column++)
{
// On copie le pixel:
dst_buffer[offset]=*(src_buffer + (x_pos_in_brush>>16) + (y_pos_in_brush>>16)*src_width);
// On passe à la colonne de brosse suivante:
x_pos_in_brush+=delta_x_in_brush;
// On passe au pixel suivant de la nouvelle brosse:
offset++;
}
// On passe à la ligne de brosse suivante:
y_pos_in_brush+=delta_y_in_brush;
}
}
void Scroll_picture(byte * main_src, byte * main_dest, short x_offset,short y_offset)
{
byte* src = main_src; //source de la copie
byte* dest = main_dest + y_offset * Main_image_width + x_offset;
const word length = Main_image_width - x_offset; // Nombre de pixels à copier à droite
word y;
for(y = Main_image_height - y_offset;y>0;y--)
{
// Pour chaque ligne
memcpy(dest,src,length);
memcpy(dest - x_offset,src+length,x_offset);
// On passe à la ligne suivante
dest += Main_image_width;
src += Main_image_width;
}
// On vient de faire le traitement pour otutes les lignes au-dessous de y_offset
// Maintenant on traite celles au dessus
dest = x_offset + main_dest;
for(y = y_offset;y>0;y--)
{
memcpy(dest,src,length);
memcpy(dest - x_offset,src+length,x_offset);
dest += Main_image_width;
src += Main_image_width;
}
Update_rect(0,0,0,0);
}
void Zoom_a_line(byte* original_line, byte* zoomed_line,
word factor, word width
)
{
byte color;
word x;
// Pour chaque pixel
for(x=0;x<width;x++){
color = *original_line;
memset(zoomed_line,color,factor);
zoomed_line+=factor;
original_line++;
}
}
/*############################################################################*/
#if defined(__WIN32__)
#define _WIN32_WINNT 0x0500
#include <windows.h>
#elif defined(__macosx__) || defined(__FreeBSD__) || defined(__NetBSD__)
#include <sys/sysctl.h>
#elif defined(__BEOS__) || defined(__HAIKU__)
// sysinfo not implemented
#elif defined(__AROS__) || defined(__amigaos4__) || defined(__MORPHOS__) || defined(__amigaos__)
#include <proto/exec.h>
#elif defined(__MINT__)
#include <mint/osbind.h>
#include <mint/sysbind.h>
#elif defined(__SKYOS__)
#include <skyos/sysinfo.h>
#else
#include <sys/sysinfo.h> // sysinfo() for free RAM
#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
unsigned long Memory_free(void)
{
// Memory is no longer relevant. If there is ANY problem or doubt here,
// you can simply return 10*1024*1024 (10Mb), to make the "Pages"something
// memory allocation functions happy.
// However, it is still a good idea to make a proper function if you can...
// If Grafx2 thinks the memory is full, weird things may happen. And if memory
// ever becomes full and you're still saying there are 10MB free here, the
// program will crash without saving any picture backup ! You've been warned...
#if defined(__WIN32__)
MEMORYSTATUS mstt;
mstt.dwLength = sizeof(MEMORYSTATUS);
GlobalMemoryStatus(&mstt);
return mstt.dwAvailPhys;
#elif defined(__macosx__) || defined(__FreeBSD__) || defined(__NetBSD__)
int mib[2];
int maxmem;
size_t len;
mib[0] = CTL_HW;
mib[1] = HW_USERMEM;
len = sizeof(maxmem);
sysctl(mib,2,&maxmem,&len,NULL,0);
return maxmem;
#elif defined(__BEOS__) || defined(__HAIKU__) || defined(__SKYOS__) || defined(__amigaos4__) || defined(__TRU64__) || defined(ANDROID)
// No <sys/sysctl.h> on BeOS or Haiku
// AvailMem is misleading on os4 (os4 caches stuff in memory that you can still allocate)
#warning "There is missing code there for your platform ! please check and correct :)"
return 10*1024*1024;
#elif defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
return AvailMem(MEMF_ANY);
#else
struct sysinfo info;
sysinfo(&info);
return info.freeram*info.mem_unit;
#endif
}
#endif
// Arrondir un nombre réel à la valeur entière la plus proche
// TODO : this should probably be replaced with round() from C99...
short Round(float value)
{
short temp=value;
if (value>=0)
{ if ((value-temp)>= 0.5) temp++; }
else
{ if ((value-temp)<=-0.5) temp--; }
return temp;
}
// Arrondir le résultat d'une division à la valeur entière supérieure
short Round_div_max(short numerator,short divisor)
{
if (!(numerator % divisor))
return (numerator/divisor);
else
return (numerator/divisor)+1;
}
// Retourne le minimum entre deux nombres
int Min(int a,int b)
{
return (a<b)?a:b;
}
// Retourne le maximum entre deux nombres
int Max(int a,int b)
{
return (a>b)?a:b;
}
/* Round number n to d decimal points */
double Fround(double n, unsigned d)
{
double exp;
exp = pow(10.0, d);
return floor(n * exp + 0.5) / exp;
}
// Fonction retournant le libellé d'une mode (ex: " 320x200")
char * Mode_label(int mode)
{
static char str[24];
if (! Video_mode[mode].Fullscreen)
return "window";
sprintf(str, "%dx%d", Video_mode[mode].Width, Video_mode[mode].Height);
return str;
}
// Trouve un mode video à partir d'une chaine: soit "window",
// soit de la forme "320x200"
// Renvoie -1 si la chaine n'est pas convertible
int Convert_videomode_arg(const char *argument)
{
// Je suis paresseux alors je vais juste tester les libellés
int mode_index;
for (mode_index=0; mode_index<Nb_video_modes; mode_index++)
// Attention les vieilles fonctions de lecture .ini mettent tout en MAJUSCULE.
if (!strcasecmp(Mode_label(mode_index), argument) && (Video_mode[mode_index].State &128) ==0)
return mode_index;
return -1;
}

View File

@@ -0,0 +1,167 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 misc.h
/// Miscellanous unsorted functions.
//////////////////////////////////////////////////////////////////////////////
#include "struct.h"
#define SWAP_BYTES(a,b) { byte c=a; a=b; b=c;}
#define SWAP_WORDS(a,b) { word c=a; a=b; b=c;}
#define SWAP_DWORDS(a,b) { dword c=a; a=b; b=c;}
#define SWAP_SHORTS(a,b) { short c=a; a=b; b=c;}
#define SWAP_FLOATS(a,b) { float 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 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 Wait_end_of_click(void);
void Set_color(byte color, byte red, byte green, byte blue);
void Set_palette(T_Palette palette);
void Palette_256_to_64(T_Palette palette);
void Palette_64_to_256(T_Palette palette);
void Clear_current_image(byte color);
void Clear_current_image_with_stencil(byte color, byte * stencil);
dword Round_div(dword numerator,dword divisor);
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_screen_area(dword* usage, word start_x, word start_y, word width, word height);
void Pixel_in_brush (word x,word y,byte color);
byte Read_pixel_from_spare_screen(word x,word y);
byte Read_pixel_from_backup_screen (word x,word y);
byte Read_pixel_from_feedback_screen (word x,word y);
byte Read_pixel_from_brush (word x,word y);
void Ellipse_compute_limites(short horizontal_radius,short vertical_radius);
// Calcule les valeurs suivantes en fonction des deux paramètres:
//
// Ellipse_vertical_radius_squared
// Ellipse_horizontal_radius_squared
// Ellipse_Limit_High
// Ellipse_Limit_Low
byte Pixel_in_ellipse(void);
// Indique si le pixel se trouvant à Ellipse_cursor_X pixels
// (Ellipse_cursor_X>0 = à droite, Ellipse_cursor_X<0 = à gauche) et à
// Ellipse_cursor_Y pixels (Ellipse_cursor_Y>0 = en bas,
// Ellipse_cursor_Y<0 = en haut) du centre se trouve dans l'ellipse en
// cours.
byte Pixel_in_circle(void);
// Indique si le pixel se trouvant à Circle_cursor_X pixels
// (Circle_cursor_X>0 = à droite, Circle_cursor_X<0 = à gauche) et à
// Circle_cursor_Y pixels (Circle_cursor_Y>0 = en bas,
// Circle_cursor_Y<0 = en haut) du centre se trouve dans le cercle en
// cours.
// Gestion du chrono dans les fileselects
void Init_chrono(dword delay);
void Check_timer(void);
void Replace_a_color(byte old_color, byte New_color);
void Replace_colors_within_limits(byte * replace_table);
byte Effect_interpolated_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_alpha_colorize(word x,word y,byte color);
byte Effect_sieve(word x,word y);
///
/// Inverts a pixel buffer, according to a horizontal axis.
/// @param src Pointer to the pixel buffer to process.
/// @param width Width of the buffer.
/// @param height Height of the buffer.
void Flip_Y_lowlevel(byte *src, short width, short height);
///
/// Inverts a pixel buffer, according to a vertical axis.
/// @param src Pointer to the pixel buffer to process.
/// @param width Width of the buffer.
/// @param height Height of the buffer.
void Flip_X_lowlevel(byte *src, short width, short height);
///
/// Rotate a pixel buffer by 90 degrees, clockwise.
/// @param source Source pixel buffer.
/// @param dest Destination pixel buffer.
/// @param width Width of the original buffer (height of the destination one).
/// @param height Height of the original buffer (width of the destination one).
void Rotate_90_deg_lowlevel(byte * source, byte * dest, short width, short height);
///
/// Rotate a pixel buffer by 90 degrees, counter-clockwise.
/// @param source Source pixel buffer.
/// @param dest Destination pixel buffer.
/// @param width Width of the original buffer (height of the destination one).
/// @param height Height of the original buffer (width of the destination one).
void Rotate_270_deg_lowlevel(byte * source, byte * dest, short width, short height);
///
/// Rotate a pixel buffer by 180 degrees.
/// @param src The pixel buffer (source and destination).
/// @param width Width of the buffer.
/// @param height Height of the buffer.
void Rotate_180_deg_lowlevel(byte *src, short width, short height);
///
/// Copies an image to another, rescaling it and optionally flipping it.
/// @param src_buffer Original image (address of first byte)
/// @param src_width Original image's width in pixels
/// @param src_height Original image's height in pixels
/// @param dst_buffer Destination image (address of first byte)
/// @param dst_width Destination image's width in pixels
/// @param dst_height Destination image's height in pixels
/// @param x_flipped Boolean, true to flip the image horizontally
/// @param y_flipped Boolean, true to flip the image vertically
void Rescale(byte *src_buffer, short src_width, short src_height, byte *dst_buffer, short dst_width, short dst_height, short x_flipped, short y_flipped);
void Zoom_a_line(byte * original_line,byte * zoomed_line,word factor,word width);
void Copy_part_of_image_to_another(byte * source,word source_x,word source_y,word width,word height,word source_width,byte * dest,word dest_x,word dest_y,word destination_width);
// -- Gestion du chrono --
byte Timer_state; // State du chrono: 0=Attente d'un Xème de seconde
// 1=Il faut afficher la preview
// 2=Plus de chrono à gerer pour l'instant
dword Timer_delay; // Nombre de 18.2ème de secondes demandés
dword Timer_start; // Heure de départ du chrono
byte New_preview_is_needed; // Booléen "Il faut relancer le chrono de preview"
unsigned long Memory_free(void);
#define Num2str(a,b,c) sprintf(b,"%*lu",c,(long)(a))
#define Dec2str(a,b,c) sprintf(b,"%.*f",c,(double)(a))
short Round(float value);
short Round_div_max(short numerator,short divisor);
/* round number n to d decimal points */
double Fround(double n, unsigned d);
int Min(int a,int b);
int Max(int a,int b);
char* Mode_label(int mode);
int Convert_videomode_arg(const char *argument);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,934 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* mountlist.c -- return a list of mounted file systems
Copyright (C) 1991, 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
// This file is not used on some platforms, so don't do anything for them
#if(!defined(__WIN32__))&&(!defined(__amigaos4__))&&(!defined(__AROS__))&&(!defined(__MORPHOS__))&&(!defined(__amigaos__))
// We don't use autoconf and all that in grafx2, so let's do the config here ...
#if defined(__macosx__) || defined(__FreeBSD__) // MacOS X is POSIX compliant
#define MOUNTED_GETMNTINFO
#if defined(__macosx__)
#include <sys/types.h>
#endif
#elif defined(__NetBSD__)
#define MOUNTED_GETMNTINFO2
#elif defined(__BEOS__) || defined(__HAIKU__)
#define MOUNTED_FS_STAT_DEV
#elif defined(__TRU64__)
#define MOUNTED_GETFSSTAT 1
#define HAVE_SYS_MOUNT_H 1
#include <sys/types.h>
#elif defined(__SKYOS__)||defined(ANDROID)
#warning "Your platform is missing some specific code here ! please check and fix :)"
#else
#define MOUNTED_GETMNTENT1
#endif
#define _XOPEN_SOURCE 500
// --- END GRAFX2 CUSTOM CONFIG ---
#include "mountlist.h"
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#if HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
#if defined MOUNTED_GETFSSTAT /* OSF_1 and Darwin1.3.x */
# if HAVE_SYS_UCRED_H
# include <grp.h> /* needed on OSF V4.0 for definition of NGROUPS,
NGROUPS is used as an array dimension in ucred.h */
# include <sys/ucred.h> /* needed by powerpc-apple-darwin1.3.7 */
# endif
# if HAVE_SYS_MOUNT_H
# include <sys/mount.h>
# endif
# if HAVE_SYS_FS_TYPES_H
# include <sys/fs_types.h> /* needed by powerpc-apple-darwin1.3.7 */
# endif
# if HAVE_STRUCT_FSSTAT_F_FSTYPENAME
# define FS_TYPE(Ent) ((Ent).f_fstypename)
# else
# define FS_TYPE(Ent) mnt_names[(Ent).f_type]
# endif
#endif /* MOUNTED_GETFSSTAT */
#ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
# include <mntent.h>
# if !defined MOUNTED
# if defined _PATH_MOUNTED /* GNU libc */
# define MOUNTED _PATH_MOUNTED
# endif
# if defined MNT_MNTTAB /* HP-UX. */
# define MOUNTED MNT_MNTTAB
# endif
# if defined MNTTABNAME /* Dynix. */
# define MOUNTED MNTTABNAME
# endif
# endif
#endif
#ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
# include <sys/mount.h>
#endif
#ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */
# include <sys/statvfs.h>
#endif
#ifdef MOUNTED_GETMNT /* Ultrix. */
# include <sys/mount.h>
# include <sys/fs_types.h>
#endif
#ifdef MOUNTED_FS_STAT_DEV /* BeOS. */
# include <fs_info.h>
# include <dirent.h>
#endif
#ifdef MOUNTED_FREAD /* SVR2. */
# include <mnttab.h>
#endif
#ifdef MOUNTED_FREAD_FSTYP /* SVR3. */
# include <mnttab.h>
# include <sys/fstyp.h>
# include <sys/statfs.h>
#endif
#ifdef MOUNTED_LISTMNTENT
# include <mntent.h>
#endif
#ifdef MOUNTED_GETMNTENT2 /* SVR4. */
# include <sys/mnttab.h>
#endif
#ifdef MOUNTED_VMOUNT /* AIX. */
# include <fshelp.h>
# include <sys/vfs.h>
#endif
#ifdef DOLPHIN
/* So special that it's not worth putting this in autoconf. */
# undef MOUNTED_FREAD_FSTYP
# define MOUNTED_GETMNTTBL
#endif
#if HAVE_SYS_MNTENT_H
/* This is to get MNTOPT_IGNORE on e.g. SVR4. */
# include <sys/mntent.h>
#endif
#undef MNT_IGNORE
#if defined MNTOPT_IGNORE && defined HAVE_HASMNTOPT
# define MNT_IGNORE(M) hasmntopt ((M), MNTOPT_IGNORE)
#else
# define MNT_IGNORE(M) 0
#endif
#if USE_UNLOCKED_IO
# include "unlocked-io.h"
#endif
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif
/* The results of open() in this file are not used with fchdir,
therefore save some unnecessary work in fchdir.c. */
#undef open
#undef close
/* The results of opendir() in this file are not used with dirfd and fchdir,
therefore save some unnecessary work in fchdir.c. */
#undef opendir
#undef closedir
// gcc2 under haiku and beos don't like these macros for some reason.
// As they are not used there anyways, we remove them and everyone is happy.
#if !defined(__HAIKU__) && !defined(__BEOS__)
#ifndef ME_DUMMY
# define ME_DUMMY(Fs_name, Fs_type) \
(strcmp (Fs_type, "autofs") == 0 \
|| strcmp (Fs_type, "none") == 0 \
|| strcmp (Fs_type, "proc") == 0 \
|| strcmp (Fs_type, "subfs") == 0 \
|| strcmp (Fs_type, "sysfs") == 0 \
|| strcmp (Fs_type, "usbfs") == 0 \
|| strcmp (Fs_type, "devpts") == 0 \
|| strcmp (Fs_type, "tmpfs") == 0 \
/* for NetBSD 3.0 */ \
|| strcmp (Fs_type, "kernfs") == 0 \
/* for Irix 6.5 */ \
|| strcmp (Fs_type, "ignore") == 0 \
/* for MacOSX */ \
|| strcmp (Fs_type, "devfs") == 0 \
|| strcmp (Fs_type, "fdesc") == 0 \
|| strcmp (Fs_type, "nfs") == 0 \
|| strcmp (Fs_type, "volfs") == 0)
#endif
#ifndef ME_REMOTE
/* A file system is `remote' if its Fs_name contains a `:'
or if (it is of type (smbfs or cifs) and its Fs_name starts with `//'). */
# define ME_REMOTE(Fs_name, Fs_type) \
(strchr (Fs_name, ':') != NULL \
|| ((Fs_name)[0] == '/' \
&& (Fs_name)[1] == '/' \
&& (strcmp (Fs_type, "smbfs") == 0 \
|| strcmp (Fs_type, "cifs") == 0)))
#endif
#endif // HAIKU / BEOS
#ifdef MOUNTED_GETMNTINFO
# if ! HAVE_STRUCT_STATFS_F_FSTYPENAME
static char *
fstype_to_string (short int t)
{
switch (t)
{
# ifdef MOUNT_PC
case MOUNT_PC:
return "pc";
# endif
# ifdef MOUNT_MFS
case MOUNT_MFS:
return "mfs";
# endif
# ifdef MOUNT_LO
case MOUNT_LO:
return "lo";
# endif
# ifdef MOUNT_TFS
case MOUNT_TFS:
return "tfs";
# endif
# ifdef MOUNT_TMP
case MOUNT_TMP:
return "tmp";
# endif
# ifdef MOUNT_UFS
case MOUNT_UFS:
return "ufs" ;
# endif
# ifdef MOUNT_NFS
case MOUNT_NFS:
return "nfs" ;
# endif
# ifdef MOUNT_MSDOS
case MOUNT_MSDOS:
return "msdos" ;
# endif
# ifdef MOUNT_LFS
case MOUNT_LFS:
return "lfs" ;
# endif
# ifdef MOUNT_LOFS
case MOUNT_LOFS:
return "lofs" ;
# endif
# ifdef MOUNT_FDESC
case MOUNT_FDESC:
return "fdesc" ;
# endif
# ifdef MOUNT_PORTAL
case MOUNT_PORTAL:
return "portal" ;
# endif
# ifdef MOUNT_NULL
case MOUNT_NULL:
return "null" ;
# endif
# ifdef MOUNT_UMAP
case MOUNT_UMAP:
return "umap" ;
# endif
# ifdef MOUNT_KERNFS
case MOUNT_KERNFS:
return "kernfs" ;
# endif
# ifdef MOUNT_PROCFS
case MOUNT_PROCFS:
return "procfs" ;
# endif
# ifdef MOUNT_AFS
case MOUNT_AFS:
return "afs" ;
# endif
# ifdef MOUNT_CD9660
case MOUNT_CD9660:
return "cd9660" ;
# endif
# ifdef MOUNT_UNION
case MOUNT_UNION:
return "union" ;
# endif
# ifdef MOUNT_DEVFS
case MOUNT_DEVFS:
return "devfs" ;
# endif
# ifdef MOUNT_EXT2FS
case MOUNT_EXT2FS:
return "ext2fs" ;
# endif
default:
return "?";
}
}
# endif
static char *
fsp_to_string (const struct statfs *fsp)
{
# if HAVE_STRUCT_STATFS_F_FSTYPENAME
return (char *) (fsp->f_fstypename);
# else
return fstype_to_string (fsp->f_type);
# endif
}
#endif /* MOUNTED_GETMNTINFO */
#ifdef MOUNTED_VMOUNT /* AIX. */
static char *
fstype_to_string (int t)
{
struct vfs_ent *e;
e = getvfsbytype (t);
if (!e || !e->vfsent_name)
return "none";
else
return e->vfsent_name;
}
#endif /* MOUNTED_VMOUNT */
#ifdef __linux__
#define BROKEN __attribute__((unused))
#else
#define BROKEN
#endif
#if defined MOUNTED_GETMNTENT1 || defined MOUNTED_GETMNTENT2
/* Return the device number from MOUNT_OPTIONS, if possible.
Otherwise return (dev_t) -1. */
static dev_t
dev_from_mount_options (BROKEN char const *mount_options)
{
/* GNU/Linux allows file system implementations to define their own
meaning for "dev=" mount options, so don't trust the meaning
here. */
# ifndef __linux__
static char const dev_pattern[] = ",dev=";
char const *devopt = strstr (mount_options, dev_pattern);
if (devopt)
{
char const *optval = devopt + sizeof dev_pattern - 1;
char *optvalend;
unsigned long int dev;
errno = 0;
dev = strtoul (optval, &optvalend, 16);
if (optval != optvalend
&& (*optvalend == '\0' || *optvalend == ',')
&& ! (dev == ULONG_MAX && errno == ERANGE)
&& dev == (dev_t) dev)
return dev;
}
# endif
return -1;
}
#endif
/* Return a list of the currently mounted file systems, or NULL on error.
Add each entry to the tail of the list so that they stay in order.
If NEED_FS_TYPE is true, ensure that the file system type fields in
the returned list are valid. Otherwise, they might not be. */
struct mount_entry *
read_file_system_list (BROKEN bool need_fs_type)
{
struct mount_entry *mount_list;
struct mount_entry *me;
struct mount_entry **mtail = &mount_list;
#ifdef MOUNTED_LISTMNTENT
{
struct tabmntent *mntlist, *p;
struct mntent *mnt;
struct mount_entry *me;
/* the third and fourth arguments could be used to filter mounts,
but Crays doesn't seem to have any mounts that we want to
remove. Specifically, automount create normal NFS mounts.
*/
if (listmntent (&mntlist, KMTAB, NULL, NULL) < 0)
return NULL;
for (p = mntlist; p; p = p->next) {
mnt = p->ment;
me = xmalloc (sizeof *me);
me->me_devname = xstrdup (mnt->mnt_fsname);
me->me_mountdir = xstrdup (mnt->mnt_dir);
me->me_type = xstrdup (mnt->mnt_type);
me->me_type_malloced = 1;
me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
me->me_dev = -1;
*mtail = me;
mtail = &me->me_next;
}
freemntlist (mntlist);
}
#endif
#ifdef MOUNTED_GETMNTENT1 /* GNU/Linux, 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
{
struct mntent *mnt;
char *table = MOUNTED;
FILE *fp;
fp = setmntent (table, "r");
if (fp == NULL)
return NULL;
while ((mnt = getmntent (fp)))
{
me = malloc (sizeof *me);
me->me_devname = strdup (mnt->mnt_fsname);
me->me_mountdir = strdup (mnt->mnt_dir);
me->me_type = strdup (mnt->mnt_type);
me->me_type_malloced = 1;
me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
me->me_dev = dev_from_mount_options (mnt->mnt_opts);
/* Add to the linked list. */
*mtail = me;
mtail = &me->me_next;
}
if (endmntent (fp) == 0)
goto free_then_fail;
}
#endif /* MOUNTED_GETMNTENT1. */
#ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
{
struct statfs *fsp;
int entries;
entries = getmntinfo (&fsp, MNT_NOWAIT);
if (entries < 0)
return NULL;
for (; entries-- > 0; fsp++)
{
me = malloc (sizeof *me);
me->me_devname = strdup (fsp->f_mntfromname);
me->me_mountdir = strdup (fsp->f_mntonname);
#if defined(__macosx__)
me->me_type = fsp->f_fstypename;
#else
me->me_type = fsp->fs_typename;
#endif
me->me_type_malloced = 0;
me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
/* Add to the linked list. */
*mtail = me;
mtail = &me->me_next;
}
}
#endif /* MOUNTED_GETMNTINFO */
#ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */
{
struct statvfs *fsp;
int entries;
entries = getmntinfo (&fsp, MNT_NOWAIT);
if (entries < 0)
return NULL;
for (; entries-- > 0; fsp++)
{
me = malloc (sizeof *me);
me->me_devname = strdup (fsp->f_mntfromname);
me->me_mountdir = strdup (fsp->f_mntonname);
me->me_type = strdup (fsp->f_fstypename);
me->me_type_malloced = 1;
me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
/* Add to the linked list. */
*mtail = me;
mtail = &me->me_next;
}
}
#endif /* MOUNTED_GETMNTINFO2 */
#ifdef MOUNTED_GETMNT /* Ultrix. */
{
int offset = 0;
int val;
struct fs_data fsd;
while (errno = 0,
0 < (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
(char *) 0)))
{
me = xmalloc (sizeof *me);
me->me_devname = xstrdup (fsd.fd_req.devname);
me->me_mountdir = xstrdup (fsd.fd_req.path);
me->me_type = gt_names[fsd.fd_req.fstype];
me->me_type_malloced = 0;
me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
me->me_dev = fsd.fd_req.dev;
/* Add to the linked list. */
*mtail = me;
mtail = &me->me_next;
}
if (val < 0)
goto free_then_fail;
}
#endif /* MOUNTED_GETMNT. */
#if defined MOUNTED_FS_STAT_DEV /* BeOS */
{
/* The next_dev() and fs_stat_dev() system calls give the list of
all file systems, including the information returned by statvfs()
(fs type, total blocks, free blocks etc.), but without the mount
point. But on BeOS all file systems except / are mounted in the
rootfs, directly under /.
The directory name of the mount point is often, but not always,
identical to the volume name of the device.
We therefore get the list of subdirectories of /, and the list
of all file systems, and match the two lists. */
DIR *dirp;
struct rootdir_entry
{
char *name;
dev_t dev;
ino_t ino;
struct rootdir_entry *next;
};
struct rootdir_entry *rootdir_list;
struct rootdir_entry **rootdir_tail;
int32 pos;
dev_t dev;
fs_info fi;
/* All volumes are mounted in the rootfs, directly under /. */
rootdir_list = NULL;
rootdir_tail = &rootdir_list;
dirp = opendir ("/");
if (dirp)
{
struct dirent *d;
while ((d = readdir (dirp)) != NULL)
{
char *name;
struct stat statbuf;
if (strcmp (d->d_name, "..") == 0)
continue;
if (strcmp (d->d_name, ".") == 0)
name = strdup ("/");
else
{
name = malloc (1 + strlen (d->d_name) + 1);
name[0] = '/';
strcpy (name + 1, d->d_name);
}
if (lstat (name, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode))
{
struct rootdir_entry *re = malloc (sizeof *re);
re->name = name;
re->dev = statbuf.st_dev;
re->ino = statbuf.st_ino;
/* Add to the linked list. */
*rootdir_tail = re;
rootdir_tail = &re->next;
}
else
free (name);
}
closedir (dirp);
}
*rootdir_tail = NULL;
for (pos = 0; (dev = next_dev (&pos)) >= 0; )
if (fs_stat_dev (dev, &fi) >= 0)
{
/* Note: fi.dev == dev. */
struct rootdir_entry *re;
for (re = rootdir_list; re; re = re->next)
if (re->dev == fi.dev && re->ino == fi.root)
break;
me = malloc (sizeof *me);
me->me_devname = strdup (fi.device_name[0] != '\0' ? fi.device_name : fi.fsh_name);
me->me_mountdir = strdup (re != NULL ? re->name : fi.fsh_name);
me->me_type = strdup (fi.fsh_name);
me->me_type_malloced = 1;
me->me_dev = fi.dev;
me->me_dummy = 0;
me->me_remote = (fi.flags & B_FS_IS_SHARED) != 0;
/* Add to the linked list. */
*mtail = me;
mtail = &me->me_next;
}
*mtail = NULL;
while (rootdir_list != NULL)
{
struct rootdir_entry *re = rootdir_list;
rootdir_list = re->next;
free (re->name);
free (re);
}
}
#endif /* MOUNTED_FS_STAT_DEV */
#if defined MOUNTED_GETFSSTAT /* __alpha running OSF_1 */
{
int numsys, counter;
size_t bufsize;
struct statfs *stats;
numsys = getfsstat ((struct statfs *)0, 0L, MNT_NOWAIT);
if (numsys < 0)
return (NULL);
/*
if (SIZE_MAX / sizeof *stats <= numsys)
xalloc_die ();*/
bufsize = (1 + numsys) * sizeof *stats;
stats = malloc (bufsize);
numsys = getfsstat (stats, bufsize, MNT_NOWAIT);
if (numsys < 0)
{
free (stats);
return (NULL);
}
for (counter = 0; counter < numsys; counter++)
{
me = malloc (sizeof *me);
me->me_devname = strdup (stats[counter].f_mntfromname);
me->me_mountdir = strdup (stats[counter].f_mntonname);
//me->me_type = strdup (FS_TYPE (stats[counter]));
me->me_type_malloced = 1;
me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
/* Add to the linked list. */
*mtail = me;
mtail = &me->me_next;
}
free (stats);
}
#endif /* MOUNTED_GETFSSTAT */
#if defined MOUNTED_FREAD || defined MOUNTED_FREAD_FSTYP /* SVR[23]. */
{
struct mnttab mnt;
char *table = "/etc/mnttab";
FILE *fp;
fp = fopen (table, "r");
if (fp == NULL)
return NULL;
while (fread (&mnt, sizeof mnt, 1, fp) > 0)
{
me = xmalloc (sizeof *me);
# ifdef GETFSTYP /* SVR3. */
me->me_devname = xstrdup (mnt.mt_dev);
# else
me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6);
strcpy (me->me_devname, "/dev/");
strcpy (me->me_devname + 5, mnt.mt_dev);
# endif
me->me_mountdir = xstrdup (mnt.mt_filsys);
me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
me->me_type = "";
me->me_type_malloced = 0;
# ifdef GETFSTYP /* SVR3. */
if (need_fs_type)
{
struct statfs fsd;
char typebuf[FSTYPSZ];
if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
&& sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
{
me->me_type = xstrdup (typebuf);
me->me_type_malloced = 1;
}
}
# endif
me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
/* Add to the linked list. */
*mtail = me;
mtail = &me->me_next;
}
if (ferror (fp))
{
/* The last fread() call must have failed. */
int saved_errno = errno;
fclose (fp);
errno = saved_errno;
goto free_then_fail;
}
if (fclose (fp) == EOF)
goto free_then_fail;
}
#endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */
#ifdef MOUNTED_GETMNTTBL /* DolphinOS goes its own way. */
{
struct mntent **mnttbl = getmnttbl (), **ent;
for (ent=mnttbl;*ent;ent++)
{
me = xmalloc (sizeof *me);
me->me_devname = xstrdup ( (*ent)->mt_resource);
me->me_mountdir = xstrdup ( (*ent)->mt_directory);
me->me_type = xstrdup ((*ent)->mt_fstype);
me->me_type_malloced = 1;
me->me_dummy = ME_DUMMY (me->me_devname, me->me_type);
me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
/* Add to the linked list. */
*mtail = me;
mtail = &me->me_next;
}
endmnttbl ();
}
#endif
#ifdef MOUNTED_GETMNTENT2 /* SVR4. */
{
struct mnttab mnt;
char *table = MNTTAB;
FILE *fp;
int ret;
int lockfd = -1;
# if defined F_RDLCK && defined F_SETLKW
/* MNTTAB_LOCK is a macro name of our own invention; it's not present in
e.g. Solaris 2.6. If the SVR4 folks ever define a macro
for this file name, we should use their macro name instead.
(Why not just lock MNTTAB directly? We don't know.) */
# ifndef MNTTAB_LOCK
# define MNTTAB_LOCK "/etc/.mnttab.lock"
# endif
lockfd = open (MNTTAB_LOCK, O_RDONLY);
if (0 <= lockfd)
{
struct flock flock;
flock.l_type = F_RDLCK;
flock.l_whence = SEEK_SET;
flock.l_start = 0;
flock.l_len = 0;
while (fcntl (lockfd, F_SETLKW, &flock) == -1)
if (errno != EINTR)
{
int saved_errno = errno;
close (lockfd);
errno = saved_errno;
return NULL;
}
}
else if (errno != ENOENT)
return NULL;
# endif
errno = 0;
fp = fopen (table, "r");
if (fp == NULL)
ret = errno;
else
{
while ((ret = getmntent (fp, &mnt)) == 0)
{
me = xmalloc (sizeof *me);
me->me_devname = xstrdup (mnt.mnt_special);
me->me_mountdir = xstrdup (mnt.mnt_mountp);
me->me_type = xstrdup (mnt.mnt_fstype);
me->me_type_malloced = 1;
me->me_dummy = MNT_IGNORE (&mnt) != 0;
me->me_remote = ME_REMOTE (me->me_devname, me->me_type);
me->me_dev = dev_from_mount_options (mnt.mnt_mntopts);
/* Add to the linked list. */
*mtail = me;
mtail = &me->me_next;
}
ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1;
}
if (0 <= lockfd && close (lockfd) != 0)
ret = errno;
if (0 <= ret)
{
errno = ret;
goto free_then_fail;
}
}
#endif /* MOUNTED_GETMNTENT2. */
#ifdef MOUNTED_VMOUNT /* AIX. */
{
int bufsize;
char *entries, *thisent;
struct vmount *vmp;
int n_entries;
int i;
/* Ask how many bytes to allocate for the mounted file system info. */
if (mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize) != 0)
return NULL;
entries = xmalloc (bufsize);
/* Get the list of mounted file systems. */
n_entries = mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
if (n_entries < 0)
{
int saved_errno = errno;
free (entries);
errno = saved_errno;
return NULL;
}
for (i = 0, thisent = entries;
i < n_entries;
i++, thisent += vmp->vmt_length)
{
char *options, *ignore;
vmp = (struct vmount *) thisent;
me = xmalloc (sizeof *me);
if (vmp->vmt_flags & MNT_REMOTE)
{
char *host, *dir;
me->me_remote = 1;
/* Prepend the remote dirname. */
host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
dir = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
me->me_devname = xmalloc (strlen (host) + strlen (dir) + 2);
strcpy (me->me_devname, host);
strcat (me->me_devname, ":");
strcat (me->me_devname, dir);
}
else
{
me->me_remote = 0;
me->me_devname = xstrdup (thisent +
vmp->vmt_data[VMT_OBJECT].vmt_off);
}
me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype));
me->me_type_malloced = 1;
options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off;
ignore = strstr (options, "ignore");
me->me_dummy = (ignore
&& (ignore == options || ignore[-1] == ',')
&& (ignore[sizeof "ignore" - 1] == ','
|| ignore[sizeof "ignore" - 1] == '\0'));
me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want. */
/* Add to the linked list. */
*mtail = me;
mtail = &me->me_next;
}
free (entries);
}
#endif /* MOUNTED_VMOUNT. */
*mtail = NULL;
return mount_list;
free_then_fail:
{
int saved_errno = errno;
*mtail = NULL;
while (mount_list)
{
me = mount_list->me_next;
free (mount_list->me_devname);
free (mount_list->me_mountdir);
if (mount_list->me_type_malloced)
free (mount_list->me_type);
free (mount_list);
mount_list = me;
}
errno = saved_errno;
return NULL;
}
}
#endif

View File

@@ -0,0 +1,54 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* mountlist.h -- declarations for list of mounted file systems
Copyright (C) 1991, 1992, 1998, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
//////////////////////////////////////////////////////////////////////////////
///@file mountlist.h
/// A function to enumerate the mounting points in the filesystem.
/// Used to display them in fileselectors.
//////////////////////////////////////////////////////////////////////////////
#ifndef MOUNTLIST_H_
# define MOUNTLIST_H_
#if !defined(__VBCC__)
# include <stdbool.h>
#else
#define bool char
#endif
#include <sys/types.h>
/* A mount table entry. */
struct mount_entry
{
char *me_devname; /* Device node name, including "/dev/". */
char *me_mountdir; /* Mount point directory name. */
char *me_type; /* "nfs", "4.2", etc. */
dev_t me_dev; /* Device number of me_mountdir. */
unsigned int me_dummy : 1; /* Nonzero for dummy file systems. */
unsigned int me_remote : 1; /* Nonzero for remote fileystems. */
unsigned int me_type_malloced : 1; /* Nonzero if me_type was malloced. */
struct mount_entry *me_next;
};
struct mount_entry *read_file_system_list (bool need_fs_type);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,218 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 op_c.h
/// Color reduction and color conversion (24b->8b, RGB<->HSL).
/// This is called op_c because half of the process was originally
/// coded in op_asm, in assembler.
//////////////////////////////////////////////////////////////////////////////
#ifndef _OP_C_H_
#define _OP_C_H_
#include "struct.h"
//////////////////////////////////////////////// Définition des types de base
typedef T_Components * T_Bitmap24B;
typedef byte * T_Bitmap256;
//////////////////////////////////////// Définition d'une table de conversion
typedef struct
{
int nbb_r; // Nb de bits de précision sur les rouges
int nbb_g; // Nb de bits de précision sur les verts
int nbb_b; // Nb de bits de précision sur les bleu
int rng_r; // Nb de valeurs sur les rouges (= 1<<nbb_r)
int rng_g; // Nb de valeurs sur les verts (= 1<<nbb_g)
int rng_b; // Nb de valeurs sur les bleus (= 1<<nbb_b)
int dec_r; // Coefficient multiplicateur d'accès dans la table (= nbb_g+nbb_b)
int dec_g; // Coefficient multiplicateur d'accès dans la table (= nbb_b)
int dec_b; // Coefficient multiplicateur d'accès dans la table (= 0)
int red_r; // Coefficient réducteur de traduction d'une couleur rouge (= 8-nbb_r)
int red_g; // Coefficient réducteur de traduction d'une couleur verte (= 8-nbb_g)
int red_b; // Coefficient réducteur de traduction d'une couleur bleue (= 8-nbb_b)
byte * table;
} T_Conversion_table;
///////////////////////////////////////// Définition d'une table d'occurences
typedef struct
{
int nbb_r; // Nb de bits de précision sur les rouges
int nbb_g; // Nb de bits de précision sur les verts
int nbb_b; // Nb de bits de précision sur les bleu
int rng_r; // Nb de valeurs sur les rouges (= 1<<nbb_r)
int rng_g; // Nb de valeurs sur les verts (= 1<<nbb_g)
int rng_b; // Nb de valeurs sur les bleus (= 1<<nbb_b)
int dec_r; // Coefficient multiplicateur d'accès dans la table (= nbb_g+nbb_b)
int dec_g; // Coefficient multiplicateur d'accès dans la table (= nbb_b)
int dec_b; // Coefficient multiplicateur d'accès dans la table (= 0)
int red_r; // Coefficient réducteur de traduction d'une couleur rouge (= 8-nbb_r)
int red_g; // Coefficient réducteur de traduction d'une couleur verte (= 8-nbb_g)
int red_b; // Coefficient réducteur de traduction d'une couleur bleue (= 8-nbb_b)
int * table;
} T_Occurrence_table;
///////////////////////////////////////// Définition d'un ensemble de couleur
typedef struct S_Cluster
{
int occurences; // Nb total d'occurences des couleurs de l'ensemble
// Grande couverture
byte Rmin,Rmax;
byte Gmin,Vmax;
byte Bmin,Bmax;
// Couverture minimale
byte rmin,rmax;
byte vmin,vmax;
byte bmin,bmax;
byte plus_large; // Composante ayant la plus grande variation (0=red,1=green,2=blue)
byte r,g,b; // color synthétisant l'ensemble
byte h; // Chrominance
byte l; // Luminosité
struct S_Cluster* next;
} T_Cluster;
//////////////////////////////////////// Définition d'un ensemble de clusters
typedef struct
{
int nb;
int nb_max;
T_Cluster * clusters;
} T_Cluster_set;
///////////////////////////////////////////////////// Définition d'un dégradé
typedef struct
{
int nb_colors; // Nombre de couleurs dans le dégradé
float min; // Chrominance minimale du dégradé
float max; // Chrominance maximale du dégradé
float hue; // Chrominance moyenne du dégradé
} T_Gradient;
///////////////////////////////////////// Définition d'un ensemble de dégradé
typedef struct
{
int nb; // Nombre de dégradés dans l'ensemble
int nb_max; // Nombre maximum de dégradés
T_Gradient * gradients; // Les dégradés
} T_Gradient_set;
/////////////////////////////////////////////////////////////////////////////
///////////////////////////// Méthodes de gestion des tables de conversion //
/////////////////////////////////////////////////////////////////////////////
T_Conversion_table * CT_new(int nbb_r,int nbb_g,int nbb_b);
void CT_delete(T_Conversion_table * t);
byte CT_get(T_Conversion_table * t,int r,int g,int b);
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 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 //
/////////////////////////////////////////////////////////////////////////////
void OT_init(T_Occurrence_table * t);
T_Occurrence_table * OT_new(int nbb_r,int nbb_g,int nbb_b);
void OT_delete(T_Occurrence_table * t);
int OT_get(T_Occurrence_table * t,int r,int g,int b);
void OT_inc(T_Occurrence_table * t,int r,int g,int b);
void OT_count_occurrences(T_Occurrence_table * t,T_Bitmap24B image,int size);
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////// Méthodes de gestion des clusters //
/////////////////////////////////////////////////////////////////////////////
void Cluster_pack(T_Cluster * c,T_Occurrence_table * to);
void Cluster_split(T_Cluster * c,T_Cluster * c1,T_Cluster * c2,int hue,T_Occurrence_table * to);
void Cluster_compute_hue(T_Cluster * c,T_Occurrence_table * to);
/////////////////////////////////////////////////////////////////////////////
//////////////////////////// Méthodes de gestion des ensembles de clusters //
/////////////////////////////////////////////////////////////////////////////
void CS_Init(T_Cluster_set * cs,T_Occurrence_table * to);
T_Cluster_set * CS_New(int nbmax,T_Occurrence_table * to);
void CS_Delete(T_Cluster_set * cs);
void CS_Get(T_Cluster_set * cs,T_Cluster * c);
void CS_Set(T_Cluster_set * cs,T_Cluster * c);
void CS_Generate(T_Cluster_set * cs,T_Occurrence_table * to);
void CS_Compute_colors(T_Cluster_set * cs,T_Occurrence_table * to);
void CS_Generate_color_table_and_palette(T_Cluster_set * cs,T_Conversion_table * tc,T_Components * palette);
/////////////////////////////////////////////////////////////////////////////
//////////////////////////// Méthodes de gestion des ensembles de dégradés //
/////////////////////////////////////////////////////////////////////////////
void GS_Init(T_Gradient_set * ds,T_Cluster_set * cs);
T_Gradient_set * GS_New(T_Cluster_set * cs);
void GS_Delete(T_Gradient_set * ds);
void GS_Generate(T_Gradient_set * ds,T_Cluster_set * cs);
// Convertie avec le plus de précision possible une image 24b en 256c
// Renvoie s'il y a eu une erreur ou pas..
int Convert_24b_bitmap_to_256(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,232 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 operatio.h
/// Code for the drawing tools operations.
//////////////////////////////////////////////////////////////////////////////
#include "struct.h"
// General operation handling functions. These may be moved to ops_handler.h when operatio.c grows over 5000 lines again...
/// Do some housekeeping before starting work on a operation.
void Start_operation_stack(word new_operation);
/// Put a value on ::Operation_stack
void Operation_push(short value);
/// Take a value off ::Operation_stack
void Operation_pop(short * value);
void Init_start_operation(void);
short Distance(short x1, short y1, short x2, short y2);
//////////////////////////////////////////////////// OPERATION_CONTINUOUS_DRAW
void Freehand_mode1_1_0(void);
void Freehand_mode1_1_2(void);
void Freehand_mode12_0_2(void);
void Freehand_mode1_2_0(void);
void Freehand_mode1_2_2(void);
///////////////////////////////////////////////// OPERATION_DISCONTINUOUS_DRAW
void Freehand_mode2_1_0(void);
void Freehand_mode2_1_2(void);
void Freehand_mode2_2_0(void);
void Freehand_mode2_2_2(void);
////////////////////////////////////////////////////// OPERATION_POINT_DRAW
void Freehand_mode3_1_0(void);
void Freehand_Mode3_2_0(void);
void Freehand_mode3_0_1(void);
///////////////////////////////////////////////////////////// OPERATION_LINE
void Line_12_0(void);
void Line_12_5(void);
void Line_0_5(void);
///////////////////////////////////////////////////////////// OPERATION_MAGNIFY
void Magnifier_12_0(void);
/////////////////////////////////////////////////// OPERATION_RECTANGLE_?????
void Rectangle_12_0(void);
void Rectangle_12_5(void);
void Empty_rectangle_0_5(void);
void Filled_rectangle_0_5(void);
////////////////////////////////////////////////////// OPERATION_CERCLE_?????
void Circle_12_0(void);
void Circle_12_5(void);
void Empty_circle_0_5(void);
void Filled_circle_0_5(void);
///////////////////////////////////////////////////// OPERATION_ELLIPSE_?????
void Ellipse_12_0(void);
void Ellipse_12_5(void);
void Empty_ellipse_0_5(void);
void Filled_ellipse_0_5(void);
////////////////////////////////////////////////////// OPERATION_GRAB_BRUSH
void Brush_12_0(void);
void Brush_12_5(void);
void Brush_0_5(void);
///////////////////////////////////////////////////// OPERATION_STRETCH_BRUSH
void Stretch_brush_12_0(void);
void Stretch_brush_1_7(void);
void Stretch_brush_0_7(void);
void Stretch_brush_2_7(void);
//////////////////////////////////////////////////// OPERATION_ROTATE_BRUSH
void Rotate_brush_12_0(void);
void Rotate_brush_1_5(void);
void Rotate_brush_0_5(void);
void Rotate_brush_2_5(void);
///////////////////////////////////////////////////// OPERATION_DISTORT_BRUSH
void Distort_brush_0_0(void);
void Distort_brush_1_0(void);
void Distort_brush_2_0(void);
void Distort_brush_1_8(void);
void Distort_brush_2_8(void);
void Distort_brush_1_9(void);
void Distort_brush_0_9(void);
//////////////////////////////////////////////////////// OPERATION_POLYBRUSH
void Polybrush_12_8(void);
////////////////////////////////////////////////////////////// OPERATION_FILL
void Fill_1_0(void);
void Fill_2_0(void);
///////////////////////////////////////////////////////// OPERATION_REPLACE
void Replace_1_0(void);
void Replace_2_0(void);
/////////////////////////////////////////////////////////// OPERATION_COLORPICK
void Pipette_0_0(void);
void Colorpicker_12_0(void);
void Colorpicker_1_1(void);
void Colorpicker_2_1(void);
void Colorpicker_0_1(void);
/////////////////////////////////////////////////////////// OPERATION_K_LIGNE
void K_line_12_0(void);
void K_line_12_6(void);
void K_line_0_6(void);
void K_line_12_7(void);
/////////////////////////////////////////////////// OPERATION_COURBE_?_POINTS
void Curve_34_points_1_0(void);
void Curve_34_points_2_0(void);
void Curve_34_points_1_5(void);
void Curve_34_points_2_5(void);
void Curve_4_points_0_5(void);
void Curve_4_points_1_9(void);
void Curve_4_points_2_9(void);
void Curve_3_points_0_5(void);
void Curve_3_points_0_11(void);
void Curve_3_points_12_11(void);
///////////////////////////////////////////////////////////// OPERATION_AIRBRUSH
void Airbrush_1_0(void);
void Airbrush_2_0(void);
void Airbrush_12_2(void);
void Airbrush_0_2(void);
//////////////////////////////////////////////////////////// OPERATION_*POLY*
void Polygon_12_0(void);
void Polygon_12_9(void);
void Polyfill_12_0(void);
void Polyfill_0_8(void);
void Polyfill_12_8(void);
void Polyfill_12_9(void);
void Polyform_12_0(void);
void Polyform_12_8(void);
void Polyform_0_8(void);
void Filled_polyform_12_0(void);
void Filled_polyform_12_8(void);
void Filled_polyform_0_8(void);
void Filled_contour_0_8(void);
//////////////////////////////////////////////////////////// OPERATION_SCROLL
void Scroll_12_0(void);
void Scroll_12_5(void);
void Scroll_0_5(void);
//////////////////////////////////////////////////// OPERATION_GRAD_CIRCLE
void Grad_circle_12_0(void);
void Grad_circle_12_6(void);
void Grad_circle_0_6(void);
void Grad_circle_12_8(void);
void Grad_circle_or_ellipse_0_8(void);
////////////////////////////////////////////////// OPERATION_GRAD_ELLIPSE
void Grad_ellipse_12_0(void);
void Grad_ellipse_12_6(void);
void Grad_ellipse_0_6(void);
void Grad_ellipse_12_8(void);
///////////////////////////////////////////////// OPERATION_GRAD_RECTANGLE
void Grad_rectangle_12_0(void);
void Grad_rectangle_12_5(void);
void Grad_rectangle_0_5(void);
void Grad_rectangle_0_7(void);
void Grad_rectangle_12_7(void);
void Grad_rectangle_12_9(void);
void Grad_rectangle_0_9(void);
/////////////////////////////////////////////////// OPERATION_CENTERED_LINES
void Centered_lines_12_0(void);
void Centered_lines_12_3(void);
void Centered_lines_0_3(void);
void Centered_lines_12_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);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,141 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 pages.h
/// Handler for the Undo/Redo system.
//////////////////////////////////////////////////////////////////////////////
#ifndef _PAGES_H_
#define _PAGES_H_
///
/// Pointer to the image to read, while drawing. It's either the last history
/// layer page when FX feedback is on, or the history page before it
/// when FX feedback is off.
extern byte * FX_feedback_screen;
//////////////////////////////////////////////////////////////////////////
/////////////////////////// BACKUP ///////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
#ifndef NOLAYERS
/// The pixels of visible layers, flattened copy.
extern T_Bitmap Main_visible_image;
/// The pixels of visible layers, flattened copy, used for no-feedback effects.
extern T_Bitmap Main_visible_image_backup;
/// The index of visible pixels from ::Visible image. Points to the right layer.
extern T_Bitmap Main_visible_image_depth_buffer;
#endif
/// The pixels of visible layers for the spare page, flattened copy.
extern T_Bitmap Spare_visible_image;
///
/// INDIVIDUAL PAGES
///
void Download_infos_page_main(T_Page * page);
void Upload_infos_page_main(T_Page * page);
/// Add a new layer to latest page of a list. Returns 0 on success.
byte Add_layer(T_List_of_pages *list, byte layer);
/// Delete a layer from the latest page of a list. Returns 0 on success.
byte Delete_layer(T_List_of_pages *list, byte layer);
/// Merges the current layer onto the one below it.
byte Merge_layer();
// private
T_Page * New_page(byte nb_layers);
void Download_infos_page_spare(T_Page * page);
void Upload_infos_page_spare(T_Page * page);
void Clear_page(T_Page * page);
void Copy_S_page(T_Page * dest,T_Page * source);
///
/// LISTS OF PAGES
///
void Init_list_of_pages(T_List_of_pages * list);
// private
int Allocate_list_of_pages(T_List_of_pages * list);
void Backward_in_list_of_pages(T_List_of_pages * list);
void Advance_in_list_of_pages(T_List_of_pages * list);
void Free_last_page_of_list(T_List_of_pages * list);
int Create_new_page(T_Page * new_page,T_List_of_pages * current_list, dword layer_mask);
void Change_page_number_of_list(T_List_of_pages * list,int number);
void Free_page_of_a_list(T_List_of_pages * list);
///
/// BACKUP HIGH-LEVEL FUNCTIONS
///
int Init_all_backup_lists(int width,int height);
void Set_number_of_backups(int nb_backups);
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.
void Backup_the_spare(dword layer_mask);
int Backup_and_resize_the_spare(int width,int height);
/// Backup with a new copy for the working layer, and references for all others.
void Backup(void);
/// Backup with a new copy of some layers (the others are references).
void Backup_layers(dword layer_mask);
void Undo(void);
void Redo(void);
void Free_current_page(void); // 'Kill' button
void Exchange_main_and_spare(void);
void End_of_modification(void);
void Update_depth_buffer(void);
void Redraw_layered_image(void);
void Redraw_current_layer(void);
void Update_screen_targets(void);
/// Update all the special image buffers, if necessary.
int Update_buffers(int width, int height);
int Update_spare_buffers(int width, int height);
void Redraw_spare_image(void);
///
/// Must be called after changing the head of Main_backups list, or
/// Main_current_layer
void Update_FX_feedback(byte with_feedback);
///
/// STATISTICS
///
/// Total number of unique bitmaps (layers, animation frames, backups)
extern long Stats_pages_number;
/// Total memory used by bitmaps (layers, animation frames, backups)
extern long long Stats_pages_memory;
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,60 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 palette.h
/// Palette screen, and some palette-related high-level functions.
//////////////////////////////////////////////////////////////////////////////
/// Open the palette menu and handles everything inside it.
void Button_Palette(void);
/// Open the secondary palette menu and handles it.
void Button_Secondary_palette(void);
/// Choose the number of graduations for RGB components, from 2 to 256.
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.
/// Returns the resulting value, in the [0-255] range.
byte Round_palette_component(byte comp);
/*!
Adds 4 menu colors in the current palette.
@param color_usage An up-to-date color usage table (byte[256]) (read only)
@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);
/// 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

@@ -0,0 +1,2 @@
char Program_version[]="2.3";

View File

@@ -0,0 +1,510 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#include <string.h>
#include <stdlib.h>
#include <SDL.h>
#include "global.h"
#include "sdlscreen.h"
#include "misc.h"
#include "graph.h"
#include "pxdouble.h"
#include "pxwide.h" // for Display_transparent_line_on_screen_wide()
#define ZOOMX 2
#define ZOOMY 2
#ifdef __VBCC__
#define __attribute__(x)
#endif
void Pixel_double (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */
{
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1)* VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1)* VIDEO_LINE_WIDTH + 1)=color;
}
byte Read_pixel_double (word x,word y)
/* On retourne la couleur du pixel aux coords données */
{
return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX);
}
void Block_double (word start_x,word start_y,word width,word height,byte color)
/* On affiche un rectangle de la couleur donnée */
{
SDL_Rect rectangle;
rectangle.x=start_x*ZOOMX;
rectangle.y=start_y*ZOOMY;
rectangle.w=width*ZOOMX;
rectangle.h=height*ZOOMY;
SDL_FillRect(Screen_SDL,&rectangle,color);
}
void Display_part_of_screen_double (word width,word height,word image_width)
/* Afficher une partie de l'image telle quelle sur l'écran */
{
byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest)
byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src)
int y;
int dy;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
// On fait une copie de la ligne
for (dy=width;dy>0;dy--)
{
*(dest+1)=*dest=*src;
src++;
dest+=ZOOMX;
}
// On double la ligne qu'on vient de copier
memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
//Update_rect(0,0,width,height);
}
void Pixel_preview_normal_double (word x,word y,byte color)
/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image
* dans l'écran, en mode normal (pas en mode loupe)
* Note: si on modifie cette procédure, il faudra penser à faire également
* la modif dans la procédure Pixel_Preview_Loupe_SDL. */
{
// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0)
Pixel_double(x-Main_offset_X,y-Main_offset_Y,color);
}
void Pixel_preview_magnifier_double (word x,word y,byte color)
{
// Affiche le pixel dans la partie non zoomée
Pixel_double(x-Main_offset_X,y-Main_offset_Y,color);
// Regarde si on doit aussi l'afficher dans la partie zoomée
if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom
&& x >= Limit_left_zoom && x <= Limit_visible_right_zoom)
{
// On est dedans
int height;
int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y);
if (Menu_Y - y_zoom < Main_magnifier_factor)
// On ne doit dessiner qu'un morceau du pixel
// sinon on dépasse sur le menu
height = Menu_Y - y_zoom;
else
height = Main_magnifier_factor;
Block_double(
Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom,
y_zoom, Main_magnifier_factor, height, color
);
}
}
void Horizontal_XOR_line_double(word x_pos,word y_pos,word width)
{
//On calcule la valeur initiale de dest:
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels;
int x;
for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+1)=*(dest+x)=~*(dest+x);
}
void Vertical_XOR_line_double(word x_pos,word y_pos,word height)
{
int i;
byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
for (i=height;i>0;i--)
{
*dest=*(dest+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=~*dest;
dest+=VIDEO_LINE_WIDTH*ZOOMY;
}
}
void Display_brush_color_double(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = Brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+1) = *dest = *src;
}
// Pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_brush_mono_double(word x_pos, word y_pos,
word x_offset, word y_offset, word width, word height,
byte transp_color, byte color, word brush_width)
/* On affiche la brosse en monochrome */
{
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à
// l'écran
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse
int x,y;
for(y=height;y!=0;y--)
//Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
if (*src!=transp_color)
*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=color;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=brush_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Clear_brush_double(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width)
{
byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest)
byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src)
int y;
int x;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=*src;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
// Affiche une brosse (arbitraire) à l'écran
void Display_brush_double(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=*src;
}
// Pixel suivant
src++; dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
}
void Remap_screen_double(word x_pos,word y_pos,word width,word height,byte * conversion_table)
{
// dest = coords a l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
int x,y;
// Pour chaque ligne
for(y=height;y>0;y--)
{
// Pour chaque pixel
for(x=width;x>0;x--)
{
*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=
conversion_table[*dest];
dest +=ZOOMX;
}
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_line_on_screen_fast_double(word x_pos,word y_pos,word width,byte * line)
/* On affiche toute une ligne de pixels telle quelle. */
/* Utilisée si le buffer contient déja des pixel doublés. */
{
memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
}
void Display_line_on_screen_double(word x_pos,word y_pos,word width,byte * line)
/* On affiche une ligne de pixels en les doublant. */
{
int x;
byte *dest;
dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH;
for(x=width;x>0;x--)
{
*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=*line;
dest+=ZOOMX;
line++;
}
}
void Display_transparent_mono_line_on_screen_double(
word x_pos, word y_pos, word width, byte* line,
byte transp_color, byte color)
// Affiche une ligne à l'écran avec une couleur + transparence.
// Utilisé par les brosses en mode zoom
{
byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX;
int x;
// Pour chaque pixel
for(x=0;x<width;x++)
{
if (transp_color!=*line)
{
*(dest+1)=*dest=color;
}
line ++; // Pixel suivant
dest+=ZOOMX;
}
}
void Read_line_screen_double(word x_pos,word y_pos,word width,byte * line)
{
memcpy(line,VIDEO_LINE_WIDTH*ZOOMY * y_pos + x_pos * ZOOMX + Screen_pixels,width*ZOOMX);
}
void Display_part_of_screen_scaled_double(
word width, // width non zoomée
word height, // height zoomée
word image_width,byte * buffer)
{
byte* src = Main_screen + Main_magnifier_offset_Y * image_width
+ Main_magnifier_offset_X;
int y = 0; // Ligne en cours de traitement
// Pour chaque ligne à zoomer
while(1)
{
int x;
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
// On l'affiche Facteur fois, sur des lignes consécutives
x = Main_magnifier_factor;
// Pour chaque ligne
do{
// On affiche la ligne zoomée
Display_line_on_screen_fast_double(
Main_X_zoom, y, width*Main_magnifier_factor,
buffer
);
// On passe à la suivante
y++;
if(y==height)
{
Redraw_grid(Main_X_zoom,0,
width*Main_magnifier_factor,height);
Update_rect(Main_X_zoom,0,
width*Main_magnifier_factor,height);
return;
}
x--;
}while (x > 0);
src += image_width;
}
// ATTENTION on n'arrive jamais ici !
}
// Affiche une partie de la brosse couleur zoomée
void Display_brush_color_zoom_double(word x_pos,word y_pos,
word x_offset,word y_offset,
word width, // width non zoomée
word end_y_pos,byte transp_color,
word brush_width, // width réelle de la brosse
byte * buffer)
{
byte* src = Brush+y_offset*brush_width + x_offset;
word y = y_pos;
byte bx;
// Pour chaque ligne
while(1)
{
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche facteur fois la ligne zoomée
for(bx=Main_magnifier_factor;bx>0;bx--)
{
Display_transparent_line_on_screen_wide(x_pos,y*ZOOMY,width*Main_magnifier_factor,buffer,transp_color);
memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
y++;
if(y==end_y_pos)
{
return;
}
}
src += brush_width;
}
// ATTENTION zone jamais atteinte
}
void Display_brush_mono_zoom_double(word x_pos, word y_pos,
word x_offset, word y_offset,
word width, // width non zoomée
word end_y_pos,
byte transp_color, byte color,
word brush_width, // width réelle de la brosse
byte * buffer
)
{
byte* src = Brush + y_offset * brush_width + x_offset;
int y=y_pos*ZOOMY;
//Pour chaque ligne à zoomer :
while(1)
{
int bx;
// src = Ligne originale
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche la ligne Facteur fois à l'écran (sur des
// lignes consécutives)
bx = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne écran
do
{
// On affiche la ligne zoomée
Display_transparent_mono_line_on_screen_double(
x_pos, y, width * Main_magnifier_factor,
buffer, transp_color, color
);
// On passe à la ligne suivante
y++;
// On vérifie qu'on est pas à la ligne finale
if(y == end_y_pos*ZOOMY)
{
Redraw_grid( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
Update_rect( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
return;
}
bx --;
}
while (bx > 0);
// Passage à la ligne suivante dans la brosse aussi
src+=brush_width;
}
}
void Clear_brush_scaled_double(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer)
{
// En fait on va recopier l'image non zoomée dans la partie zoomée !
byte* src = Main_screen + y_offset * image_width + x_offset;
int y = y_pos;
int bx;
// Pour chaque ligne à zoomer
while(1){
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
bx=Main_magnifier_factor;
// Pour chaque ligne
do{
Display_line_on_screen_fast_double(x_pos,y,
width * Main_magnifier_factor,buffer);
// Ligne suivante
y++;
if(y==end_y_pos)
{
Redraw_grid(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
Update_rect(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
return;
}
bx--;
}while(bx!=0);
src+= image_width;
}
}

View File

@@ -0,0 +1,50 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 pxdouble.h
/// Renderer for double pixels (2x2).
//////////////////////////////////////////////////////////////////////////////
#include "struct.h"
void Pixel_double (word x,word y,byte color);
byte Read_pixel_double (word x,word y);
void Block_double (word start_x,word start_y,word width,word height,byte color);
void Pixel_preview_normal_double (word x,word y,byte color);
void Pixel_preview_magnifier_double (word x,word y,byte color);
void Horizontal_XOR_line_double (word x_pos,word y_pos,word width);
void Vertical_XOR_line_double (word x_pos,word y_pos,word height);
void Display_brush_color_double (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_brush_mono_double (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width);
void Clear_brush_double (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width);
void Remap_screen_double (word x_pos,word y_pos,word width,word height,byte * conversion_table);
void Display_part_of_screen_double (word width,word height,word image_width);
void Display_line_on_screen_double (word x_pos,word y_pos,word width,byte * line);
void Read_line_screen_double (word x_pos,word y_pos,word width,byte * line);
void Display_part_of_screen_scaled_double(word width,word height,word image_width,byte * buffer);
void Display_brush_color_zoom_double (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer);
void Display_brush_mono_zoom_double (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer);
void Clear_brush_scaled_double (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer);
void Display_brush_double (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_line_on_screen_fast_double (word x_pos,word y_pos,word width,byte * line);

View File

@@ -0,0 +1,545 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#include <string.h>
#include <stdlib.h>
#include <SDL.h>
#include "global.h"
#include "sdlscreen.h"
#include "misc.h"
#include "graph.h"
#include "pxquad.h"
#define ZOOMX 4
#define ZOOMY 4
#ifdef __VBCC__
#define __attribute__(x)
#endif
void Pixel_quad (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */
{
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 2)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 3)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 2)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 3)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 2)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 3)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH + 2)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH + 3)=color;
}
byte Read_pixel_quad (word x,word y)
/* On retourne la couleur du pixel aux coords données */
{
return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX);
}
void Block_quad (word start_x,word start_y,word width,word height,byte color)
/* On affiche un rectangle de la couleur donnée */
{
SDL_Rect rectangle;
rectangle.x=start_x*ZOOMX;
rectangle.y=start_y*ZOOMY;
rectangle.w=width*ZOOMX;
rectangle.h=height*ZOOMY;
SDL_FillRect(Screen_SDL,&rectangle,color);
}
void Display_part_of_screen_quad (word width,word height,word image_width)
/* Afficher une partie de l'image telle quelle sur l'écran */
{
byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest)
byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src)
int y;
int dy;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
// On fait une copie de la ligne
for (dy=width;dy>0;dy--)
{
*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src;
src++;
dest+=ZOOMX;
}
// On double la ligne qu'on vient de copier
memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On la triple
memcpy(dest-width*ZOOMX+2*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On la quadruple
memcpy(dest-width*ZOOMX+3*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
//Update_rect(0,0,width,height);
}
void Pixel_preview_normal_quad (word x,word y,byte color)
/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image
* dans l'écran, en mode normal (pas en mode loupe)
* Note: si on modifie cette procédure, il faudra penser à faire également
* la modif dans la procédure Pixel_Preview_Loupe_SDL. */
{
// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0)
Pixel_quad(x-Main_offset_X,y-Main_offset_Y,color);
}
void Pixel_preview_magnifier_quad (word x,word y,byte color)
{
// Affiche le pixel dans la partie non zoomée
Pixel_quad(x-Main_offset_X,y-Main_offset_Y,color);
// Regarde si on doit aussi l'afficher dans la partie zoomée
if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom
&& x >= Limit_left_zoom && x <= Limit_visible_right_zoom)
{
// On est dedans
int height;
int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y);
if (Menu_Y - y_zoom < Main_magnifier_factor)
// On ne doit dessiner qu'un morceau du pixel
// sinon on dépasse sur le menu
height = Menu_Y - y_zoom;
else
height = Main_magnifier_factor;
Block_quad(
Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom,
y_zoom, Main_magnifier_factor, height, color
);
}
}
void Horizontal_XOR_line_quad(word x_pos,word y_pos,word width)
{
//On calcule la valeur initiale de dest:
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels;
int x;
for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+3*VIDEO_LINE_WIDTH+3)=*(dest+x+3*VIDEO_LINE_WIDTH+2)=*(dest+x+3*VIDEO_LINE_WIDTH+1)=*(dest+x+3*VIDEO_LINE_WIDTH)=*(dest+x+2*VIDEO_LINE_WIDTH+3)=*(dest+x+2*VIDEO_LINE_WIDTH+2)=*(dest+x+2*VIDEO_LINE_WIDTH+1)=*(dest+x+2*VIDEO_LINE_WIDTH)=*(dest+x+VIDEO_LINE_WIDTH+3)=*(dest+x+VIDEO_LINE_WIDTH+2)=*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+3)=*(dest+x+2)=*(dest+x+1)=*(dest+x)=~*(dest+x);
}
void Vertical_XOR_line_quad(word x_pos,word y_pos,word height)
{
int i;
byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
for (i=height;i>0;i--)
{
*(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*(dest)=~*(dest);
dest+=VIDEO_LINE_WIDTH*ZOOMY;
}
}
void Display_brush_color_quad(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = Brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+3*VIDEO_LINE_WIDTH+3) = *(dest+3*VIDEO_LINE_WIDTH+2) = *(dest+3*VIDEO_LINE_WIDTH+1) = *(dest+3*VIDEO_LINE_WIDTH) = *(dest+2*VIDEO_LINE_WIDTH+3) = *(dest+2*VIDEO_LINE_WIDTH+2) = *(dest+2*VIDEO_LINE_WIDTH+1) = *(dest+2*VIDEO_LINE_WIDTH) = *(dest+VIDEO_LINE_WIDTH+3) = *(dest+VIDEO_LINE_WIDTH+2) = *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+3) = *(dest+2) = *(dest+1) = *dest = *src;
}
// Pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_brush_mono_quad(word x_pos, word y_pos,
word x_offset, word y_offset, word width, word height,
byte transp_color, byte color, word brush_width)
/* On affiche la brosse en monochrome */
{
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à
// l'écran
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse
int x,y;
for(y=height;y!=0;y--)
//Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
if (*src!=transp_color)
*(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=color;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=brush_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Clear_brush_quad(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width)
{
byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest)
byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src)
int y;
int x;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
*(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
// Affiche une brosse (arbitraire) à l'écran
void Display_brush_quad(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src;
}
// Pixel suivant
src++; dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
}
void Remap_screen_quad(word x_pos,word y_pos,word width,word height,byte * conversion_table)
{
// dest = coords a l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
int x,y;
// Pour chaque ligne
for(y=height;y>0;y--)
{
// Pour chaque pixel
for(x=width;x>0;x--)
{
*(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=
conversion_table[*dest];
dest +=ZOOMX;
}
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_line_on_screen_fast_quad(word x_pos,word y_pos,word width,byte * line)
/* On affiche toute une ligne de pixels telle quelle. */
/* Utilisée si le buffer contient déja des pixel doublés. */
{
memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+2)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+3)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
}
void Display_line_on_screen_quad(word x_pos,word y_pos,word width,byte * line)
/* On affiche une ligne de pixels en les doublant. */
{
int x;
byte *dest;
dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH;
for(x=width;x>0;x--)
{
*(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*line;
dest+=ZOOMX;
line++;
}
}
void Display_transparent_mono_line_on_screen_quad(
word x_pos, word y_pos, word width, byte* line,
byte transp_color, byte color)
// Affiche une ligne à l'écran avec une couleur + transparence.
// Utilisé par les brosses en mode zoom
{
byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX;
int x;
// Pour chaque pixel
for(x=0;x<width;x++)
{
if (transp_color!=*line)
{
*(dest+3)=*(dest+2)=*(dest+1)=*dest=color;
}
line ++; // Pixel suivant
dest+=ZOOMX;
}
}
void Read_line_screen_quad(word x_pos,word y_pos,word width,byte * line)
{
memcpy(line,VIDEO_LINE_WIDTH*ZOOMY * y_pos + x_pos * ZOOMX + Screen_pixels,width*ZOOMX);
}
void Display_part_of_screen_scaled_quad(
word width, // width non zoomée
word height, // height zoomée
word image_width,byte * buffer)
{
byte* src = Main_screen + Main_magnifier_offset_Y * image_width
+ Main_magnifier_offset_X;
int y = 0; // Ligne en cours de traitement
// Pour chaque ligne à zoomer
while(1)
{
int x;
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
// On l'affiche Facteur fois, sur des lignes consécutives
x = Main_magnifier_factor/**ZOOMY*/;
// Pour chaque ligne
do{
// On affiche la ligne zoomée
Display_line_on_screen_fast_quad(
Main_X_zoom, y, width*Main_magnifier_factor,
buffer
);
// On passe à la suivante
y++;
if(y==height/**ZOOMY*/)
{
Redraw_grid(Main_X_zoom,0,
width*Main_magnifier_factor,height);
Update_rect(Main_X_zoom,0,
width*Main_magnifier_factor,height);
return;
}
x--;
}while (x > 0);
src += image_width;
}
// ATTENTION on n'arrive jamais ici !
}
// Affiche une partie de la brosse couleur zoomée
void Display_brush_color_zoom_quad(word x_pos,word y_pos,
word x_offset,word y_offset,
word width, // width non zoomée
word end_y_pos,byte transp_color,
word brush_width, // width réelle de la brosse
byte * buffer)
{
byte* src = Brush+y_offset*brush_width + x_offset;
word y = y_pos;
byte bx;
// Pour chaque ligne
while(1)
{
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche facteur fois la ligne zoomée
for(bx=Main_magnifier_factor;bx>0;bx--)
{
byte* line_src = buffer;
byte* dest = Screen_pixels + y*ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
word x;
// Pour chaque pixel de la ligne
for(x = width*Main_magnifier_factor;x > 0;x--)
{
if(*line_src!=transp_color)
{
*(dest+3)=*(dest+2)=*(dest+1)=*dest = *line_src;
}
line_src++;
dest+=ZOOMX;
}
// Double the line
memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
// Triple the line
memcpy(Screen_pixels + (y*ZOOMY+2)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
// Quadruple it
memcpy(Screen_pixels + (y*ZOOMY+3)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
y++;
if(y==end_y_pos)
{
return;
}
}
src += brush_width;
}
// ATTENTION zone jamais atteinte
}
void Display_brush_mono_zoom_quad(word x_pos, word y_pos,
word x_offset, word y_offset,
word width, // width non zoomée
word end_y_pos,
byte transp_color, byte color,
word brush_width, // width réelle de la brosse
byte * buffer
)
{
byte* src = Brush + y_offset * brush_width + x_offset;
int y=y_pos*ZOOMY;
//Pour chaque ligne à zoomer :
while(1)
{
int bx;
// src = Ligne originale
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche la ligne Facteur fois à l'écran (sur des
// lignes consécutives)
bx = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne écran
do
{
// On affiche la ligne zoomée
Display_transparent_mono_line_on_screen_quad(
x_pos, y, width * Main_magnifier_factor,
buffer, transp_color, color
);
// On passe à la ligne suivante
y++;
// On vérifie qu'on est pas à la ligne finale
if(y == end_y_pos*ZOOMY)
{
Redraw_grid( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
Update_rect( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
return;
}
bx --;
}
while (bx > 0);
// Passage à la ligne suivante dans la brosse aussi
src+=brush_width;
}
}
void Clear_brush_scaled_quad(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer)
{
// En fait on va recopier l'image non zoomée dans la partie zoomée !
byte* src = Main_screen + y_offset * image_width + x_offset;
int y = y_pos;
int bx;
// Pour chaque ligne à zoomer
while(1){
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
bx=Main_magnifier_factor;
// Pour chaque ligne
do{
// TODO a verifier
Display_line_on_screen_fast_quad(x_pos,y,
width * Main_magnifier_factor,buffer);
// Ligne suivante
y++;
if(y==end_y_pos)
{
Redraw_grid(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
Update_rect(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
return;
}
bx--;
}while(bx!=0);
src+= image_width;
}
}

View File

@@ -0,0 +1,50 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 pxquad.h
/// Renderer for quadruple pixels (4x4).
//////////////////////////////////////////////////////////////////////////////
#include "struct.h"
void Pixel_quad (word x,word y,byte color);
byte Read_pixel_quad (word x,word y);
void Block_quad (word start_x,word start_y,word width,word height,byte color);
void Pixel_preview_normal_quad (word x,word y,byte color);
void Pixel_preview_magnifier_quad (word x,word y,byte color);
void Horizontal_XOR_line_quad (word x_pos,word y_pos,word width);
void Vertical_XOR_line_quad (word x_pos,word y_pos,word height);
void Display_brush_color_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_brush_mono_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width);
void Clear_brush_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width);
void Remap_screen_quad (word x_pos,word y_pos,word width,word height,byte * conversion_table);
void Display_part_of_screen_quad (word width,word height,word image_width);
void Display_line_on_screen_quad (word x_pos,word y_pos,word width,byte * line);
void Read_line_screen_quad (word x_pos,word y_pos,word width,byte * line);
void Display_part_of_screen_scaled_quad(word width,word height,word image_width,byte * buffer);
void Display_brush_color_zoom_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer);
void Display_brush_mono_zoom_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer);
void Clear_brush_scaled_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer);
void Display_brush_quad (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_line_on_screen_fast_quad (word x_pos,word y_pos,word width,byte * line);

View File

@@ -0,0 +1,481 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#include <string.h>
#include <stdlib.h>
#include <SDL.h>
#include "global.h"
#include "sdlscreen.h"
#include "misc.h"
#include "graph.h"
#include "pxsimple.h"
#ifdef __VBCC__
#define __attribute__(x)
#endif
void Pixel_simple (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */
{
*(Screen_pixels + x + y * VIDEO_LINE_WIDTH)=color;
}
byte Read_pixel_simple (word x,word y)
/* On retourne la couleur du pixel aux coords données */
{
return *( Screen_pixels + y * VIDEO_LINE_WIDTH + x );
}
void Block_simple (word start_x,word start_y,word width,word height,byte color)
/* On affiche un rectangle de la couleur donnée */
{
SDL_Rect rectangle;
rectangle.x=start_x;
rectangle.y=start_y;
rectangle.w=width;
rectangle.h=height;
SDL_FillRect(Screen_SDL,&rectangle,color);
}
void Display_part_of_screen_simple (word width,word height,word image_width)
/* Afficher une partie de l'image telle quelle sur l'écran */
{
byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest)
byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src)
int y;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
// On fait une copie de la ligne
memcpy(dest,src,width);
// On passe à la ligne suivante
src+=image_width;
dest+=VIDEO_LINE_WIDTH;
}
//Update_rect(0,0,width,height);
}
void Pixel_preview_normal_simple (word x,word y,byte color)
/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image
* dans l'écran, en mode normal (pas en mode loupe)
* Note: si on modifie cette procédure, il faudra penser à faire également
* la modif dans la procédure Pixel_Preview_Loupe_SDL. */
{
// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0)
Pixel_simple(x-Main_offset_X,y-Main_offset_Y,color);
}
void Pixel_preview_magnifier_simple (word x,word y,byte color)
{
// Affiche le pixel dans la partie non zoomée
Pixel_simple(x-Main_offset_X,y-Main_offset_Y,color);
// Regarde si on doit aussi l'afficher dans la partie zoomée
if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom
&& x >= Limit_left_zoom && x <= Limit_visible_right_zoom)
{
// On est dedans
int height;
int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y);
if (Menu_Y - y_zoom < Main_magnifier_factor)
// On ne doit dessiner qu'un morceau du pixel
// sinon on dépasse sur le menu
height = Menu_Y - y_zoom;
else
height = Main_magnifier_factor;
Block_simple(
Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom,
y_zoom, Main_magnifier_factor, height, color
);
}
}
void Horizontal_XOR_line_simple(word x_pos,word y_pos,word width)
{
//On calcule la valeur initiale de dest:
byte* dest=y_pos*VIDEO_LINE_WIDTH+x_pos+Screen_pixels;
int x;
for (x=0;x<width;x++)
*(dest+x)=~*(dest+x);
}
void Vertical_XOR_line_simple(word x_pos,word y_pos,word height)
{
int i;
byte color;
for (i=y_pos;i<y_pos+height;i++)
{
color=*(Screen_pixels+x_pos+i*VIDEO_LINE_WIDTH);
*(Screen_pixels+x_pos+i*VIDEO_LINE_WIDTH)=~color;
}
}
void Display_brush_color_simple(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * VIDEO_LINE_WIDTH + x_pos;
// src = Position dans la brosse
byte* src = Brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*dest = *src;
}
// Pixel suivant
src++; dest++;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH - width;
src = src + brush_width - width;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_brush_mono_simple(word x_pos, word y_pos,
word x_offset, word y_offset, word width, word height,
byte transp_color, byte color, word brush_width)
/* On affiche la brosse en monochrome */
{
byte* dest=y_pos*VIDEO_LINE_WIDTH+x_pos+Screen_pixels; // dest = adr Destination à
// l'écran
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse
int x,y;
for(y=height;y!=0;y--)
//Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
if (*src!=transp_color)
*dest=color;
// On passe au pixel suivant
src++;
dest++;
}
// On passe à la ligne suivante
src+=brush_width-width;
dest+=VIDEO_LINE_WIDTH-width;
}
Update_rect(x_pos,y_pos,width,height);
}
void Clear_brush_simple(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width)
{
byte* dest=Screen_pixels+x_pos+y_pos*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest)
byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src)
int y;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
// On fait une copie de la ligne
memcpy(dest,src,width);
// On passe à la ligne suivante
src+=image_width;
dest+=VIDEO_LINE_WIDTH;
}
Update_rect(x_pos,y_pos,width,height);
}
// Affiche une brosse (arbitraire) à l'écran
void Display_brush_simple(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * VIDEO_LINE_WIDTH + x_pos;
// src = Position dans la brosse
byte* src = brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*dest = *src;
}
// Pixel suivant
src++; dest++;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH - width;
src = src + brush_width - width;
}
}
void Remap_screen_simple(word x_pos,word y_pos,word width,word height,byte * conversion_table)
{
// dest = coords a l'écran
byte* dest = Screen_pixels + y_pos * VIDEO_LINE_WIDTH + x_pos;
int x,y;
// Pour chaque ligne
for(y=height;y>0;y--)
{
// Pour chaque pixel
for(x=width;x>0;x--)
{
*dest = conversion_table[*dest];
dest ++;
}
dest = dest + VIDEO_LINE_WIDTH - width;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_line_on_screen_simple(word x_pos,word y_pos,word width,byte * line)
/* On affiche toute une ligne de pixels. Utilisé pour les textes. */
{
memcpy(Screen_pixels+x_pos+y_pos*VIDEO_LINE_WIDTH,line,width);
}
void Display_transparent_mono_line_on_screen_simple(
word x_pos, word y_pos, word width, byte* line,
byte transp_color, byte color)
// Affiche une ligne à l'écran avec une couleur + transparence.
// Utilisé par les brosses en mode zoom
{
byte* dest = Screen_pixels+ y_pos * VIDEO_LINE_WIDTH + x_pos;
int x;
// Pour chaque pixel
for(x=0;x<width;x++)
{
if (transp_color!=*line)
*dest = color;
line ++; // Pixel suivant
dest++;
}
}
void Read_line_screen_simple(word x_pos,word y_pos,word width,byte * line)
{
memcpy(line,VIDEO_LINE_WIDTH * y_pos + x_pos + Screen_pixels,width);
}
void Display_part_of_screen_scaled_simple(
word width, // width non zoomée
word height, // height zoomée
word image_width,byte * buffer)
{
byte* src = Main_screen + Main_magnifier_offset_Y * image_width
+ Main_magnifier_offset_X;
int y = 0; // Ligne en cours de traitement
// Pour chaque ligne à zoomer
while(1)
{
int x;
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On l'affiche Facteur fois, sur des lignes consécutives
x = Main_magnifier_factor;
// Pour chaque ligne
do{
// On affiche la ligne zoomée
Display_line_on_screen_simple(
Main_X_zoom, y, width*Main_magnifier_factor,
buffer
);
// On passe à la suivante
y++;
if(y==height)
{
Redraw_grid(Main_X_zoom,0,
width*Main_magnifier_factor,height);
Update_rect(Main_X_zoom,0,
width*Main_magnifier_factor,height);
return;
}
x--;
}while (x > 0);
src += image_width;
}
// ATTENTION on n'arrive jamais ici !
}
void Display_transparent_line_on_screen_simple(word x_pos,word y_pos,word width,byte* line,byte transp_color)
{
byte* src = line;
byte* dest = Screen_pixels + y_pos * VIDEO_LINE_WIDTH + x_pos;
word x;
// Pour chaque pixel de la ligne
for(x = width;x > 0;x--)
{
if(*src!=transp_color)
*dest = *src;
src++;
dest++;
}
}
// Affiche une partie de la brosse couleur zoomée
void Display_brush_color_zoom_simple(word x_pos,word y_pos,
word x_offset,word y_offset,
word width, // width non zoomée
word end_y_pos,byte transp_color,
word brush_width, // width réelle de la brosse
byte * buffer)
{
byte* src = Brush+y_offset*brush_width + x_offset;
word y = y_pos;
byte bx;
// Pour chaque ligne
while(1)
{
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche facteur fois la ligne zoomée
for(bx=Main_magnifier_factor;bx>0;bx--)
{
Display_transparent_line_on_screen_simple(x_pos,y,width*Main_magnifier_factor,buffer,transp_color);
y++;
if(y==end_y_pos)
{
return;
}
}
src += brush_width;
}
// ATTENTION zone jamais atteinte
}
void Display_brush_mono_zoom_simple(word x_pos, word y_pos,
word x_offset, word y_offset,
word width, // width non zoomée
word end_y_pos,
byte transp_color, byte color,
word brush_width, // width réelle de la brosse
byte * buffer
)
{
byte* src = Brush + y_offset * brush_width + x_offset;
int y=y_pos;
//Pour chaque ligne à zoomer :
while(1)
{
int bx;
// src = Ligne originale
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche la ligne Facteur fois à l'écran (sur des
// lignes consécutives)
bx = Main_magnifier_factor;
// Pour chaque ligne écran
do
{
// On affiche la ligne zoomée
Display_transparent_mono_line_on_screen_simple(
x_pos, y, width * Main_magnifier_factor,
buffer, transp_color, color
);
// On passe à la ligne suivante
y++;
// On vérifie qu'on est pas à la ligne finale
if(y == end_y_pos)
{
Redraw_grid( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
Update_rect( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
return;
}
bx --;
}
while (bx > 0);
// Passage à la ligne suivante dans la brosse aussi
src+=brush_width;
}
}
void Clear_brush_scaled_simple(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer)
{
// En fait on va recopier l'image non zoomée dans la partie zoomée !
byte* src = Main_screen + y_offset * image_width + x_offset;
int y = y_pos;
int bx;
// Pour chaque ligne à zoomer
while(1){
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
bx=Main_magnifier_factor;
// Pour chaque ligne
do{
Display_line_on_screen_simple(x_pos,y,
width * Main_magnifier_factor,buffer);
// Ligne suivante
y++;
if(y==end_y_pos)
{
Redraw_grid(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
Update_rect(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
return;
}
bx--;
}while(bx!=0);
src+= image_width;
}
}

View File

@@ -0,0 +1,53 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 pxsimple.h
/// Renderer for simple pixels (1x1). This is the normal one.
//////////////////////////////////////////////////////////////////////////////
#include "struct.h"
void Pixel_simple (word x,word y,byte color);
byte Read_pixel_simple (word x,word y);
void Block_simple (word start_x,word start_y,word width,word height,byte color);
void Pixel_preview_normal_simple (word x,word y,byte color);
void Pixel_preview_magnifier_simple (word x,word y,byte color);
void Horizontal_XOR_line_simple (word x_pos,word y_pos,word width);
void Vertical_XOR_line_simple (word x_pos,word y_pos,word height);
void Display_brush_color_simple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_brush_mono_simple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width);
void Clear_brush_simple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width);
void Remap_screen_simple (word x_pos,word y_pos,word width,word height,byte * conversion_table);
void Display_part_of_screen_simple (word width,word height,word image_width);
void Display_line_on_screen_simple (word x_pos,word y_pos,word width,byte * line);
void Read_line_screen_simple (word x_pos,word y_pos,word width,byte * line);
void Display_part_of_screen_scaled_simple(word width,word height,word image_width,byte * buffer);
void Display_brush_color_zoom_simple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer);
void Display_brush_mono_zoom_simple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer);
void Clear_brush_scaled_simple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer);
void Display_brush_simple (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_transparent_mono_line_on_screen_simple(
word x_pos, word y_pos, word width, byte* line,
byte transp_color, byte color);
void Display_transparent_line_on_screen_simple(word x_pos,word y_pos,word width,byte* line,byte transp_color);

View File

@@ -0,0 +1,466 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#include <string.h>
#include <stdlib.h>
#include <SDL.h>
#include "global.h"
#include "sdlscreen.h"
#include "misc.h"
#include "graph.h"
#include "pxtall.h"
#include "pxsimple.h"
#define ZOOMX 1
#define ZOOMY 2
#ifdef __VBCC__
#define __attribute__(x)
#endif
void Pixel_tall (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */
{
*(Screen_pixels + x + y*ZOOMY*VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x + (y*ZOOMY+1)*VIDEO_LINE_WIDTH)=color;
}
byte Read_pixel_tall (word x,word y)
/* On retourne la couleur du pixel aux coords données */
{
return *( Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x );
}
void Block_tall (word start_x,word start_y,word width,word height,byte color)
/* On affiche un rectangle de la couleur donnée */
{
SDL_Rect rectangle;
rectangle.x=start_x;
rectangle.y=start_y*ZOOMY;
rectangle.w=width;
rectangle.h=height*ZOOMY;
SDL_FillRect(Screen_SDL,&rectangle,color);
}
void Display_part_of_screen_tall (word width,word height,word image_width)
/* Afficher une partie de l'image telle quelle sur l'écran */
{
byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest)
byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src)
int y;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
// On fait une copie de la ligne
memcpy(dest,src,width);
dest+=VIDEO_LINE_WIDTH;
memcpy(dest,src,width);
// On passe à la ligne suivante
src+=image_width;
dest+=VIDEO_LINE_WIDTH;
}
//Update_rect(0,0,width,height);
}
void Pixel_preview_normal_tall (word x,word y,byte color)
/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image
* dans l'écran, en mode normal (pas en mode loupe)
* Note: si on modifie cette procédure, il faudra penser à faire également
* la modif dans la procédure Pixel_Preview_Loupe_SDL. */
{
// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0)
Pixel_tall(x-Main_offset_X,y-Main_offset_Y,color);
}
void Pixel_preview_magnifier_tall (word x,word y,byte color)
{
// Affiche le pixel dans la partie non zoomée
Pixel_tall(x-Main_offset_X,y-Main_offset_Y,color);
// Regarde si on doit aussi l'afficher dans la partie zoomée
if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom
&& x >= Limit_left_zoom && x <= Limit_visible_right_zoom)
{
// On est dedans
int height;
int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y);
if (Menu_Y - y_zoom < Main_magnifier_factor)
// On ne doit dessiner qu'un morceau du pixel
// sinon on dépasse sur le menu
height = Menu_Y - y_zoom;
else
height = Main_magnifier_factor;
Block_tall(
Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom,
y_zoom, Main_magnifier_factor, height, color
);
}
}
void Horizontal_XOR_line_tall(word x_pos,word y_pos,word width)
{
//On calcule la valeur initiale de dest:
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos+Screen_pixels;
int x;
for (x=0;x<width;x++)
*(dest+x)=~*(dest+x);
dest=(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH+x_pos+Screen_pixels;
for (x=0;x<width;x++)
*(dest+x)=~*(dest+x);
}
void Vertical_XOR_line_tall(word x_pos,word y_pos,word height)
{
int i;
byte color;
for (i=y_pos*ZOOMY;i<(y_pos+height)*ZOOMY;i++)
{
color=*(Screen_pixels+x_pos+i*VIDEO_LINE_WIDTH);
*(Screen_pixels+x_pos+i*VIDEO_LINE_WIDTH)=~color;
}
}
void Display_brush_color_tall(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos*ZOOMY*VIDEO_LINE_WIDTH + x_pos;
// src = Position dans la brosse
byte* src = Brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*dest = *src;
*(dest+VIDEO_LINE_WIDTH) = *src;
}
// Pixel suivant
src++; dest++;
}
// On passe à la ligne suivante
dest = dest + ZOOMY*VIDEO_LINE_WIDTH - width;
src = src + brush_width - width;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_brush_mono_tall(word x_pos, word y_pos,
word x_offset, word y_offset, word width, word height,
byte transp_color, byte color, word brush_width)
/* On affiche la brosse en monochrome */
{
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos+Screen_pixels; // dest = adr Destination à
// l'écran
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse
int x,y;
for(y=height;y!=0;y--)
//Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
if (*src!=transp_color)
{
*dest=color;
*(dest+VIDEO_LINE_WIDTH)=color;
}
// On passe au pixel suivant
src++;
dest++;
}
// On passe à la ligne suivante
src+=brush_width-width;
dest+=ZOOMY*VIDEO_LINE_WIDTH-width;
}
Update_rect(x_pos,y_pos,width,height);
}
void Clear_brush_tall(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width)
{
byte* dest=Screen_pixels+x_pos+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest)
byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src)
int y;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
// On fait une copie de la ligne
memcpy(dest,src,width);
dest+=VIDEO_LINE_WIDTH;
memcpy(dest,src,width);
// On passe à la ligne suivante
src+=image_width;
dest+=VIDEO_LINE_WIDTH;
}
Update_rect(x_pos,y_pos,width,height);
}
// Affiche une brosse (arbitraire) à l'écran
void Display_brush_tall(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos*ZOOMY*VIDEO_LINE_WIDTH + x_pos;
// src = Position dans la brosse
byte* src = brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*dest = *src;
*(dest+VIDEO_LINE_WIDTH) = *src;
}
// Pixel suivant
src++; dest++;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width;
src = src + brush_width - width;
}
}
void Remap_screen_tall(word x_pos,word y_pos,word width,word height,byte * conversion_table)
{
// dest = coords a l'écran
byte* dest = Screen_pixels + y_pos*ZOOMY*VIDEO_LINE_WIDTH + x_pos;
int x,y;
// Pour chaque ligne
for(y=height*ZOOMY;y>0;y--)
{
// Pour chaque pixel
for(x=width;x>0;x--)
{
*dest = conversion_table[*dest];
dest ++;
}
dest = dest + VIDEO_LINE_WIDTH - width;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_line_on_screen_tall(word x_pos,word y_pos,word width,byte * line)
/* On affiche toute une ligne de pixels. Utilisé pour les textes. */
{
memcpy(Screen_pixels+x_pos+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width);
memcpy(Screen_pixels+x_pos+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width);
}
void Read_line_screen_tall(word x_pos,word y_pos,word width,byte * line)
{
memcpy(line,VIDEO_LINE_WIDTH*ZOOMY*y_pos + x_pos + Screen_pixels,width);
}
void Display_part_of_screen_scaled_tall(
word width, // width non zoomée
word height, // height zoomée
word image_width,byte * buffer)
{
byte* src = Main_screen + Main_magnifier_offset_Y * image_width
+ Main_magnifier_offset_X;
int y = 0; // Ligne en cours de traitement
// Pour chaque ligne à zoomer
while(1)
{
int x;
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On l'affiche Facteur fois, sur des lignes consécutives
x = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne
do{
// On affiche la ligne zoomée
Display_line_on_screen_simple(
Main_X_zoom, y, width*Main_magnifier_factor,
buffer
);
// On passe à la suivante
y++;
if(y==height*ZOOMY)
{
Redraw_grid(Main_X_zoom,0,
width*Main_magnifier_factor,height);
Update_rect(Main_X_zoom,0,
width*Main_magnifier_factor,height);
return;
}
x--;
}while (x > 0);
src += image_width;
}
// ATTENTION on n'arrive jamais ici !
}
// Affiche une partie de la brosse couleur zoomée
void Display_brush_color_zoom_tall(word x_pos,word y_pos,
word x_offset,word y_offset,
word width, // width non zoomée
word end_y_pos,byte transp_color,
word brush_width, // width réelle de la brosse
byte * buffer)
{
byte* src = Brush+y_offset*brush_width + x_offset;
word y = y_pos;
byte bx;
// Pour chaque ligne
while(1)
{
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche facteur fois la ligne zoomée
for(bx=Main_magnifier_factor;bx>0;bx--)
{
Display_transparent_line_on_screen_simple(x_pos,y*ZOOMY,width*Main_magnifier_factor,buffer,transp_color);
memcpy(Screen_pixels + (y*ZOOMY +1) * VIDEO_LINE_WIDTH + x_pos, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos, width*Main_magnifier_factor);
y++;
if(y==end_y_pos)
{
return;
}
}
src += brush_width;
}
// ATTENTION zone jamais atteinte
}
void Display_brush_mono_zoom_tall(word x_pos, word y_pos,
word x_offset, word y_offset,
word width, // width non zoomée
word end_y_pos,
byte transp_color, byte color,
word brush_width, // width réelle de la brosse
byte * buffer
)
{
byte* src = Brush + y_offset * brush_width + x_offset;
int y=y_pos*ZOOMY;
//Pour chaque ligne à zoomer :
while(1)
{
int bx;
// src = Ligne originale
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche la ligne Facteur fois à l'écran (sur des
// lignes consécutives)
bx = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne écran
do
{
// On affiche la ligne zoomée
Display_transparent_mono_line_on_screen_simple(
x_pos, y, width * Main_magnifier_factor,
buffer, transp_color, color
);
// On passe à la ligne suivante
y++;
// On vérifie qu'on est pas à la ligne finale
if(y == end_y_pos*ZOOMY)
{
Redraw_grid( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
Update_rect( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
return;
}
bx --;
}
while (bx > 0);
// Passage à la ligne suivante dans la brosse aussi
src+=brush_width;
}
}
void Clear_brush_scaled_tall(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer)
{
// En fait on va recopier l'image non zoomée dans la partie zoomée !
byte* src = Main_screen + y_offset * image_width + x_offset;
int y = y_pos;
int bx;
// Pour chaque ligne à zoomer
while(1){
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
bx=Main_magnifier_factor;
// Pour chaque ligne
do{
Display_line_on_screen_tall(x_pos,y,
width * Main_magnifier_factor,buffer);
// Ligne suivante
y++;
if(y==end_y_pos)
{
Redraw_grid(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
Update_rect(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
return;
}
bx--;
}while(bx!=0);
src+= image_width;
}
}

View File

@@ -0,0 +1,48 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 pxtall.h
/// Renderer for tall pixels (1x2).
//////////////////////////////////////////////////////////////////////////////
#include "struct.h"
void Pixel_tall (word x,word y,byte color);
byte Read_pixel_tall (word x,word y);
void Block_tall (word start_x,word start_y,word width,word height,byte color);
void Pixel_preview_normal_tall (word x,word y,byte color);
void Pixel_preview_magnifier_tall (word x,word y,byte color);
void Horizontal_XOR_line_tall (word x_pos,word y_pos,word width);
void Vertical_XOR_line_tall (word x_pos,word y_pos,word height);
void Display_brush_color_tall (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_brush_mono_tall (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width);
void Clear_brush_tall (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width);
void Remap_screen_tall (word x_pos,word y_pos,word width,word height,byte * conversion_table);
void Display_part_of_screen_tall (word width,word height,word image_width);
void Display_line_on_screen_tall (word x_pos,word y_pos,word width,byte * line);
void Read_line_screen_tall (word x_pos,word y_pos,word width,byte * line);
void Display_part_of_screen_scaled_tall(word width,word height,word image_width,byte * buffer);
void Display_brush_color_zoom_tall (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer);
void Display_brush_mono_zoom_tall (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer);
void Clear_brush_scaled_tall (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer);
void Display_brush_tall (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);

View File

@@ -0,0 +1,537 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#include <string.h>
#include <stdlib.h>
#include <SDL.h>
#include "global.h"
#include "sdlscreen.h"
#include "misc.h"
#include "graph.h"
#include "pxtall2.h"
#define ZOOMX 2
#define ZOOMY 4
#ifdef __VBCC__
#define __attribute__(x)
#endif
void Pixel_tall2 (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */
{
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH + 1)=color;
}
byte Read_pixel_tall2 (word x,word y)
/* On retourne la couleur du pixel aux coords données */
{
return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX);
}
void Block_tall2 (word start_x,word start_y,word width,word height,byte color)
/* On affiche un rectangle de la couleur donnée */
{
SDL_Rect rectangle;
rectangle.x=start_x*ZOOMX;
rectangle.y=start_y*ZOOMY;
rectangle.w=width*ZOOMX;
rectangle.h=height*ZOOMY;
SDL_FillRect(Screen_SDL,&rectangle,color);
}
void Display_part_of_screen_tall2 (word width,word height,word image_width)
/* Afficher une partie de l'image telle quelle sur l'écran */
{
byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest)
byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src)
int y;
int dy;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
// On fait une copie de la ligne
for (dy=width;dy>0;dy--)
{
*(dest+1)=*dest=*src;
src++;
dest+=ZOOMX;
}
// On double la ligne qu'on vient de copier
memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On la triple
memcpy(dest-width*ZOOMX+2*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On la quadruple
memcpy(dest-width*ZOOMX+3*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
//Update_rect(0,0,width,height);
}
void Pixel_preview_normal_tall2 (word x,word y,byte color)
/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image
* dans l'écran, en mode normal (pas en mode loupe)
* Note: si on modifie cette procédure, il faudra penser à faire également
* la modif dans la procédure Pixel_Preview_Loupe_SDL. */
{
// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0)
Pixel_tall2(x-Main_offset_X,y-Main_offset_Y,color);
}
void Pixel_preview_magnifier_tall2 (word x,word y,byte color)
{
// Affiche le pixel dans la partie non zoomée
Pixel_tall2(x-Main_offset_X,y-Main_offset_Y,color);
// Regarde si on doit aussi l'afficher dans la partie zoomée
if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom
&& x >= Limit_left_zoom && x <= Limit_visible_right_zoom)
{
// On est dedans
int height;
int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y);
if (Menu_Y - y_zoom < Main_magnifier_factor)
// On ne doit dessiner qu'un morceau du pixel
// sinon on dépasse sur le menu
height = Menu_Y - y_zoom;
else
height = Main_magnifier_factor;
Block_tall2(
Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom,
y_zoom, Main_magnifier_factor, height, color
);
}
}
void Horizontal_XOR_line_tall2(word x_pos,word y_pos,word width)
{
//On calcule la valeur initiale de dest:
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels;
int x;
for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+3*VIDEO_LINE_WIDTH+1)=*(dest+x+3*VIDEO_LINE_WIDTH)=*(dest+x+2*VIDEO_LINE_WIDTH+1)=*(dest+x+2*VIDEO_LINE_WIDTH)=*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+1)=*(dest+x)=~*(dest+x);
}
void Vertical_XOR_line_tall2(word x_pos,word y_pos,word height)
{
int i;
byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
for (i=height;i>0;i--)
{
*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=~*(dest);
dest+=VIDEO_LINE_WIDTH*ZOOMY;
}
}
void Display_brush_color_tall2(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = Brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+3*VIDEO_LINE_WIDTH+1) = *(dest+3*VIDEO_LINE_WIDTH) = *(dest+2*VIDEO_LINE_WIDTH+1) = *(dest+2*VIDEO_LINE_WIDTH) = *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+1) = *dest = *src;
}
// Pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_brush_mono_tall2(word x_pos, word y_pos,
word x_offset, word y_offset, word width, word height,
byte transp_color, byte color, word brush_width)
/* On affiche la brosse en monochrome */
{
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à
// l'écran
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse
int x,y;
for(y=height;y!=0;y--)
//Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
if (*src!=transp_color)
*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=color;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=brush_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Clear_brush_tall2(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width)
{
byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest)
byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src)
int y;
int x;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=*src;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
// Affiche une brosse (arbitraire) à l'écran
void Display_brush_tall2(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=*src;
}
// Pixel suivant
src++; dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
}
void Remap_screen_tall2(word x_pos,word y_pos,word width,word height,byte * conversion_table)
{
// dest = coords a l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
int x,y;
// Pour chaque ligne
for(y=height;y>0;y--)
{
// Pour chaque pixel
for(x=width;x>0;x--)
{
*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=
conversion_table[*dest];
dest +=ZOOMX;
}
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_line_on_screen_fast_tall2(word x_pos,word y_pos,word width,byte * line)
/* On affiche toute une ligne de pixels telle quelle. */
/* Utilisée si le buffer contient déja des pixel doublés. */
{
memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+2)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+3)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
}
void Display_line_on_screen_tall2(word x_pos,word y_pos,word width,byte * line)
/* On affiche une ligne de pixels en les doublant. */
{
int x;
byte *dest;
dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH;
for(x=width;x>0;x--)
{
*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=*line;
dest+=ZOOMX;
line++;
}
}
void Display_transparent_mono_line_on_screen_tall2(
word x_pos, word y_pos, word width, byte* line,
byte transp_color, byte color)
// Affiche une ligne à l'écran avec une couleur + transparence.
// Utilisé par les brosses en mode zoom
{
byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX;
int x;
// Pour chaque pixel
for(x=0;x<width;x++)
{
if (transp_color!=*line)
{
*(dest+1)=*dest=color;
}
line ++; // Pixel suivant
dest+=ZOOMX;
}
}
void Read_line_screen_tall2(word x_pos,word y_pos,word width,byte * line)
{
memcpy(line,VIDEO_LINE_WIDTH*ZOOMY * y_pos + x_pos * ZOOMX + Screen_pixels,width*ZOOMX);
}
void Display_part_of_screen_scaled_tall2(
word width, // width non zoomée
word height, // height zoomée
word image_width,byte * buffer)
{
byte* src = Main_screen + Main_magnifier_offset_Y * image_width
+ Main_magnifier_offset_X;
int y = 0; // Ligne en cours de traitement
// Pour chaque ligne à zoomer
while(1)
{
int x;
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
// On l'affiche Facteur fois, sur des lignes consécutives
x = Main_magnifier_factor/**ZOOMY*/;
// Pour chaque ligne
do{
// On affiche la ligne zoomée
Display_line_on_screen_fast_tall2(
Main_X_zoom, y, width*Main_magnifier_factor,
buffer
);
// On passe à la suivante
y++;
if(y==height/**ZOOMY*/)
{
Redraw_grid(Main_X_zoom,0,
width*Main_magnifier_factor,height);
Update_rect(Main_X_zoom,0,
width*Main_magnifier_factor,height);
return;
}
x--;
}while (x > 0);
src += image_width;
}
// ATTENTION on n'arrive jamais ici !
}
// Affiche une partie de la brosse couleur zoomée
void Display_brush_color_zoom_tall2(word x_pos,word y_pos,
word x_offset,word y_offset,
word width, // width non zoomée
word end_y_pos,byte transp_color,
word brush_width, // width réelle de la brosse
byte * buffer)
{
byte* src = Brush+y_offset*brush_width + x_offset;
word y = y_pos;
byte bx;
// Pour chaque ligne
while(1)
{
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche facteur fois la ligne zoomée
for(bx=Main_magnifier_factor;bx>0;bx--)
{
byte* line_src = buffer;
byte* dest = Screen_pixels + y*ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
word x;
// Pour chaque pixel de la ligne
for(x = width*Main_magnifier_factor;x > 0;x--)
{
if(*line_src!=transp_color)
{
*(dest+1)=*dest = *line_src;
}
line_src++;
dest+=ZOOMX;
}
// Double the line
memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
// Triple the line
memcpy(Screen_pixels + (y*ZOOMY+2)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
// Quadruple it
memcpy(Screen_pixels + (y*ZOOMY+3)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
y++;
if(y==end_y_pos)
{
return;
}
}
src += brush_width;
}
// ATTENTION zone jamais atteinte
}
void Display_brush_mono_zoom_tall2(word x_pos, word y_pos,
word x_offset, word y_offset,
word width, // width non zoomée
word end_y_pos,
byte transp_color, byte color,
word brush_width, // width réelle de la brosse
byte * buffer
)
{
byte* src = Brush + y_offset * brush_width + x_offset;
int y=y_pos*ZOOMY;
//Pour chaque ligne à zoomer :
while(1)
{
int bx;
// src = Ligne originale
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche la ligne Facteur fois à l'écran (sur des
// lignes consécutives)
bx = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne écran
do
{
// On affiche la ligne zoomée
Display_transparent_mono_line_on_screen_tall2(
x_pos, y, width * Main_magnifier_factor,
buffer, transp_color, color
);
// On passe à la ligne suivante
y++;
// On vérifie qu'on est pas à la ligne finale
if(y == end_y_pos*ZOOMY)
{
Redraw_grid( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
Update_rect( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
return;
}
bx --;
}
while (bx > 0);
// Passage à la ligne suivante dans la brosse aussi
src+=brush_width;
}
}
void Clear_brush_scaled_tall2(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer)
{
// En fait on va recopier l'image non zoomée dans la partie zoomée !
byte* src = Main_screen + y_offset * image_width + x_offset;
int y = y_pos;
int bx;
// Pour chaque ligne à zoomer
while(1){
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
bx=Main_magnifier_factor;
// Pour chaque ligne
do{
// TODO a verifier
Display_line_on_screen_fast_tall2(x_pos,y,
width * Main_magnifier_factor,buffer);
// Ligne suivante
y++;
if(y==end_y_pos)
{
Redraw_grid(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
Update_rect(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
return;
}
bx--;
}while(bx!=0);
src+= image_width;
}
}

View File

@@ -0,0 +1,50 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 pxtall2.h
/// Renderer for double-tall pixels (2x4).
//////////////////////////////////////////////////////////////////////////////
#include "struct.h"
void Pixel_tall2 (word x,word y,byte color);
byte Read_pixel_tall2 (word x,word y);
void Block_tall2 (word start_x,word start_y,word width,word height,byte color);
void Pixel_preview_normal_tall2 (word x,word y,byte color);
void Pixel_preview_magnifier_tall2 (word x,word y,byte color);
void Horizontal_XOR_line_tall2 (word x_pos,word y_pos,word width);
void Vertical_XOR_line_tall2 (word x_pos,word y_pos,word height);
void Display_brush_color_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_brush_mono_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width);
void Clear_brush_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width);
void Remap_screen_tall2 (word x_pos,word y_pos,word width,word height,byte * conversion_table);
void Display_part_of_screen_tall2 (word width,word height,word image_width);
void Display_line_on_screen_tall2 (word x_pos,word y_pos,word width,byte * line);
void Read_line_screen_tall2 (word x_pos,word y_pos,word width,byte * line);
void Display_part_of_screen_scaled_tall2(word width,word height,word image_width,byte * buffer);
void Display_brush_color_zoom_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer);
void Display_brush_mono_zoom_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer);
void Clear_brush_scaled_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer);
void Display_brush_tall2 (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_line_on_screen_fast_tall2 (word x_pos,word y_pos,word width,byte * line);

View File

@@ -0,0 +1,533 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#include <string.h>
#include <stdlib.h>
#include <SDL.h>
#include "global.h"
#include "sdlscreen.h"
#include "misc.h"
#include "graph.h"
#include "pxtriple.h"
#define ZOOMX 3
#define ZOOMY 3
#ifdef __VBCC__
#define __attribute__(x)
#endif
void Pixel_triple (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */
{
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 2)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 2)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 2)=color;
}
byte Read_pixel_triple (word x,word y)
/* On retourne la couleur du pixel aux coords données */
{
return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX);
}
void Block_triple (word start_x,word start_y,word width,word height,byte color)
/* On affiche un rectangle de la couleur donnée */
{
SDL_Rect rectangle;
rectangle.x=start_x*ZOOMX;
rectangle.y=start_y*ZOOMY;
rectangle.w=width*ZOOMX;
rectangle.h=height*ZOOMY;
SDL_FillRect(Screen_SDL,&rectangle,color);
}
void Display_part_of_screen_triple (word width,word height,word image_width)
/* Afficher une partie de l'image telle quelle sur l'écran */
{
byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest)
byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src)
int y;
int dy;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
// On fait une copie de la ligne
for (dy=width;dy>0;dy--)
{
*(dest+2)=*(dest+1)=*dest=*src;
src++;
dest+=ZOOMX;
}
// On double la ligne qu'on vient de copier
memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On la triple
memcpy(dest-width*ZOOMX+2*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
//Update_rect(0,0,width,height);
}
void Pixel_preview_normal_triple (word x,word y,byte color)
/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image
* dans l'écran, en mode normal (pas en mode loupe)
* Note: si on modifie cette procédure, il faudra penser à faire également
* la modif dans la procédure Pixel_Preview_Loupe_SDL. */
{
// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0)
Pixel_triple(x-Main_offset_X,y-Main_offset_Y,color);
}
void Pixel_preview_magnifier_triple (word x,word y,byte color)
{
// Affiche le pixel dans la partie non zoomée
Pixel_triple(x-Main_offset_X,y-Main_offset_Y,color);
// Regarde si on doit aussi l'afficher dans la partie zoomée
if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom
&& x >= Limit_left_zoom && x <= Limit_visible_right_zoom)
{
// On est dedans
int height;
int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y);
if (Menu_Y - y_zoom < Main_magnifier_factor)
// On ne doit dessiner qu'un morceau du pixel
// sinon on dépasse sur le menu
height = Menu_Y - y_zoom;
else
height = Main_magnifier_factor;
Block_triple(
Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom,
y_zoom, Main_magnifier_factor, height, color
);
}
}
void Horizontal_XOR_line_triple(word x_pos,word y_pos,word width)
{
//On calcule la valeur initiale de dest:
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels;
int x;
for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+2*VIDEO_LINE_WIDTH+2)=*(dest+x+2*VIDEO_LINE_WIDTH+1)=*(dest+x+2*VIDEO_LINE_WIDTH)=*(dest+x+VIDEO_LINE_WIDTH+2)=*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+2)=*(dest+x+1)=*(dest+x)=~*(dest+x);
}
void Vertical_XOR_line_triple(word x_pos,word y_pos,word height)
{
int i;
byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
for (i=height;i>0;i--)
{
*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=~*dest;
dest+=VIDEO_LINE_WIDTH*ZOOMY;
}
}
void Display_brush_color_triple(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = Brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+2*VIDEO_LINE_WIDTH+2) = *(dest+2*VIDEO_LINE_WIDTH+1) = *(dest+2*VIDEO_LINE_WIDTH) = *(dest+VIDEO_LINE_WIDTH+2) = *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+2) = *(dest+1) = *dest = *src;
}
// Pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_brush_mono_triple(word x_pos, word y_pos,
word x_offset, word y_offset, word width, word height,
byte transp_color, byte color, word brush_width)
/* On affiche la brosse en monochrome */
{
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à
// l'écran
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse
int x,y;
for(y=height;y!=0;y--)
//Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
if (*src!=transp_color)
*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=color;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=brush_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Clear_brush_triple(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width)
{
byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest)
byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src)
int y;
int x;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=*src;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
// Affiche une brosse (arbitraire) à l'écran
void Display_brush_triple(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=*src;
}
// Pixel suivant
src++; dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
}
void Remap_screen_triple(word x_pos,word y_pos,word width,word height,byte * conversion_table)
{
// dest = coords a l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
int x,y;
// Pour chaque ligne
for(y=height;y>0;y--)
{
// Pour chaque pixel
for(x=width;x>0;x--)
{
*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=
conversion_table[*dest];
dest +=ZOOMX;
}
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_line_on_screen_fast_triple(word x_pos,word y_pos,word width,byte * line)
/* On affiche toute une ligne de pixels telle quelle. */
/* Utilisée si le buffer contient déja des pixel doublés. */
{
memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+2)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
}
void Display_line_on_screen_triple(word x_pos,word y_pos,word width,byte * line)
/* On affiche une ligne de pixels en les doublant. */
{
int x;
byte *dest;
dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH;
for(x=width;x>0;x--)
{
*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=*line;
dest+=ZOOMX;
line++;
}
}
void Display_transparent_mono_line_on_screen_triple(
word x_pos, word y_pos, word width, byte* line,
byte transp_color, byte color)
// Affiche une ligne à l'écran avec une couleur + transparence.
// Utilisé par les brosses en mode zoom
{
byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX;
int x;
// Pour chaque pixel
for(x=0;x<width;x++)
{
if (transp_color!=*line)
{
*(dest+2)=*(dest+1)=*dest=color;
}
line ++; // Pixel suivant
dest+=ZOOMX;
}
}
void Read_line_screen_triple(word x_pos,word y_pos,word width,byte * line)
{
memcpy(line,VIDEO_LINE_WIDTH*ZOOMY * y_pos + x_pos * ZOOMX + Screen_pixels,width*ZOOMX);
}
void Display_part_of_screen_scaled_triple(
word width, // width non zoomée
word height, // height zoomée
word image_width,byte * buffer)
{
byte* src = Main_screen + Main_magnifier_offset_Y * image_width
+ Main_magnifier_offset_X;
int y = 0; // Ligne en cours de traitement
// Pour chaque ligne à zoomer
while(1)
{
int x;
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
// On l'affiche Facteur fois, sur des lignes consécutives
x = Main_magnifier_factor/**ZOOMY*/;
// Pour chaque ligne
do{
// On affiche la ligne zoomée
Display_line_on_screen_fast_triple(
Main_X_zoom, y, width*Main_magnifier_factor,
buffer
);
// On passe à la suivante
y++;
if(y==height/**ZOOMY*/)
{
Redraw_grid(Main_X_zoom,0,
width*Main_magnifier_factor,height);
Update_rect(Main_X_zoom,0,
width*Main_magnifier_factor,height);
return;
}
x--;
}while (x > 0);
src += image_width;
}
// ATTENTION on n'arrive jamais ici !
}
// Affiche une partie de la brosse couleur zoomée
void Display_brush_color_zoom_triple(word x_pos,word y_pos,
word x_offset,word y_offset,
word width, // width non zoomée
word end_y_pos,byte transp_color,
word brush_width, // width réelle de la brosse
byte * buffer)
{
byte* src = Brush+y_offset*brush_width + x_offset;
word y = y_pos;
byte bx;
// Pour chaque ligne
while(1)
{
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche facteur fois la ligne zoomée
for(bx=Main_magnifier_factor;bx>0;bx--)
{
byte* line_src = buffer;
byte* dest = Screen_pixels + y*ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
word x;
// Pour chaque pixel de la ligne
for(x = width*Main_magnifier_factor;x > 0;x--)
{
if(*line_src!=transp_color)
{
*(dest+2)=*(dest+1)=*dest = *line_src;
}
line_src++;
dest+=ZOOMX;
}
// Double the line
memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
// Triple the line
memcpy(Screen_pixels + (y*ZOOMY+2)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
y++;
if(y==end_y_pos)
{
return;
}
}
src += brush_width;
}
// ATTENTION zone jamais atteinte
}
void Display_brush_mono_zoom_triple(word x_pos, word y_pos,
word x_offset, word y_offset,
word width, // width non zoomée
word end_y_pos,
byte transp_color, byte color,
word brush_width, // width réelle de la brosse
byte * buffer
)
{
byte* src = Brush + y_offset * brush_width + x_offset;
int y=y_pos*ZOOMY;
//Pour chaque ligne à zoomer :
while(1)
{
int bx;
// src = Ligne originale
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche la ligne Facteur fois à l'écran (sur des
// lignes consécutives)
bx = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne écran
do
{
// On affiche la ligne zoomée
Display_transparent_mono_line_on_screen_triple(
x_pos, y, width * Main_magnifier_factor,
buffer, transp_color, color
);
// On passe à la ligne suivante
y++;
// On vérifie qu'on est pas à la ligne finale
if(y == end_y_pos*ZOOMY)
{
Redraw_grid( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
Update_rect( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
return;
}
bx --;
}
while (bx > 0);
// Passage à la ligne suivante dans la brosse aussi
src+=brush_width;
}
}
void Clear_brush_scaled_triple(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer)
{
// En fait on va recopier l'image non zoomée dans la partie zoomée !
byte* src = Main_screen + y_offset * image_width + x_offset;
int y = y_pos;
int bx;
// Pour chaque ligne à zoomer
while(1){
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
bx=Main_magnifier_factor;
// Pour chaque ligne
do{
// TODO a verifier
Display_line_on_screen_fast_triple(x_pos,y,
width * Main_magnifier_factor,buffer);
// Ligne suivante
y++;
if(y==end_y_pos)
{
Redraw_grid(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
Update_rect(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
return;
}
bx--;
}while(bx!=0);
src+= image_width;
}
}

View File

@@ -0,0 +1,50 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 pxtriple.h
/// Renderer for triple pixels (3x3).
//////////////////////////////////////////////////////////////////////////////
#include "struct.h"
void Pixel_triple (word x,word y,byte color);
byte Read_pixel_triple (word x,word y);
void Block_triple (word start_x,word start_y,word width,word height,byte color);
void Pixel_preview_normal_triple (word x,word y,byte color);
void Pixel_preview_magnifier_triple (word x,word y,byte color);
void Horizontal_XOR_line_triple (word x_pos,word y_pos,word width);
void Vertical_XOR_line_triple (word x_pos,word y_pos,word height);
void Display_brush_color_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_brush_mono_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width);
void Clear_brush_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width);
void Remap_screen_triple (word x_pos,word y_pos,word width,word height,byte * conversion_table);
void Display_part_of_screen_triple (word width,word height,word image_width);
void Display_line_on_screen_triple (word x_pos,word y_pos,word width,byte * line);
void Read_line_screen_triple (word x_pos,word y_pos,word width,byte * line);
void Display_part_of_screen_scaled_triple(word width,word height,word image_width,byte * buffer);
void Display_brush_color_zoom_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer);
void Display_brush_mono_zoom_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer);
void Clear_brush_scaled_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer);
void Display_brush_triple (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_line_on_screen_fast_triple (word x_pos,word y_pos,word width,byte * line);

View File

@@ -0,0 +1,519 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#include <string.h>
#include <stdlib.h>
#include <SDL.h>
#include "global.h"
#include "sdlscreen.h"
#include "misc.h"
#include "graph.h"
#include "pxwide.h"
#define ZOOMX 2
#define ZOOMY 1
#ifdef __VBCC__
#define __attribute__(x)
#endif
void Pixel_wide (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */
{
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color;
}
byte Read_pixel_wide (word x,word y)
/* On retourne la couleur du pixel aux coords données */
{
return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX);
}
void Block_wide (word start_x,word start_y,word width,word height,byte color)
/* On affiche un rectangle de la couleur donnée */
{
SDL_Rect rectangle;
rectangle.x=start_x*ZOOMX;
rectangle.y=start_y*ZOOMY;
rectangle.w=width*ZOOMX;
rectangle.h=height*ZOOMY;
SDL_FillRect(Screen_SDL,&rectangle,color);
}
void Display_part_of_screen_wide (word width,word height,word image_width)
/* Afficher une partie de l'image telle quelle sur l'écran */
{
byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest)
byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src)
int y;
int dy;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
// On fait une copie de la ligne
for (dy=width;dy>0;dy--)
{
*(dest+1)=*dest=*src;
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
//Update_rect(0,0,width,height);
}
void Pixel_preview_normal_wide (word x,word y,byte color)
/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image
* dans l'écran, en mode normal (pas en mode loupe)
* Note: si on modifie cette procédure, il faudra penser à faire également
* la modif dans la procédure Pixel_Preview_Loupe_SDL. */
{
// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0)
Pixel_wide(x-Main_offset_X,y-Main_offset_Y,color);
}
void Pixel_preview_magnifier_wide (word x,word y,byte color)
{
// Affiche le pixel dans la partie non zoomée
Pixel_wide(x-Main_offset_X,y-Main_offset_Y,color);
// Regarde si on doit aussi l'afficher dans la partie zoomée
if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom
&& x >= Limit_left_zoom && x <= Limit_visible_right_zoom)
{
// On est dedans
int height;
int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y);
if (Menu_Y - y_zoom < Main_magnifier_factor)
// On ne doit dessiner qu'un morceau du pixel
// sinon on dépasse sur le menu
height = Menu_Y - y_zoom;
else
height = Main_magnifier_factor;
Block_wide(
Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom,
y_zoom, Main_magnifier_factor, height, color
);
}
}
void Horizontal_XOR_line_wide(word x_pos,word y_pos,word width)
{
//On calcule la valeur initiale de dest:
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels;
int x;
for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+1)=*(dest+x)=~*(dest+x);
}
void Vertical_XOR_line_wide(word x_pos,word y_pos,word height)
{
int i;
byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
for (i=height;i>0;i--)
{
*dest=*(dest+1)=~*dest;
dest+=VIDEO_LINE_WIDTH*ZOOMY;
}
}
void Display_brush_color_wide(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = Brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+1) = *dest = *src;
}
// Pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_brush_mono_wide(word x_pos, word y_pos,
word x_offset, word y_offset, word width, word height,
byte transp_color, byte color, word brush_width)
/* On affiche la brosse en monochrome */
{
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à
// l'écran
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse
int x,y;
for(y=height;y!=0;y--)
//Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
if (*src!=transp_color)
*(dest+1)=*dest=color;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=brush_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Clear_brush_wide(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width)
{
byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest)
byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src)
int y;
int x;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
*(dest+1)=*dest=*src;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
// Affiche une brosse (arbitraire) à l'écran
void Display_brush_wide(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+1) = *dest = *src;
}
// Pixel suivant
src++; dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
}
void Remap_screen_wide(word x_pos,word y_pos,word width,word height,byte * conversion_table)
{
// dest = coords a l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
int x,y;
// Pour chaque ligne
for(y=height;y>0;y--)
{
// Pour chaque pixel
for(x=width;x>0;x--)
{
*(dest+1) = *dest = conversion_table[*dest];
dest +=ZOOMX;
}
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_line_on_screen_fast_wide(word x_pos,word y_pos,word width,byte * line)
/* On affiche toute une ligne de pixels telle quelle. */
/* Utilisée si le buffer contient déja des pixel doublés. */
{
memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX);
}
void Display_line_on_screen_wide(word x_pos,word y_pos,word width,byte * line)
/* On affiche une ligne de pixels en les doublant. */
{
int x;
byte *dest;
dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH;
for(x=width;x>0;x--)
{
*(dest+1)=*dest=*line;
dest+=ZOOMX;
line++;
}
}
void Display_transparent_mono_line_on_screen_wide(
word x_pos, word y_pos, word width, byte* line,
byte transp_color, byte color)
// Affiche une ligne à l'écran avec une couleur + transparence.
// Utilisé par les brosses en mode zoom
{
byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX;
int x;
// Pour chaque pixel
for(x=0;x<width;x++)
{
if (transp_color!=*line)
{
*(dest+1)=*dest=color;
}
line ++; // Pixel suivant
dest+=ZOOMX;
}
}
void Read_line_screen_wide(word x_pos,word y_pos,word width,byte * line)
{
memcpy(line,VIDEO_LINE_WIDTH*ZOOMY * y_pos + x_pos * ZOOMX + Screen_pixels,width*ZOOMX);
}
void Display_part_of_screen_scaled_wide(
word width, // width non zoomée
word height, // height zoomée
word image_width,byte * buffer)
{
byte* src = Main_screen + Main_magnifier_offset_Y * image_width
+ Main_magnifier_offset_X;
int y = 0; // Ligne en cours de traitement
// Pour chaque ligne à zoomer
while(1)
{
int x;
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
// On l'affiche Facteur fois, sur des lignes consécutives
x = Main_magnifier_factor;
// Pour chaque ligne
do{
// On affiche la ligne zoomée
Display_line_on_screen_fast_wide(
Main_X_zoom, y, width*Main_magnifier_factor,
buffer
);
// On passe à la suivante
y++;
if(y==height)
{
Redraw_grid(Main_X_zoom,0,
width*Main_magnifier_factor,height);
Update_rect(Main_X_zoom,0,
width*Main_magnifier_factor,height);
return;
}
x--;
}while (x > 0);
src += image_width;
}
// ATTENTION on n'arrive jamais ici !
}
void Display_transparent_line_on_screen_wide(word x_pos,word y_pos,word width,byte* line,byte transp_color)
{
byte* src = line;
byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX;
word x;
// Pour chaque pixel de la ligne
for(x = width;x > 0;x--)
{
if(*src!=transp_color)
{
*(dest+1) = *dest = *src;
}
src++;
dest+=ZOOMX;
}
}
// Affiche une partie de la brosse couleur zoomée
void Display_brush_color_zoom_wide(word x_pos,word y_pos,
word x_offset,word y_offset,
word width, // width non zoomée
word end_y_pos,byte transp_color,
word brush_width, // width réelle de la brosse
byte * buffer)
{
byte* src = Brush+y_offset*brush_width + x_offset;
word y = y_pos;
byte bx;
// Pour chaque ligne
while(1)
{
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche facteur fois la ligne zoomée
for(bx=Main_magnifier_factor;bx>0;bx--)
{
Display_transparent_line_on_screen_wide(x_pos,y*ZOOMY,width*Main_magnifier_factor,buffer,transp_color);
y++;
if(y==end_y_pos)
{
return;
}
}
src += brush_width;
}
// ATTENTION zone jamais atteinte
}
void Display_brush_mono_zoom_wide(word x_pos, word y_pos,
word x_offset, word y_offset,
word width, // width non zoomée
word end_y_pos,
byte transp_color, byte color,
word brush_width, // width réelle de la brosse
byte * buffer
)
{
byte* src = Brush + y_offset * brush_width + x_offset;
int y=y_pos*ZOOMY;
//Pour chaque ligne à zoomer :
while(1)
{
int bx;
// src = Ligne originale
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche la ligne Facteur fois à l'écran (sur des
// lignes consécutives)
bx = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne écran
do
{
// On affiche la ligne zoomée
Display_transparent_mono_line_on_screen_wide(
x_pos, y, width * Main_magnifier_factor,
buffer, transp_color, color
);
// On passe à la ligne suivante
y++;
// On vérifie qu'on est pas à la ligne finale
if(y == end_y_pos*ZOOMY)
{
Redraw_grid( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
Update_rect( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
return;
}
bx --;
}
while (bx > 0);
// Passage à la ligne suivante dans la brosse aussi
src+=brush_width;
}
}
void Clear_brush_scaled_wide(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer)
{
// En fait on va recopier l'image non zoomée dans la partie zoomée !
byte* src = Main_screen + y_offset * image_width + x_offset;
int y = y_pos;
int bx;
// Pour chaque ligne à zoomer
while(1){
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
bx=Main_magnifier_factor;
// Pour chaque ligne
do{
Display_line_on_screen_fast_wide(x_pos,y,
width * Main_magnifier_factor,buffer);
// Ligne suivante
y++;
if(y==end_y_pos)
{
Redraw_grid(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
Update_rect(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
return;
}
bx--;
}while(bx!=0);
src+= image_width;
}
}

View File

@@ -0,0 +1,51 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 pxwide.h
/// Renderer for wide pixels (2x1).
//////////////////////////////////////////////////////////////////////////////
#include "struct.h"
void Pixel_wide (word x,word y,byte color);
byte Read_pixel_wide (word x,word y);
void Block_wide (word start_x,word start_y,word width,word height,byte color);
void Pixel_preview_normal_wide (word x,word y,byte color);
void Pixel_preview_magnifier_wide (word x,word y,byte color);
void Horizontal_XOR_line_wide (word x_pos,word y_pos,word width);
void Vertical_XOR_line_wide (word x_pos,word y_pos,word height);
void Display_brush_color_wide (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_brush_mono_wide (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width);
void Clear_brush_wide (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width);
void Remap_screen_wide (word x_pos,word y_pos,word width,word height,byte * conversion_table);
void Display_part_of_screen_wide (word width,word height,word image_width);
void Display_line_on_screen_wide (word x_pos,word y_pos,word width,byte * line);
void Read_line_screen_wide (word x_pos,word y_pos,word width,byte * line);
void Display_part_of_screen_scaled_wide(word width,word height,word image_width,byte * buffer);
void Display_brush_color_zoom_wide (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer);
void Display_brush_mono_zoom_wide (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer);
void Clear_brush_scaled_wide (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer);
void Display_brush_wide (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_line_on_screen_fast_wide (word x_pos,word y_pos,word width,byte * line);
void Display_transparent_line_on_screen_wide(word x_pos,word y_pos,word width,byte* line,byte transp_color);

View File

@@ -0,0 +1,527 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#include <string.h>
#include <stdlib.h>
#include <SDL.h>
#include "global.h"
#include "sdlscreen.h"
#include "misc.h"
#include "graph.h"
#include "pxwide2.h"
#define ZOOMX 4
#define ZOOMY 2
#ifdef __VBCC__
#define __attribute__(w)
#endif
void Pixel_wide2 (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */
{
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 2)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 3)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 2)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 3)=color;
}
byte Read_pixel_wide2 (word x,word y)
/* On retourne la couleur du pixel aux coords données */
{
return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX);
}
void Block_wide2 (word start_x,word start_y,word width,word height,byte color)
/* On affiche un rectangle de la couleur donnée */
{
SDL_Rect rectangle;
rectangle.x=start_x*ZOOMX;
rectangle.y=start_y*ZOOMY;
rectangle.w=width*ZOOMX;
rectangle.h=height*ZOOMY;
SDL_FillRect(Screen_SDL,&rectangle,color);
}
void Display_part_of_screen_wide2 (word width,word height,word image_width)
/* Afficher une partie de l'image telle quelle sur l'écran */
{
byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest)
byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src)
int y;
int dy;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
// On fait une copie de la ligne
for (dy=width;dy>0;dy--)
{
*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src;
src++;
dest+=ZOOMX;
}
// On double la ligne qu'on vient de copier
memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
//Update_rect(0,0,width,height);
}
void Pixel_preview_normal_wide2 (word x,word y,byte color)
/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image
* dans l'écran, en mode normal (pas en mode loupe)
* Note: si on modifie cette procédure, il faudra penser à faire également
* la modif dans la procédure Pixel_Preview_Loupe_SDL. */
{
// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0)
Pixel_wide2(x-Main_offset_X,y-Main_offset_Y,color);
}
void Pixel_preview_magnifier_wide2 (word x,word y,byte color)
{
// Affiche le pixel dans la partie non zoomée
Pixel_wide2(x-Main_offset_X,y-Main_offset_Y,color);
// Regarde si on doit aussi l'afficher dans la partie zoomée
if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom
&& x >= Limit_left_zoom && x <= Limit_visible_right_zoom)
{
// On est dedans
int height;
int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y);
if (Menu_Y - y_zoom < Main_magnifier_factor)
// On ne doit dessiner qu'un morceau du pixel
// sinon on dépasse sur le menu
height = Menu_Y - y_zoom;
else
height = Main_magnifier_factor;
Block_wide2(
Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom,
y_zoom, Main_magnifier_factor, height, color
);
}
}
void Horizontal_XOR_line_wide2(word x_pos,word y_pos,word width)
{
//On calcule la valeur initiale de dest:
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels;
int x;
for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+VIDEO_LINE_WIDTH+3)=*(dest+x+VIDEO_LINE_WIDTH+2)=*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+3)=*(dest+x+2)=*(dest+x+1)=*(dest+x)=~*(dest+x);
}
void Vertical_XOR_line_wide2(word x_pos,word y_pos,word height)
{
int i;
byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
for (i=height;i>0;i--)
{
*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*(dest)=~*(dest);
dest+=VIDEO_LINE_WIDTH*ZOOMY;
}
}
void Display_brush_color_wide2(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = Brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+VIDEO_LINE_WIDTH+3) = *(dest+VIDEO_LINE_WIDTH+2) = *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+3) = *(dest+2) = *(dest+1) = *dest = *src;
}
// Pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_brush_mono_wide2(word x_pos, word y_pos,
word x_offset, word y_offset, word width, word height,
byte transp_color, byte color, word brush_width)
/* On affiche la brosse en monochrome */
{
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à
// l'écran
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse
int x,y;
for(y=height;y!=0;y--)
//Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
if (*src!=transp_color)
*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=color;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=brush_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Clear_brush_wide2(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width)
{
byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest)
byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src)
int y;
int x;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
// Affiche une brosse (arbitraire) à l'écran
void Display_brush_wide2(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src;
}
// Pixel suivant
src++; dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
}
void Remap_screen_wide2(word x_pos,word y_pos,word width,word height,byte * conversion_table)
{
// dest = coords a l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
int x,y;
// Pour chaque ligne
for(y=height;y>0;y--)
{
// Pour chaque pixel
for(x=width;x>0;x--)
{
*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=
conversion_table[*dest];
dest +=ZOOMX;
}
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_line_on_screen_fast_wide2(word x_pos,word y_pos,word width,byte * line)
/* On affiche toute une ligne de pixels telle quelle. */
/* Utilisée si le buffer contient déja des pixel doublés. */
{
memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
}
void Display_line_on_screen_wide2(word x_pos,word y_pos,word width,byte * line)
/* On affiche une ligne de pixels en les doublant. */
{
int x;
byte *dest;
dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH;
for(x=width;x>0;x--)
{
*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*line;
dest+=ZOOMX;
line++;
}
}
void Display_transparent_mono_line_on_screen_wide2(
word x_pos, word y_pos, word width, byte* line,
byte transp_color, byte color)
// Affiche une ligne à l'écran avec une couleur + transparence.
// Utilisé par les brosses en mode zoom
{
byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX;
int x;
// Pour chaque pixel
for(x=0;x<width;x++)
{
if (transp_color!=*line)
{
*(dest+3)=*(dest+2)=*(dest+1)=*dest=color;
}
line ++; // Pixel suivant
dest+=ZOOMX;
}
}
void Read_line_screen_wide2(word x_pos,word y_pos,word width,byte * line)
{
memcpy(line,VIDEO_LINE_WIDTH*ZOOMY * y_pos + x_pos * ZOOMX + Screen_pixels,width*ZOOMX);
}
void Display_part_of_screen_scaled_wide2(
word width, // width non zoomée
word height, // height zoomée
word image_width,byte * buffer)
{
byte* src = Main_screen + Main_magnifier_offset_Y * image_width
+ Main_magnifier_offset_X;
int y = 0; // Ligne en cours de traitement
// Pour chaque ligne à zoomer
while(1)
{
int x;
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
// On l'affiche Facteur fois, sur des lignes consécutives
x = Main_magnifier_factor/**ZOOMY*/;
// Pour chaque ligne
do{
// On affiche la ligne zoomée
Display_line_on_screen_fast_wide2(
Main_X_zoom, y, width*Main_magnifier_factor,
buffer
);
// On passe à la suivante
y++;
if(y==height/**ZOOMY*/)
{
Redraw_grid(Main_X_zoom,0,
width*Main_magnifier_factor,height);
Update_rect(Main_X_zoom,0,
width*Main_magnifier_factor,height);
return;
}
x--;
}while (x > 0);
src += image_width;
}
// ATTENTION on n'arrive jamais ici !
}
// Affiche une partie de la brosse couleur zoomée
void Display_brush_color_zoom_wide2(word x_pos,word y_pos,
word x_offset,word y_offset,
word width, // width non zoomée
word end_y_pos,byte transp_color,
word brush_width, // width réelle de la brosse
byte * buffer)
{
byte* src = Brush+y_offset*brush_width + x_offset;
word y = y_pos;
byte bx;
// Pour chaque ligne
while(1)
{
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche facteur fois la ligne zoomée
for(bx=Main_magnifier_factor;bx>0;bx--)
{
byte* line_src = buffer;
byte* dest = Screen_pixels + y*ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
word x;
// Pour chaque pixel de la ligne
for(x = width*Main_magnifier_factor;x > 0;x--)
{
if(*line_src!=transp_color)
{
*(dest+3)=*(dest+2)=*(dest+1)=*dest = *line_src;
}
line_src++;
dest+=ZOOMX;
}
// Double the line
memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
y++;
if(y==end_y_pos)
{
return;
}
}
src += brush_width;
}
// ATTENTION zone jamais atteinte
}
void Display_brush_mono_zoom_wide2(word x_pos, word y_pos,
word x_offset, word y_offset,
word width, // width non zoomée
word end_y_pos,
byte transp_color, byte color,
word brush_width, // width réelle de la brosse
byte * buffer
)
{
byte* src = Brush + y_offset * brush_width + x_offset;
int y=y_pos*ZOOMY;
//Pour chaque ligne à zoomer :
while(1)
{
int bx;
// src = Ligne originale
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche la ligne Facteur fois à l'écran (sur des
// lignes consécutives)
bx = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne écran
do
{
// On affiche la ligne zoomée
Display_transparent_mono_line_on_screen_wide2(
x_pos, y, width * Main_magnifier_factor,
buffer, transp_color, color
);
// On passe à la ligne suivante
y++;
// On vérifie qu'on est pas à la ligne finale
if(y == end_y_pos*ZOOMY)
{
Redraw_grid( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
Update_rect( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
return;
}
bx --;
}
while (bx > 0);
// Passage à la ligne suivante dans la brosse aussi
src+=brush_width;
}
}
void Clear_brush_scaled_wide2(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer)
{
// En fait on va recopier l'image non zoomée dans la partie zoomée !
byte* src = Main_screen + y_offset * image_width + x_offset;
int y = y_pos;
int bx;
// Pour chaque ligne à zoomer
while(1){
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
bx=Main_magnifier_factor;
// Pour chaque ligne
do{
// TODO a verifier
Display_line_on_screen_fast_wide2(x_pos,y,
width * Main_magnifier_factor,buffer);
// Ligne suivante
y++;
if(y==end_y_pos)
{
Redraw_grid(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
Update_rect(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
return;
}
bx--;
}while(bx!=0);
src+= image_width;
}
}

View File

@@ -0,0 +1,50 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 pxwide2.h
/// Renderer for double-wide pixels (4x2).
//////////////////////////////////////////////////////////////////////////////
#include "struct.h"
void Pixel_wide2 (word x,word y,byte color);
byte Read_pixel_wide2 (word x,word y);
void Block_wide2 (word start_x,word start_y,word width,word height,byte color);
void Pixel_preview_normal_wide2 (word x,word y,byte color);
void Pixel_preview_magnifier_wide2 (word x,word y,byte color);
void Horizontal_XOR_line_wide2 (word x_pos,word y_pos,word width);
void Vertical_XOR_line_wide2 (word x_pos,word y_pos,word height);
void Display_brush_color_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_brush_mono_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width);
void Clear_brush_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width);
void Remap_screen_wide2 (word x_pos,word y_pos,word width,word height,byte * conversion_table);
void Display_part_of_screen_wide2 (word width,word height,word image_width);
void Display_line_on_screen_wide2 (word x_pos,word y_pos,word width,byte * line);
void Read_line_screen_wide2 (word x_pos,word y_pos,word width,byte * line);
void Display_part_of_screen_scaled_wide2(word width,word height,word image_width,byte * buffer);
void Display_brush_color_zoom_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer);
void Display_brush_mono_zoom_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer);
void Clear_brush_scaled_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer);
void Display_brush_wide2 (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_line_on_screen_fast_wide2 (word x_pos,word y_pos,word width,byte * line);

View File

@@ -0,0 +1,980 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Peter Gordon
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "const.h"
#include "errors.h"
#include "global.h"
#include "misc.h"
#include "readini.h"
#include "setup.h"
#include "realpath.h"
#include "io.h"
void Load_INI_clear_string(char * str, byte keep_comments)
{
int index;
int equal_found=0;
for (index=0;str[index]!='\0';)
{
if ((str[index]=='='))
{
equal_found=1;
index++;
// On enleve les espaces après le '='
while (str[index]==' ' || str[index]=='\t')
memmove(str+index,str+index+1,strlen(str+index));
}
else if ((str[index]==' ' && !equal_found) || (str[index]=='\t'))
{
// Suppression d'un espace ou d'un tab:
memmove(str+index,str+index+1,strlen(str+index));
}
else
if (!keep_comments && ((str[index]==';') || (str[index]=='#')))
{
// Comment
str[index]='\0';
}
else if ((str[index]=='\r') || (str[index]=='\n'))
{
// Line break
str[index]='\0';
}
else
{
if (!equal_found)
{
// Passage en majuscule d'un caractère:
str[index]=toupper((int)str[index]);
}
index++;
}
}
// On enlève les espaces avant la fin de chaine
while (index>0 && (str[index-1]==' ' || str[index-1]=='\t'))
{
index--;
str[index]='\0';
}
}
int Load_INI_seek_pattern(char * buffer,char * pattern)
{
int buffer_index;
int pattern_index;
// A partir de chaque lettre de la chaîne buffer
for (buffer_index=0;buffer[buffer_index]!='\0';buffer_index++)
{
// On regarde si la chaîne pattern est équivalente à la position courante
// de la chaîne buffer:
for (pattern_index=0;(pattern[pattern_index]!='\0') && (buffer[buffer_index+pattern_index]==pattern[pattern_index]);pattern_index++);
// Si on a trouvé la chaîne pattern dans la chaîne buffer, on renvoie la
// position à laquelle on l'a trouvée (+1 pour que si on la trouve au
// début ça ne renvoie pas la même chose que si on ne l'avait pas
// trouvée):
if (pattern[pattern_index]=='\0')
return (buffer_index+1);
}
// Si on ne l'a pas trouvée, on renvoie 0:
return 0;
}
int Load_INI_reach_group(FILE * file,char * buffer,char * group)
{
int stop_seek;
char * group_upper;
char * upper_buffer;
// On alloue les zones de mémoire:
group_upper=(char *)malloc(1024);
upper_buffer=(char *)malloc(1024);
// On commence par se faire une version majuscule du groupe à rechercher:
strcpy(group_upper,group);
Load_INI_clear_string(group_upper, 0);
stop_seek=0;
do
{
// On lit une ligne dans le fichier:
if (fgets(buffer,1024,file)==0)
{
free(upper_buffer);
free(group_upper);
return ERROR_INI_CORRUPTED;
}
Line_number_in_INI_file++;
// On s'en fait une version en majuscule:
strcpy(upper_buffer,buffer);
Load_INI_clear_string(upper_buffer, 0);
// On compare la chaîne avec le groupe recherché:
stop_seek=Load_INI_seek_pattern(upper_buffer,group_upper);
}
while (!stop_seek);
free(upper_buffer);
free(group_upper);
return 0;
}
///
/// Find the next string in the .INI file.
/// @param file INI file currently opened
/// @param buffer Current text buffer, preserved from one call to the next
/// @param option_name string to search
/// @param return_code the found value will be copied there. (must be allocaed)
/// @param raw_text Boolean: true to return the raw value (up to end-of-line), false to strip comments.
int Load_INI_get_string(FILE * file,char * buffer,char * option_name,char * return_code, byte raw_text)
{
int stop_seek;
char * option_upper;
char * upper_buffer;
int buffer_index;
// On alloue les zones de mémoire:
option_upper=(char *)malloc(1024);
upper_buffer=(char *)malloc(1024);
// On commence par se faire une version majuscule de l'option à rechercher:
strcpy(option_upper,option_name);
Load_INI_clear_string(option_upper, 0);
stop_seek=0;
do
{
// On lit une ligne dans le fichier:
if (fgets(buffer,1024,file)==NULL)
{
free(upper_buffer);
free(option_upper);
return ERROR_INI_CORRUPTED;
}
Line_number_in_INI_file++;
// On s'en fait une version en majuscule:
strcpy(upper_buffer,buffer);
Load_INI_clear_string(upper_buffer, raw_text);
// On compare la chaîne avec l'option recherchée:
stop_seek=Load_INI_seek_pattern(upper_buffer,option_upper);
// Si on l'a trouvée:
if (stop_seek)
{
// On se positionne juste après la chaîne "="
buffer_index=Load_INI_seek_pattern(upper_buffer,"=");
strcpy(return_code, upper_buffer + buffer_index);
}
}
while (!stop_seek);
free(upper_buffer);
free(option_upper);
return 0;
}
int Load_INI_get_value(char * str,int * index,int * value)
{
int negative = 0;
// On teste si la valeur actuelle est YES (ou Y):
if (Load_INI_seek_pattern(str+(*index),"yes,")==1)
{
(*value)=1;
(*index)+=4;
return 0;
}
if (strcmp(str+(*index),"yes")==0)
{
(*value)=1;
(*index)+=3;
return 0;
}
if (Load_INI_seek_pattern(str+(*index),"y,")==1)
{
(*value)=1;
(*index)+=2;
return 0;
}
if (strcmp(str+(*index),"y")==0)
{
(*value)=1;
(*index)+=1;
return 0;
}
// On teste si la valeur actuelle est NO (ou N):
if (Load_INI_seek_pattern(str+(*index),"no,")==1)
{
(*value)=0;
(*index)+=3;
return 0;
}
if (strcmp(str+(*index),"no")==0)
{
(*value)=0;
(*index)+=2;
return 0;
}
if (Load_INI_seek_pattern(str+(*index),"n,")==1)
{
(*value)=0;
(*index)+=2;
return 0;
}
if (strcmp(str+(*index),"n")==0)
{
(*value)=0;
(*index)+=1;
return 0;
}
if (str[*index]=='$')
{
(*value)=0;
for (;;)
{
(*index)++;
if ((str[*index]>='0') && (str[*index]<='9'))
(*value)=((*value)*16)+str[*index]-'0';
else
if ((str[*index]>='A') && (str[*index]<='F'))
(*value)=((*value)*16)+str[*index]-'A'+10;
else
if (str[*index]==',')
{
(*index)++;
return 0;
}
else
if (str[*index]=='\0')
return 0;
else
return ERROR_INI_CORRUPTED;
}
}
if (str[*index]=='-')
{
negative = 1;
// next character
(*index)++;
// Fall thru
}
if ((str[*index]>='0') && (str[*index]<='9'))
{
(*value)=0;
for (;;)
{
if ((str[*index]>='0') && (str[*index]<='9'))
{
(*value)=((*value)*10)+str[*index]-'0';
if (negative)
{
(*value)*= -1;
// This is to do it once per number.
negative = 0;
}
}
else
if (str[*index]==',')
{
(*index)++;
return 0;
}
else
if (str[*index]=='\0')
return 0;
else
return ERROR_INI_CORRUPTED;
(*index)++;
}
}
else
return ERROR_INI_CORRUPTED;
}
int Load_INI_get_values(FILE * file,char * buffer,char * option_name,int nb_expected_values,int * values)
{
int stop_seek;
char * option_upper;
char * upper_buffer;
int buffer_index;
int nb_values;
// On alloue les zones de mémoire:
option_upper=(char *)malloc(1024);
upper_buffer=(char *)malloc(1024);
// On commence par se faire une version majuscule de l'option à rechercher:
strcpy(option_upper,option_name);
Load_INI_clear_string(option_upper, 0);
stop_seek=0;
do
{
// On lit une ligne dans le fichier:
if (fgets(buffer,1024,file)==0)
{
free(upper_buffer);
free(option_upper);
return ERROR_INI_CORRUPTED;
}
Line_number_in_INI_file++;
// On s'en fait une version en majuscule:
strcpy(upper_buffer,buffer);
Load_INI_clear_string(upper_buffer, 0);
// On compare la chaîne avec l'option recherchée:
stop_seek=Load_INI_seek_pattern(upper_buffer,option_upper);
// Si on l'a trouvée:
if (stop_seek)
{
nb_values=0;
// On se positionne juste après la chaîne "="
buffer_index=Load_INI_seek_pattern(upper_buffer,"=");
// Tant qu'on a pas atteint la fin de la ligne
while (upper_buffer[buffer_index]!='\0')
{
if (Load_INI_get_value(upper_buffer,&buffer_index,values+nb_values))
{
free(upper_buffer);
free(option_upper);
return ERROR_INI_CORRUPTED;
}
if ( ((++nb_values) == nb_expected_values) &&
(upper_buffer[buffer_index]!='\0') )
{
// Too many values !
free(upper_buffer);
free(option_upper);
return ERROR_INI_CORRUPTED;
}
}
if (nb_values<nb_expected_values)
{
// Not enough values !
free(upper_buffer);
free(option_upper);
return ERROR_INI_CORRUPTED;
}
}
}
while (!stop_seek);
free(upper_buffer);
free(option_upper);
return 0;
}
int Load_INI(T_Config * conf)
{
FILE * file;
char * buffer;
int values[3];
int index;
char * filename;
int return_code;
char value_label[1024];
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:
buffer=(char *)malloc(1024);
filename=(char *)malloc(256);
// On calcule le nom du fichier qu'on manipule:
strcpy(filename,Config_directory);
strcat(filename,INI_FILENAME);
file=fopen(filename,"r");
if (file==0)
{
// Si le fichier ini est absent on le relit depuis gfx2def.ini
strcpy(filename,Data_directory);
strcat(filename,INIDEF_FILENAME);
file=fopen(filename,"r");
if (file == 0)
{
free(filename);
free(buffer);
return ERROR_INI_MISSING;
}
}
if ((return_code=Load_INI_reach_group(file,buffer,"[MOUSE]")))
goto Erreur_Retour;
if ((return_code=Load_INI_get_values (file,buffer,"X_sensitivity",1,values)))
goto Erreur_Retour;
if ((values[0]<1) || (values[0]>4))
conf->Mouse_sensitivity_index_x=1;
else
conf->Mouse_sensitivity_index_x=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Y_sensitivity",1,values)))
goto Erreur_Retour;
if ((values[0]<1) || (values[0]>4))
conf->Mouse_sensitivity_index_y=1;
else
conf->Mouse_sensitivity_index_y=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"X_correction_factor",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>4))
goto Erreur_ERREUR_INI_CORROMPU;
// Deprecated setting, unused
if ((return_code=Load_INI_get_values (file,buffer,"Y_correction_factor",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>4))
goto Erreur_ERREUR_INI_CORROMPU;
// Deprecated setting, unused
if ((return_code=Load_INI_get_values (file,buffer,"Cursor_aspect",1,values)))
goto Erreur_Retour;
if ((values[0]<1) || (values[0]>3))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Cursor=values[0]-1;
if ((return_code=Load_INI_reach_group(file,buffer,"[MENU]")))
goto Erreur_Retour;
conf->Fav_menu_colors[0].R=0;
conf->Fav_menu_colors[0].G=0;
conf->Fav_menu_colors[0].B=0;
conf->Fav_menu_colors[3].R=255;
conf->Fav_menu_colors[3].G=255;
conf->Fav_menu_colors[3].B=255;
if ((return_code=Load_INI_get_values (file,buffer,"Light_color",3,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>63))
goto Erreur_ERREUR_INI_CORROMPU;
if ((values[1]<0) || (values[1]>63))
goto Erreur_ERREUR_INI_CORROMPU;
if ((values[2]<0) || (values[2]>63))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Fav_menu_colors[2].R=(values[0]<<2)|(values[0]>>4);
conf->Fav_menu_colors[2].G=(values[1]<<2)|(values[1]>>4);
conf->Fav_menu_colors[2].B=(values[2]<<2)|(values[2]>>4);
if ((return_code=Load_INI_get_values (file,buffer,"Dark_color",3,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>63))
goto Erreur_ERREUR_INI_CORROMPU;
if ((values[1]<0) || (values[1]>63))
goto Erreur_ERREUR_INI_CORROMPU;
if ((values[2]<0) || (values[2]>63))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Fav_menu_colors[1].R=(values[0]<<2)|(values[0]>>4);
conf->Fav_menu_colors[1].G=(values[1]<<2)|(values[1]>>4);
conf->Fav_menu_colors[1].B=(values[2]<<2)|(values[2]>>4);
if ((return_code=Load_INI_get_values (file,buffer,"Menu_ratio",1,values)))
goto Erreur_Retour;
if ((values[0]<-4) || (values[0]>2))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Ratio=values[0];
if ((return_code=Load_INI_reach_group(file,buffer,"[FILE_SELECTOR]")))
goto Erreur_Retour;
if ((return_code=Load_INI_get_values (file,buffer,"Show_hidden_files",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Show_hidden_files=values[0]?1:0;
if ((return_code=Load_INI_get_values (file,buffer,"Show_hidden_directories",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Show_hidden_directories=values[0]?1:0;
/* if ((return_code=Load_INI_get_values (file,buffer,"Show_system_directories",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Show_system_directories=values[0]?1:0;
*/
if ((return_code=Load_INI_get_values (file,buffer,"Preview_delay",1,values)))
goto Erreur_Retour;
if ((values[0]<1) || (values[0]>256))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Timer_delay=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Maximize_preview",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Maximize_preview=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Find_file_fast",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>2))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Find_file_fast=values[0];
if ((return_code=Load_INI_reach_group(file,buffer,"[LOADING]")))
goto Erreur_Retour;
if ((return_code=Load_INI_get_values (file,buffer,"Auto_set_resolution",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Auto_set_res=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Set_resolution_according_to",1,values)))
goto Erreur_Retour;
if ((values[0]<1) || (values[0]>2))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Set_resolution_according_to=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Clear_palette",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Clear_palette=values[0];
if ((return_code=Load_INI_reach_group(file,buffer,"[MISCELLANEOUS]")))
goto Erreur_Retour;
if ((return_code=Load_INI_get_values (file,buffer,"Draw_limits",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Display_image_limits=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Adjust_brush_pick",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Adjust_brush_pick=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Coordinates",1,values)))
goto Erreur_Retour;
if ((values[0]<1) || (values[0]>2))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Coords_rel=2-values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Backup",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Backup=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Undo_pages",1,values)))
goto Erreur_Retour;
if ((values[0]<1) || (values[0]>99))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Max_undo_pages=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Gauges_scrolling_speed_Left",1,values)))
goto Erreur_Retour;
if ((values[0]<1) || (values[0]>255))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Delay_left_click_on_slider=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Gauges_scrolling_speed_Right",1,values)))
goto Erreur_Retour;
if ((values[0]<1) || (values[0]>255))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Delay_right_click_on_slider=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Auto_save",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Auto_save=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Vertices_per_polygon",1,values)))
goto Erreur_Retour;
if ((values[0]<2) || (values[0]>16384))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Nb_max_vertices_per_polygon=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Fast_zoom",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Fast_zoom=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Separate_colors",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Separate_colors=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"FX_feedback",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->FX_Feedback=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Safety_colors",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Safety_colors=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Opening_message",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Opening_message=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Clear_with_stencil",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Clear_with_stencil=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Auto_discontinuous",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Auto_discontinuous=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Save_screen_size_in_GIF",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Screen_size_in_GIF=values[0];
if ((return_code=Load_INI_get_values (file,buffer,"Auto_nb_colors_used",1,values)))
goto Erreur_Retour;
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Auto_nb_used=values[0];
// Optionnel, le mode video par défaut (à partir de beta 97.0%)
conf->Default_resolution=0;
if (!Load_INI_get_string (file,buffer,"Default_video_mode",value_label, 0))
{
int mode = Convert_videomode_arg(value_label);
if (mode>=0)
conf->Default_resolution=mode;
}
// Optionnel, les dimensions de la fenêtre (à partir de beta 97.0%)
// Do that only if the first mode is actually windowed (not the case on gp2x for example)
if(Video_mode[0].Fullscreen==0)
{
Video_mode[0].Width = 640;
Video_mode[0].Height = 480;
if (!Load_INI_get_values (file,buffer,"Default_window_size",2,values))
{
if ((values[0]>=320))
Video_mode[0].Width = values[0];
if ((values[1]>=200))
Video_mode[0].Height = values[1];
}
}
conf->Mouse_merge_movement=100;
// Optionnel, paramètre pour grouper les mouvements souris (>98.0%)
if (!Load_INI_get_values (file,buffer,"Merge_movement",1,values))
{
if ((values[0]<0) || (values[0]>1000))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Mouse_merge_movement=values[0];
}
conf->Palette_cells_X=8;
// Optionnel, nombre de colonnes dans la palette (>98.0%)
if (!Load_INI_get_values (file,buffer,"Palette_cells_X",1,values))
{
if ((values[0]<1) || (values[0]>256))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Palette_cells_X=values[0];
}
conf->Palette_cells_Y=8;
// Optionnel, nombre de lignes dans la palette (>98.0%)
if (!Load_INI_get_values (file,buffer,"Palette_cells_Y",1,values))
{
if (values[0]<1 || values[0]>16)
goto Erreur_ERREUR_INI_CORROMPU;
conf->Palette_cells_Y=values[0];
}
// Optionnel, bookmarks (>98.0%)
for (index=0;index<NB_BOOKMARKS;index++)
{
conf->Bookmark_directory[index]=NULL;
conf->Bookmark_label[index][0]='\0';
}
for (index=0;index<NB_BOOKMARKS;index++)
{
if (!Load_INI_get_string (file,buffer,"Bookmark_label",value_label, 1))
{
int size=strlen(value_label);
if (size!=0)
{
if (size>8)
{
value_label[7]=ELLIPSIS_CHARACTER;
value_label[8]='\0';
}
strcpy(conf->Bookmark_label[index],value_label);
}
}
else
break;
if (!Load_INI_get_string (file,buffer,"Bookmark_directory",value_label, 1))
{
int size=strlen(value_label);
if (size!=0)
{
conf->Bookmark_directory[index]=(char *)malloc(size+1);
strcpy(conf->Bookmark_directory[index],value_label);
}
}
else
break;
}
conf->Palette_vertical=0;
// Optional, vertical palette option (>98.0%)
if (!Load_INI_get_values (file,buffer,"Palette_vertical",1,values))
{
if ((values[0]<0) || (values[0]>1))
goto Erreur_ERREUR_INI_CORROMPU;
conf->Palette_vertical=values[0];
}
// Optional, the window position (>98.0%)
conf->Window_pos_x=9999;
conf->Window_pos_y=9999;
if (!Load_INI_get_values (file,buffer,"Window_position",2,values))
{
conf->Window_pos_x = values[0];
conf->Window_pos_y = values[1];
}
conf->Double_click_speed=500;
// Optional, speed of double-click (>2.0)
if (!Load_INI_get_values (file,buffer,"Double_click_speed",1,values))
{
if ((values[0]>0) || (values[0]<=2000))
conf->Double_click_speed=values[0];
}
conf->Double_key_speed=500;
// Optional, speed of double-keypress (>2.0)
if (!Load_INI_get_values (file,buffer,"Double_key_speed",1,values))
{
if ((values[0]>0) || (values[0]<=2000))
conf->Double_key_speed=values[0];
}
// Optional, name of skin file. (>2.0)
if(!Load_INI_get_string(file,buffer,"Skin_file",value_label,1))
{
conf->Skin_file = strdup(value_label);
}
else
conf->Skin_file = strdup("skin_DPaint.png");
// Optional, name of font file. (>2.0)
if(!Load_INI_get_string(file,buffer,"Font_file",value_label,1))
conf->Font_file = strdup(value_label);
else
conf->Font_file = strdup("font_Dpaint.png");
conf->Grid_XOR_color=255;
// Optional, XOR color for grid overlay (>2.0)
if (!Load_INI_get_values (file,buffer,"Grid_XOR_color",1,values))
{
if ((values[0]>0) && (values[0]<=255))
conf->Grid_XOR_color=values[0];
}
// Optional, "fake hardware zoom" factor (>2.1)
if (!Load_INI_get_values (file, buffer,"Pixel_ratio",1,values))
{
Pixel_ratio = values[0];
switch(Pixel_ratio) {
case PIXEL_WIDE:
if(Video_mode[0].Width < 640)
Pixel_ratio = PIXEL_SIMPLE;
break;
case PIXEL_TALL:
if(Video_mode[0].Height < 400)
Pixel_ratio = PIXEL_SIMPLE;
break;
case PIXEL_DOUBLE:
if(Video_mode[0].Width < 640 || Video_mode[0].Height < 400)
Pixel_ratio = PIXEL_SIMPLE;
break;
case PIXEL_TRIPLE:
if(Video_mode[0].Width < 3*320 || Video_mode[0].Height < 3*200)
Pixel_ratio = PIXEL_SIMPLE;
break;
case PIXEL_WIDE2:
if(Video_mode[0].Width < 4*320 || Video_mode[0].Height < 2*200)
Pixel_ratio = PIXEL_SIMPLE;
break;
case PIXEL_TALL2:
if(Video_mode[0].Width < 2*320 || Video_mode[0].Height < 4*200)
Pixel_ratio = PIXEL_SIMPLE;
break;
case PIXEL_QUAD:
if(Video_mode[0].Width < 4*320 || Video_mode[0].Height < 4*200)
Pixel_ratio = PIXEL_SIMPLE;
break;
default:
// Convert back unknown values to PIXEL_SIMPLE
Pixel_ratio = PIXEL_SIMPLE;
break;
}
}
// Optional, Menu bars visibility (> 2.1)
if (!Load_INI_get_values (file, buffer,"Menubars_visible",1,values))
{
int index;
for (index=MENUBAR_STATUS+1; index<MENUBAR_COUNT;index++)
{
// Note that I skip the status bar, always enabled.
Menu_bars[index].Visible = (values[0] & (1<<index)) ? 1 : 0;
}
}
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;
}
}
// Optional, Location of last directory used for Lua scripts browsing (>=2.3)
conf->Scripts_directory[0]='\0';
if (!Load_INI_get_string (file,buffer,"Scripts_directory",value_label, 1))
{
strcpy(conf->Scripts_directory,value_label);
}
if (conf->Scripts_directory[0]=='\0')
{
// Default when empty:
Realpath(Data_directory, conf->Scripts_directory);
Append_path(conf->Scripts_directory, "scripts", NULL);
}
conf->Allow_multi_shortcuts=0;
// Optional, allow or disallow multiple shortcuts on same key (>=2.3)
if (!Load_INI_get_values (file,buffer,"Allow_multi_shortcuts",1,values))
{
conf->Allow_multi_shortcuts=(values[0]!=0);
}
// Insert new values here
fclose(file);
free(filename);
free(buffer);
return 0;
// Gestion des erreurs:
Erreur_Retour:
fclose(file);
free(filename);
free(buffer);
return return_code;
Erreur_ERREUR_INI_CORROMPU:
fclose(file);
free(filename);
free(buffer);
return ERROR_INI_CORRUPTED;
}

View File

@@ -0,0 +1,29 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 readini.h
/// Reading settings in gfx2.ini
//////////////////////////////////////////////////////////////////////////////
int Load_INI(T_Config * conf);
int Load_INI_seek_pattern(char * buffer,char * pattern);
void Load_INI_clear_string(char * str, byte keep_comments);

View File

@@ -0,0 +1,675 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
/************************************************************************
* *
* READLINE (procédure permettant de saisir une chaîne de caractères) *
* *
************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "const.h"
#include "struct.h"
#include "global.h"
#include "misc.h"
#include "errors.h"
#include "const.h"
#include "sdlscreen.h"
#include "readline.h"
#include "windows.h"
#include "input.h"
#include "engine.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 BACKGROUND_COLOR MC_Light
#define CURSOR_COLOR MC_Black
#define CURSOR_BACKGROUND_COLOR MC_Dark
// Suppresion d'un caractère à une certaine POSITION dans une CHAINE.
void Remove_character(char * str, byte position)
{
for (;str[position]!='\0';position++)
str[position]=str[position+1];
}
void Insert_character(char * str, char letter, byte position)
// Insertion d'une LETTRE à une certaine POSITION
// dans une CHAINE d'une certaine TAILLE.
{
char temp_char;
for (;letter!='\0';position++)
{
// On mémorise le caractère qui se trouve en "position"
temp_char=str[position];
// On splotch la lettre à insérer
str[position]=letter;
// On place le caractère mémorisé dans "letter" comme nouvelle lettre à insérer
letter=temp_char;
}
// On termine la chaine
str[position]='\0';
}
int Valid_character(int c)
{
// Sous Linux: Seul le / est strictement interdit, mais beaucoup
// d'autres poseront des problèmes au shell, alors on évite.
// Sous Windows : c'est moins grave car le fopen() échouerait de toutes façons.
// AmigaOS4: Pas de ':' car utilisé pour les volumes.
#if defined(__WIN32__)
char forbidden_char[] = {'/', '|', '?', '*', '<', '>', ':', '\\'};
#elif defined (__amigaos4__)
char forbidden_char[] = {'/', '|', '?', '*', '<', '>', ':'};
#else
char forbidden_char[] = {'/', '|', '?', '*', '<', '>'};
#endif
int position;
if (c < ' ' || c > 255)
return 0;
for (position=0; position<(long)sizeof(forbidden_char); position++)
if (c == forbidden_char[position])
return 0;
return 1;
}
void Display_whole_string(word x_pos,word y_pos,char * str,byte position)
{
char cursor[2];
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);
}
}
/****************************************************************************
* Enhanced super scanf deluxe pro plus giga mieux :-) *
****************************************************************************/
byte Readline(word x_pos,word y_pos,char * str,byte visible_size,byte input_type)
// Paramètres:
// x_pos, y_pos : Coordonnées de la saisie dans la fenêtre
// str : Chaîne recevant la saisie (et contenant éventuellement une valeur initiale)
// max_size : Nombre de caractères logeant dans la zone de saisie
// input_type : 0=Chaîne, 1=Nombre, 2=Nom de fichier
// Sortie:
// 0: Sortie par annulation (Esc.) / 1: sortie par acceptation (Return)
{
byte max_size;
// Grosse astuce pour les noms de fichiers: La taille affichée est différente
// de la taille maximum gérée.
if (input_type == 2)
max_size = 255;
else
max_size = visible_size;
return Readline_ex(x_pos,y_pos,str,visible_size,max_size,input_type,0);
}
/****************************************************************************
* Enhanced super scanf deluxe pro plus giga mieux :-) *
****************************************************************************/
byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_size, byte input_type, byte decimal_places)
// Paramètres:
// x_pos, y_pos : Coordonnées de la saisie dans la fenêtre
// str : Chaîne recevant la saisie (et contenant éventuellement une valeur initiale)
// max_size : Nombre de caractères logeant dans la zone de saisie
// input_type : 0=String, 1=Unsigned int, 2=Filename 3=Signed Double
// decimal_places: Number of decimal places for a double
// Sortie:
// 0: Sortie par annulation (Esc.) / 1: sortie par acceptation (Return)
{
char initial_string[256];
char display_string[256];
byte position;
byte size;
word input_key=0;
byte is_authorized;
word window_x=Window_pos_X;
word window_y=Window_pos_Y;
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.
if (Mouse_K==RIGHT_SIDE)
str[0]='\0';
else if (input_type==INPUT_TYPE_INTEGER && str[0]!='\0')
snprintf(str,10,"%d",atoi(str)); // On tasse la chaine à gauche
else if (input_type==INPUT_TYPE_DECIMAL)
{
// 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.
}
else if (input_type==INPUT_TYPE_HEXA)
{
// Nothing. The caller should have initialized a valid hexa number.
}
// 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;
Hide_cursor();
// 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);
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));
// Mise à jour des variables se rapportant à la chaîne en fonction de la chaîne initiale
strcpy(initial_string,str);
size=strlen(str);
position=(size<max_size)? size:size-1;
if (position-offset>=visible_size)
offset=position-visible_size+1;
// Formatage d'une partie de la chaine (si trop longue pour tenir)
strncpy(display_string, str + offset, visible_size);
display_string[visible_size]='\0';
if (offset>0)
display_string[0]=LEFT_TRIANGLE_CHARACTER;
if (visible_size + offset + 1 < size )
display_string[visible_size-1]=RIGHT_TRIANGLE_CHARACTER;
Display_whole_string(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),display_string,position - offset);
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));
Flush_update();
if (Mouse_K)
{
Display_cursor();
Wait_end_of_click();
Hide_cursor();
}
while ((input_key!=SDLK_RETURN) && (input_key!=KEY_ESC))
{
Display_cursor();
#ifdef VIRT_KEY
if (use_virtual_keyboard)
{
int clicked_button;
clicked_button=Window_clicked_button();
input_key=Key_ANSI;
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();
switch (input_key)
{
case SDLK_DELETE : // Suppr.
if (position<size)
{
Remove_character(str,position);
size--;
// 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;
}
break;
case SDLK_LEFT : // Gauche
if (position>0)
{
// Effacement de la chaîne
if (position==size)
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);
position--;
if (offset > 0 && (position == 0 || position < (offset + 1)))
offset--;
goto affichage;
}
break;
case SDLK_RIGHT : // Droite
if ((position<size) && (position<max_size-1))
{
position++;
//if (position > visible_size + offset - 2)
//if (offset + visible_size < max_size && (position == size || (position > visible_size + offset - 2)))
if (display_string[position-offset]==RIGHT_TRIANGLE_CHARACTER || position-offset>=visible_size)
offset++;
goto affichage;
}
break;
case SDLK_HOME : // Home
if (position)
{
// Effacement de la chaîne
if (position==size)
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);
position = 0;
offset = 0;
goto affichage;
}
break;
case SDLK_END : // End
if ((position<size) && (position<max_size-1))
{
position=(size<max_size)?size:size-1;
if (position-offset>=visible_size)
offset=position-visible_size+1;
goto affichage;
}
break;
case SDLK_BACKSPACE : // Backspace : combinaison de gauche + suppr
if (position)
{
position--;
if (offset > 0 && (position == 0 || position < (offset + 1)))
offset--;
Remove_character(str,position);
size--;
// 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;
}
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 :
break;
case KEY_ESC :
// On restaure la chaine initiale
strcpy(str,initial_string);
size=strlen(str);
break;
default :
if (size<max_size)
{
// On va regarder si l'utilisateur le droit de se servir de cette touche
is_authorized=0; // On commence par supposer qu'elle est interdite
switch(input_type)
{
case INPUT_TYPE_STRING :
if ((input_key>=' ' && input_key<= 255)||input_key=='\n')
is_authorized=1;
break;
case INPUT_TYPE_INTEGER :
if ( (input_key>='0') && (input_key<='9') )
is_authorized=1;
break;
case INPUT_TYPE_DECIMAL:
if ( (input_key>='0') && (input_key<='9') )
is_authorized=1;
else if (input_key=='-' && position==0 && str[0]!='-')
is_authorized=1;
else if (input_key=='.')
is_authorized=1;
break;
case INPUT_TYPE_FILENAME:
// On regarde si la touche est autorisée
if ( Valid_character(input_key))
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)"
// Si la touche était autorisée...
if (is_authorized)
{
// ... alors on l'insère ...
Insert_character(str,input_key,position/*,size*/);
// ce qui augmente la taille de la chaine
size++;
// et qui risque de déplacer le curseur vers la droite
if (size<max_size)
{
position++;
if (display_string[position-offset]==RIGHT_TRIANGLE_CHARACTER || position-offset>=visible_size)
offset++;
}
// Enfin, on raffiche la chaine
goto affichage;
} // End du test d'autorisation de touche
} // End du test de place libre
break;
affichage:
size=strlen(str);
// Formatage d'une partie de la chaine (si trop longue pour tenir)
strncpy(display_string, str + offset, visible_size);
display_string[visible_size]='\0';
if (offset>0)
display_string[0]=LEFT_TRIANGLE_CHARACTER;
if (visible_size + offset + 0 < size )
display_string[visible_size-1]=RIGHT_TRIANGLE_CHARACTER;
Display_whole_string(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),display_string,position - offset);
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));
} // End du "switch(input_key)"
Flush_update();
} // End du "while"
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
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);
// On raffiche la chaine correctement
if (input_type==INPUT_TYPE_INTEGER)
{
if (str[0]=='\0')
{
strcpy(str,"0");
size=1;
}
Print_in_window(x_pos+((max_size-size)<<3),y_pos,str,TEXT_COLOR,BACKGROUND_COLOR);
}
else if (input_type==INPUT_TYPE_DECIMAL)
{
double value;
// Discard extra digits
value = Fround(atof(str), decimal_places);
Sprint_double(str,value,decimal_places,visible_size);
// Recompute updated size
size = strlen(str);
if (size<=visible_size)
Print_in_window(x_pos+((visible_size-size)<<3),y_pos,str,TEXT_COLOR,BACKGROUND_COLOR);
else
Print_in_window_limited(x_pos,y_pos,str,visible_size,TEXT_COLOR,BACKGROUND_COLOR);
}
else
{
Print_in_window_limited(x_pos,y_pos,str,visible_size,TEXT_COLOR,BACKGROUND_COLOR);
}
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));
return (input_key==SDLK_RETURN);
}
void Sprint_double(char *str, double value, byte decimal_places, byte min_positions)
{
int i;
int length;
sprintf(str,"%.*f",decimal_places, value);
length=strlen(str);
for (i=0; i<length; i++)
{
if (str[i]=='.')
{
// Remove extraneous zeroes
char * decimals = str+i+1;
int j;
for (j=strlen(decimals)-1; j >= 0 && decimals[j]=='0'; j--)
{
decimals[j] = '\0';
}
// If all decimals were removed, remove the dot too
if (str[i+1]=='\0')
str[i]='\0';
// Update string length
length=strlen(str);
// Ends the parent loop
break;
}
}
// Now try add spaces at beginning
if (length<min_positions)
{
int offset = min_positions - length;
// Move the string to the right
for (i=0; i<=length; i++)
{
str[length+offset-i] = str[length-i];
}
// Replace the N first characters by spaces
for (i=0; i<offset; i++)
{
str[i] = ' ';
}
}
}

View File

@@ -0,0 +1,64 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 readline.h
/// 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.
/// @param x_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 visible_size Number of characters visible and editable.
/// @param input_type one of enum ::INPUT_TYPE
/// @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);
///
/// 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 y_pos Coordinates of input, in window coordinates before scaling.
/// @param str The original string value (will be modified, unless user cancels.
/// @param visible_size Number of characters visible.
/// @param max_size Number of characters editable.
/// @param input_type one of enum ::INPUT_TYPE
/// @param decimal_places Number of decimal places (used only with decimal type)
/// @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);
///
/// Converts a double to string.
/// @param str Target string, should be pre-allocated and at least 40 characters, to be safe.
/// @param value The number to convert
/// @param decimal_places Number of decimal places to keep. 15 seems the maximum.
/// @param min_positions Minimum number of characters: Will pad spaces on the left to meet this minimum.
void Sprint_double(char *str, double value, byte decimal_places, byte min_positions);

View File

@@ -0,0 +1,121 @@
/* vim:expandtab:ts=2 sw=2:
*/
#define _XOPEN_SOURCE 500
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#if defined(__AROS__)
#include <limits.h>
#endif
#if defined(__AROS__) || defined(__BEOS__) || defined(__MORPHOS__) || defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__) || defined(__amigaos__)
// These platforms don't have realpath().
// We use the following implementation, found in:
// http://amiga.sourceforge.net/amigadevhelp/FUNCTIONS/GeekGadgets/realpath/ex02_realpath.c
//
// When tested on Debian, this piece of code doesn't resolve
// symbolic link in the filename itself, only on the directories in
// the path. So this implementation is limited, it's really better to
// use realpath() if your platform has it.
#if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__) || defined(__amigaos__)
// This is a random default value ...
#define PATH_MAX 32768
#endif
static char *sep(char *path)
{
char *tmp, c;
tmp = strrchr(path, '/');
if(tmp) {
c = tmp[1];
tmp[1] = 0;
if (chdir(path)) {
return NULL;
}
tmp[1] = c;
return tmp + 1;
}
return path;
}
char *Realpath(const char *_path, char *resolved_path)
{
int fd = open(".", O_RDONLY), l;
char current_dir_path[PATH_MAX];
char path[PATH_MAX], lnk[PATH_MAX], *tmp = (char *)"";
if (fd < 0) {
return NULL;
}
getcwd(current_dir_path,PATH_MAX);
strncpy(path, _path, PATH_MAX);
if (chdir(path)) {
if (errno == ENOTDIR) {
#if defined(__WIN32__) || defined(__MORPHOS__) || defined(__amigaos__)
// No symbolic links and no readlink()
l = -1;
#else
l = readlink(path, lnk, PATH_MAX);
#endif
if (!(tmp = sep(path))) {
resolved_path = NULL;
goto abort;
}
if (l < 0) {
if (errno != EINVAL) {
resolved_path = NULL;
goto abort;
}
} else {
lnk[l] = 0;
if (!(tmp = sep(lnk))) {
resolved_path = NULL;
goto abort;
}
}
} else {
resolved_path = NULL;
goto abort;
}
}
if(resolved_path==NULL) // if we called realpath with null as a 2nd arg
resolved_path = (char*) malloc( PATH_MAX );
if (!getcwd(resolved_path, PATH_MAX)) {
resolved_path = NULL;
goto abort;
}
if(strcmp(resolved_path, "/") && *tmp) {
strcat(resolved_path, "/");
}
strcat(resolved_path, tmp);
abort:
chdir(current_dir_path);
close(fd);
return resolved_path;
}
#elif defined (__WIN32__)
// Mingw has a working equivalent. It only has reversed arguments.
char *Realpath(const char *_path, char *resolved_path)
{
return _fullpath(resolved_path,_path,260);
}
#else
// Use the stdlib function.
char *Realpath(const char *_path, char *resolved_path)
{
return realpath(_path, resolved_path);
}
#endif

View File

@@ -0,0 +1,36 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 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 realpath.h
/// Implementation of realpath() that is portable on all our platforms.
//////////////////////////////////////////////////////////////////////////////
#ifndef _REALPATH_H
#define _REALPATH_H
///
/// Makes an absolute filename, resolving symbolic links etc.
/// @param _path Input path
/// @param resolved_path Output path, allocated by caller
/// @return (points to resolved_path)
char *Realpath(const char *_path, char *resolved_path);
#endif

View File

@@ -0,0 +1,735 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Peter Gordon
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "const.h"
#include "global.h"
#include "readini.h"
#include "io.h"
#include "errors.h"
#include "misc.h"
#include "saveini.h"
#include "setup.h"
int Save_INI_reach_group(FILE * old_file,FILE * new_file,char * buffer,char * group)
{
int stop_seek;
char * group_upper;
char * upper_buffer;
// On alloue les zones de mémoire:
group_upper =(char *)malloc(1024);
upper_buffer=(char *)malloc(1024);
// On commence par se faire une version majuscule du groupe à rechercher:
strcpy(group_upper,group);
Load_INI_clear_string(group_upper, 0);
stop_seek=0;
do
{
// On lit une ligne dans le fichier:
if (fgets(buffer,1024,old_file)==0)
{
free(upper_buffer);
free(group_upper);
return ERROR_INI_CORRUPTED;
}
// On s'en fait une version en majuscule:
strcpy(upper_buffer,buffer);
Load_INI_clear_string(upper_buffer, 0);
// On compare la chaîne avec le groupe recherché:
stop_seek=Load_INI_seek_pattern(upper_buffer,group_upper);
if (fprintf(new_file,"%s",buffer)<0)
{
free(upper_buffer);
free(group_upper);
return ERROR_SAVING_INI;
}
}
while (stop_seek==0);
free(upper_buffer);
free(group_upper);
return 0;
}
int Save_INI_char_in_value_alphabet(char c)
{
if (
( // Digit
(c>='0') &&
(c<='9')
) ||
( // Uppercase letter
(c>='A') &&
(c<='Z')
) ||
( // Lowerchase letter
(c>='a') &&
(c<='z')
) ||
(c == '$') || // Hexa prefix
(c == '-') || // Minus sign
(c== '.') // Dot (in filenames)
)
return 1;
else
return 0;
}
void Save_INI_set_value(char * dest,char * source,int nb_values_to_set,int * values,int litteral)
{
int dest_index;
int source_index;
int value_index;
// On commence par recopier tout jusqu'au symbole '=':
for (source_index=0;source[source_index]!='=';source_index++)
dest[source_index]=source[source_index];
// Puis on recopie le symbole '=':
dest[source_index]=source[source_index];
source_index++;
// Puis on recopie tous les espaces qui suivent:
for (;source[source_index]==' ';source_index++)
dest[source_index]=source[source_index];
// Pour l'instant, la source et la destination en sont au même point:
dest_index=source_index;
// Puis pour chaque valeur à recopier:
for (value_index=0;value_index<nb_values_to_set;value_index++)
{
// Dans la destination, on écrit la valeur:
if (litteral)
{
// La valeur doit être écrite sous la forme Yes/No
if (values[value_index])
{
// La valeur <=> Yes
memcpy(dest+dest_index,"yes",3);
dest_index+=3;
}
else
{
// La valeur <=> No
memcpy(dest+dest_index,"no",2);
dest_index+=2;
}
}
else
{
// La valeur doit être écrite sous forme numérique
if (source[source_index]=='$')
{
// On va écrire la valeur sous forme hexadécimale:
// On commence par inscrire le symbole '$':
dest[dest_index]='$';
// Puis on y concatène la valeur:
sprintf(dest+dest_index+1,"%x",values[value_index]);
dest_index+=strlen(dest+dest_index);
}
else
{
// On va écrire la valeur sous forme décimale:
sprintf(dest+dest_index,"%d",values[value_index]);
dest_index+=strlen(dest+dest_index);
}
}
// Dans la source, on saute la valeur:
for (;Save_INI_char_in_value_alphabet(source[source_index]) && (source[source_index]!='\0');source_index++);
if (value_index!=(nb_values_to_set-1))
{
// Il reste d'autres valeurs à écrire
// On recopie tous les caractères de la source jusqu'au suivant qui
// désigne une valeur:
for (;(!Save_INI_char_in_value_alphabet(source[source_index])) && (source[source_index]!='\0');source_index++,dest_index++)
dest[dest_index]=source[source_index];
}
else
{
// C'est la dernière valeur à initialiser
// On recopie toute la fin de la ligne:
for (;source[source_index]!='\0';source_index++,dest_index++)
dest[dest_index]=source[source_index];
// Et on n'oublie pas d'y mettre l''\0':
dest[dest_index]='\0';
}
}
}
void Save_INI_set_string(char * dest,char * source,char * value)
{
int dest_index;
int source_index;
// On commence par recopier tout jusqu'au symbole '=':
for (source_index=0;source[source_index]!='=';source_index++)
dest[source_index]=source[source_index];
// Puis on recopie le symbole '=':
dest[source_index]=source[source_index];
source_index++;
// Puis on recopie tous les espaces qui suivent:
for (;source[source_index]==' ';source_index++)
dest[source_index]=source[source_index];
// Pour l'instant, la source et la destination en sont au même point:
dest_index=source_index;
// Dans la destination, on écrit la valeur:
strcpy(dest+dest_index,value);
dest_index+=strlen(value);
// Dans la source, on saute la valeur:
for (;Save_INI_char_in_value_alphabet(source[source_index]) && (source[source_index]!='\0');source_index++);
// On recopie toute la fin de la ligne:
for (;source[source_index]!='\0';source_index++,dest_index++)
dest[dest_index]=source[source_index];
// Et on n'oublie pas d'y mettre l''\0':
dest[dest_index]='\0';
}
int Save_INI_set_strings(FILE * old_file,FILE * new_file,char * buffer,char * option_name,char * value)
{
int stop_seek;
char * option_upper;
char * upper_buffer;
char * result_buffer;
//int buffer_index;
// On alloue les zones de mémoire:
option_upper=(char *)malloc(1024);
upper_buffer=(char *)malloc(1024);
result_buffer=(char *)malloc(1024);
// On convertit un eventuel argument NULL en chaine vide.
if (value == NULL)
value="";
// On commence par se faire une version majuscule de l'option à rechercher:
strcpy(option_upper,option_name);
Load_INI_clear_string(option_upper, 0);
stop_seek=0;
do
{
// On lit une ligne dans le fichier:
if (fgets(buffer,1024,old_file)==0)
{
free(result_buffer);
free(upper_buffer);
free(option_upper);
return ERROR_INI_CORRUPTED;
}
// On s'en fait une version en majuscule:
strcpy(upper_buffer,buffer);
Load_INI_clear_string(upper_buffer, 0);
// On compare la chaîne avec l'option recherchée:
stop_seek=Load_INI_seek_pattern(upper_buffer,option_upper);
if (stop_seek)
{
// On l'a trouvée:
Save_INI_set_string(result_buffer,buffer,value);
if (fprintf(new_file,"%s",result_buffer)<0)
{
free(result_buffer);
free(upper_buffer);
free(option_upper);
return ERROR_SAVING_INI;
}
}
else
{
// On l'a pas trouvée:
if (fprintf(new_file,"%s",buffer)<0)
{
free(result_buffer);
free(upper_buffer);
free(option_upper);
return ERROR_SAVING_INI;
}
}
}
while (stop_seek==0);
free(result_buffer);
free(upper_buffer);
free(option_upper);
return 0;
}
int Save_INI_set_values(FILE * old_file,FILE * new_file,char * buffer,char * option_name,int nb_values_to_set,int * values,int litteral)
{
int stop_seek;
char * option_upper;
char * upper_buffer;
char * result_buffer;
//int buffer_index;
// On alloue les zones de mémoire:
option_upper=(char *)malloc(1024);
upper_buffer=(char *)malloc(1024);
result_buffer=(char *)malloc(1024);
// On commence par se faire une version majuscule de l'option à rechercher:
strcpy(option_upper,option_name);
Load_INI_clear_string(option_upper, 0);
stop_seek=0;
do
{
// On lit une ligne dans le fichier:
if (fgets(buffer,1024,old_file)==0)
{
free(result_buffer);
free(upper_buffer);
free(option_upper);
DEBUG("END OF FILE",0);
return ERROR_INI_CORRUPTED;
}
// On s'en fait une version en majuscule:
strcpy(upper_buffer,buffer);
Load_INI_clear_string(upper_buffer, 0);
// On compare la chaîne avec l'option recherchée:
stop_seek=Load_INI_seek_pattern(upper_buffer,option_upper);
if (stop_seek)
{
// On l'a trouvée:
Save_INI_set_value(result_buffer,buffer,nb_values_to_set,values,litteral);
if (fprintf(new_file,"%s",result_buffer)<0)
{
free(result_buffer);
free(upper_buffer);
free(option_upper);
return ERROR_SAVING_INI;
}
}
else
{
// On l'a pas trouvée:
if (fprintf(new_file,"%s",buffer)<0)
{
free(result_buffer);
free(upper_buffer);
free(option_upper);
return ERROR_SAVING_INI;
}
}
}
while (stop_seek==0);
free(result_buffer);
free(upper_buffer);
free(option_upper);
return 0;
}
void Save_INI_flush(FILE * old_file,FILE * new_file,char * buffer)
{
while (fgets(buffer,1024,old_file)!=0)
fprintf(new_file,"%s",buffer);
}
int Save_INI(T_Config * conf)
{
FILE * old_file;
FILE * new_file;
char * buffer;
int values[3];
char filename[MAX_PATH_CHARACTERS];
char temp_filename[MAX_PATH_CHARACTERS];
int return_code;
char ref_ini_file[MAX_PATH_CHARACTERS];
int ini_file_exists;
int index;
// On alloue les zones de mémoire:
buffer=(char *)malloc(1024);
// On calcule les noms des fichiers qu'on manipule:
strcpy(filename,Config_directory);
strcat(filename,INI_FILENAME);
// On vérifie si le fichier INI existe
if ((ini_file_exists = File_exists(filename)))
{
strcpy(temp_filename,Config_directory);
strcat(temp_filename,INISAVE_FILENAME);
// Delete gfx2.$$$
remove(temp_filename);
// Rename current config file as gfx2.$$$
if (rename(filename,temp_filename)!=0)
{
goto Erreur_ERREUR_SAUVEGARDE_INI;
}
}
// On récupère un fichier INI "propre" à partir de gfx2def.ini
strcpy(ref_ini_file,Data_directory);
strcat(ref_ini_file,INIDEF_FILENAME);
old_file=fopen(ref_ini_file,"rb");
if (old_file==0)
{
fclose(old_file);
free(buffer);
return ERROR_INI_MISSING;
}
new_file=fopen(filename,"wb");
if (new_file==0)
{
free(buffer);
return ERROR_SAVING_INI;
}
if ((return_code=Save_INI_reach_group(old_file,new_file,buffer,"[MOUSE]")))
goto Erreur_Retour;
values[0]=conf->Mouse_sensitivity_index_x;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"X_sensitivity",1,values,0)))
goto Erreur_Retour;
values[0]=conf->Mouse_sensitivity_index_y;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Y_sensitivity",1,values,0)))
goto Erreur_Retour;
values[0]=0;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"X_correction_factor",1,values,0)))
goto Erreur_Retour;
values[0]=0;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Y_correction_factor",1,values,0)))
goto Erreur_Retour;
values[0]=(conf->Cursor)+1;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Cursor_aspect",1,values,0)))
goto Erreur_Retour;
if ((return_code=Save_INI_reach_group(old_file,new_file,buffer,"[MENU]")))
goto Erreur_Retour;
values[0]=conf->Fav_menu_colors[2].R>>2;
values[1]=conf->Fav_menu_colors[2].G>>2;
values[2]=conf->Fav_menu_colors[2].B>>2;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Light_color",3,values,0)))
goto Erreur_Retour;
values[0]=conf->Fav_menu_colors[1].R>>2;
values[1]=conf->Fav_menu_colors[1].G>>2;
values[2]=conf->Fav_menu_colors[1].B>>2;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Dark_color",3,values,0)))
goto Erreur_Retour;
values[0]=conf->Ratio;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Menu_ratio",1,values,0)))
goto Erreur_Retour;
if ((return_code=Save_INI_reach_group(old_file,new_file,buffer,"[FILE_SELECTOR]")))
goto Erreur_Retour;
values[0]=conf->Show_hidden_files?1:0;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Show_hidden_files",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Show_hidden_directories?1:0;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Show_hidden_directories",1,values,1)))
goto Erreur_Retour;
/* values[0]=conf->Show_system_directories?1:0;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Show_system_directories",1,values,1)))
goto Erreur_Retour;
*/
values[0]=conf->Timer_delay;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Preview_delay",1,values,0)))
goto Erreur_Retour;
values[0]=conf->Maximize_preview;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Maximize_preview",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Find_file_fast;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Find_file_fast",1,values,0)))
goto Erreur_Retour;
if ((return_code=Save_INI_reach_group(old_file,new_file,buffer,"[LOADING]")))
goto Erreur_Retour;
values[0]=conf->Auto_set_res;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Auto_set_resolution",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Set_resolution_according_to;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Set_resolution_according_to",1,values,0)))
goto Erreur_Retour;
values[0]=conf->Clear_palette;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Clear_palette",1,values,1)))
goto Erreur_Retour;
if ((return_code=Save_INI_reach_group(old_file,new_file,buffer,"[MISCELLANEOUS]")))
goto Erreur_Retour;
values[0]=conf->Display_image_limits;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Draw_limits",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Adjust_brush_pick;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Adjust_brush_pick",1,values,1)))
goto Erreur_Retour;
values[0]=2-conf->Coords_rel;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Coordinates",1,values,0)))
goto Erreur_Retour;
values[0]=conf->Backup;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Backup",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Max_undo_pages;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Undo_pages",1,values,0)))
goto Erreur_Retour;
values[0]=conf->Delay_left_click_on_slider;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Gauges_scrolling_speed_Left",1,values,0)))
goto Erreur_Retour;
values[0]=conf->Delay_right_click_on_slider;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Gauges_scrolling_speed_Right",1,values,0)))
goto Erreur_Retour;
values[0]=conf->Auto_save;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Auto_save",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Nb_max_vertices_per_polygon;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Vertices_per_polygon",1,values,0)))
goto Erreur_Retour;
values[0]=conf->Fast_zoom;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Fast_zoom",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Separate_colors;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Separate_colors",1,values,1)))
goto Erreur_Retour;
values[0]=conf->FX_Feedback;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"FX_feedback",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Safety_colors;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Safety_colors",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Opening_message;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Opening_message",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Clear_with_stencil;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Clear_with_stencil",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Auto_discontinuous;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Auto_discontinuous",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Screen_size_in_GIF;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Save_screen_size_in_GIF",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Auto_nb_used;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Auto_nb_colors_used",1,values,1)))
goto Erreur_Retour;
if ((return_code=Save_INI_set_strings (old_file,new_file,buffer,"Default_video_mode",Mode_label(conf->Default_resolution))))
goto Erreur_Retour;
values[0]=Video_mode[0].Width;
values[1]=Video_mode[0].Height;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Default_window_size",2,values,0)))
goto Erreur_Retour;
values[0]=(conf->Mouse_merge_movement);
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Merge_movement",1,values,0)))
goto Erreur_Retour;
values[0]=(conf->Palette_cells_X);
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Palette_cells_X",1,values,0)))
goto Erreur_Retour;
values[0]=(conf->Palette_cells_Y);
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Palette_cells_Y",1,values,0)))
goto Erreur_Retour;
for (index=0;index<NB_BOOKMARKS;index++)
{
if ((return_code=Save_INI_set_strings (old_file,new_file,buffer,"Bookmark_label",conf->Bookmark_label[index])))
goto Erreur_Retour;
if ((return_code=Save_INI_set_strings (old_file,new_file,buffer,"Bookmark_directory",conf->Bookmark_directory[index])))
goto Erreur_Retour;
}
values[0]=(conf->Palette_vertical);
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Palette_vertical",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Window_pos_x;
values[1]=conf->Window_pos_y;
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Window_position",2,values,0)))
goto Erreur_Retour;
values[0]=(conf->Double_click_speed);
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Double_click_speed",1,values,0)))
goto Erreur_Retour;
values[0]=(conf->Double_key_speed);
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Double_key_speed",1,values,0)))
goto Erreur_Retour;
if ((return_code=Save_INI_set_strings (old_file,new_file,buffer,"Skin_file",conf->Skin_file)))
goto Erreur_Retour;
if ((return_code=Save_INI_set_strings (old_file,new_file,buffer,"Font_file",conf->Font_file)))
goto Erreur_Retour;
values[0]=(conf->Grid_XOR_color);
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Grid_XOR_color",1,values,0)))
goto Erreur_Retour;
values[0]=(Pixel_ratio);
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Pixel_ratio",1,values,0))) {
DEBUG("saving pixel ratio",return_code);
goto Erreur_Retour;
}
values[0]=0;
for (index=0; index<MENUBAR_COUNT;index++)
{
values[0] |= Menu_bars[index].Visible ? (1<<index) : 0;
}
// Fill out the remaining bits. When new toolbars get implemented, they will
// be visible by default.
for (; index<8;index++)
values[0] |= (1<<index);
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Menubars_visible",1,values,0)))
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;
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;
switch(conf->Swap_buttons)
{
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;
if ((return_code=Save_INI_set_strings (old_file,new_file,buffer,"Scripts_directory",conf->Scripts_directory)))
goto Erreur_Retour;
values[0]=(conf->Allow_multi_shortcuts);
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Allow_multi_shortcuts",1,values,1)))
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
if (ini_file_exists)
remove(temp_filename);
free(buffer);
return 0;
// Gestion des erreurs:
Erreur_Retour:
fclose(new_file);
fclose(old_file);
free(buffer);
return return_code;
Erreur_ERREUR_SAUVEGARDE_INI:
free(buffer);
return ERROR_SAVING_INI;
}

View File

@@ -0,0 +1,27 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 saveini.h
/// Saving settings in gfx2.ini
//////////////////////////////////////////////////////////////////////////////
int Save_INI(T_Config * conf);

View File

@@ -0,0 +1,373 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#include <string.h>
#include <stdlib.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 "sdlscreen.h"
#include "errors.h"
#include "misc.h"
// Update method that does a large number of small rectangles, aiming
// for a minimum number of total pixels updated.
#define UPDATE_METHOD_MULTI_RECTANGLE 1
// Intermediate update method, does only one update with the smallest
// rectangle that includes all modified pixels.
#define UPDATE_METHOD_CUMULATED 2
// Total screen update, for platforms that impose a Vsync on each SDL update.
#define UPDATE_METHOD_FULL_PAGE 3
// UPDATE_METHOD can be set from makefile, otherwise it's selected here
// depending on the platform :
#ifndef UPDATE_METHOD
#if defined(__macosx__)
#define UPDATE_METHOD UPDATE_METHOD_FULL_PAGE
#elif defined(__MINT__)
#define UPDATE_METHOD UPDATE_METHOD_CUMULATED
#elif defined(ANDROID)
#define UPDATE_METHOD UPDATE_METHOD_FULL_PAGE
#else
#define UPDATE_METHOD UPDATE_METHOD_CUMULATED
#endif
#endif
volatile int Allow_colorcycling=1;
/// Sets the new screen/window dimensions.
void Set_mode_SDL(int *width, int *height, int fullscreen)
{
static SDL_Cursor* cur = NULL;
static byte cursorData = 0;
#ifdef ANDROID
Screen_SDL_Hardware=SDL_SetVideoMode(*width,*height,16,(fullscreen?SDL_FULLSCREEN:0));
Screen_SDL=SDL_CreateRGBSurface(SDL_SWSURFACE, *width, *height, 8, 0, 0, 0, 0);
if(Screen_SDL_Hardware != NULL)
#else
Screen_SDL=SDL_SetVideoMode(*width,*height,8,(fullscreen?SDL_FULLSCREEN:0)|SDL_RESIZABLE);
if(Screen_SDL != NULL)
#endif
{
// Check the mode we got, in case it was different from the one we requested.
if (Screen_SDL->w != *width || Screen_SDL->h != *height)
{
DEBUG("Error: Got a different video mode than the requested one!",0);
*width = Screen_SDL->w;
*height = Screen_SDL->h;
}
Screen_pixels=Screen_SDL->pixels;
}
else
{
DEBUG("Error: Unable to change video mode!",0);
}
// 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)
short Min_X=0;
short Min_Y=0;
short Max_X=10000;
short Max_Y=10000;
short Status_line_dirty_begin=0;
short Status_line_dirty_end=0;
#endif
#if (UPDATE_METHOD == UPDATE_METHOD_FULL_PAGE)
int update_is_required=0;
#endif
void Flush_update(void)
{
#if (UPDATE_METHOD == UPDATE_METHOD_FULL_PAGE)
// Do a full screen update
if (update_is_required)
{
#ifdef ANDROID
SDL_BlitSurface(Screen_SDL, NULL, Screen_SDL_Hardware, NULL);
SDL_UpdateRect(Screen_SDL_Hardware, 0, 0, 0, 0);
#else
SDL_UpdateRect(Screen_SDL, 0, 0, 0, 0);
#endif
update_is_required=0;
}
#endif
#if (UPDATE_METHOD == UPDATE_METHOD_CUMULATED)
if (Min_X>=Max_X || Min_Y>=Max_Y)
{
; // Nothing to do
}
else
{
if (Min_X<0)
Min_X=0;
if (Min_Y<0)
Min_Y=0;
SDL_UpdateRect(Screen_SDL, Min_X*Pixel_width, Min_Y*Pixel_height, Min(Screen_width-Min_X, Max_X-Min_X)*Pixel_width, Min(Screen_height-Min_Y, Max_Y-Min_Y)*Pixel_height);
Min_X=Min_Y=10000;
Max_X=Max_Y=0;
}
if (Status_line_dirty_end)
{
SDL_UpdateRect(Screen_SDL, (18+(Status_line_dirty_begin*8))*Menu_factor_X*Pixel_width,Menu_status_Y*Pixel_height,(Status_line_dirty_end-Status_line_dirty_begin)*8*Menu_factor_X*Pixel_width,8*Menu_factor_Y*Pixel_height);
}
Status_line_dirty_begin=25;
Status_line_dirty_end=0;
#endif
}
void Update_rect(short x, short y, unsigned short width, unsigned short height)
{
#if (UPDATE_METHOD == UPDATE_METHOD_MULTI_RECTANGLE)
SDL_UpdateRect(Screen_SDL, x*Pixel_width, y*Pixel_height, width*Pixel_width, height*Pixel_height);
#endif
#if (UPDATE_METHOD == UPDATE_METHOD_CUMULATED)
if (width==0 || height==0)
{
Min_X=Min_Y=0;
Max_X=Max_Y=10000;
}
else
{
if (x < Min_X)
Min_X = x;
if (y < Min_Y)
Min_Y = y;
if (x+width>Max_X)
Max_X=x+width;
if (y+height>Max_Y)
Max_Y=y+height;
}
#endif
#if (UPDATE_METHOD == UPDATE_METHOD_FULL_PAGE)
update_is_required=1;
#endif
}
void Update_status_line(short char_pos, short width)
{
#if (UPDATE_METHOD == UPDATE_METHOD_MULTI_RECTANGLE)
SDL_UpdateRect(Screen_SDL, (18+char_pos*8)*Menu_factor_X*Pixel_width,Menu_status_Y*Pixel_height,width*8*Menu_factor_X*Pixel_width,8*Menu_factor_Y*Pixel_height);
#endif
#if (UPDATE_METHOD == UPDATE_METHOD_CUMULATED)
// Merge the ranges
if (Status_line_dirty_end < char_pos+width)
Status_line_dirty_end=char_pos+width;
if (Status_line_dirty_begin > char_pos)
Status_line_dirty_begin=char_pos;
#endif
#if (UPDATE_METHOD == UPDATE_METHOD_FULL_PAGE)
(void)char_pos; // unused parameter
(void)width; // unused parameter
update_is_required=1;
#endif
}
///
/// Converts a SDL_Surface (indexed colors or RGB) into an array of bytes
/// (indexed colors).
/// If dest is NULL, it's allocated by malloc(). Otherwise, be sure to
/// pass a buffer of the right dimensions.
byte * Surface_to_bytefield(SDL_Surface *source, byte * dest)
{
byte *src;
byte *dest_ptr;
int y;
int remainder;
// Support seulement des images 256 couleurs
if (source->format->BytesPerPixel != 1)
return NULL;
if (source->w & 3)
remainder=4-(source->w&3);
else
remainder=0;
if (dest==NULL)
dest=(byte *)malloc(source->w*source->h);
dest_ptr=dest;
src=(byte *)(source->pixels);
for(y=0; y < source->h; y++)
{
memcpy(dest_ptr, src,source->w);
dest_ptr += source->w;
src += source->w + remainder;
}
return dest;
}
/// Gets the RGB 24-bit color currently associated with a palette index.
SDL_Color Color_to_SDL_color(byte index)
{
SDL_Color color;
color.r = Main_palette[index].R;
color.g = Main_palette[index].G;
color.b = Main_palette[index].B;
color.unused = 255;
return color;
}
/// Reads a pixel in a 8-bit SDL surface.
byte Get_SDL_pixel_8(SDL_Surface *bmp, int x, int y)
{
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.
dword Get_SDL_pixel_hicolor(SDL_Surface *bmp, int x, int y)
{
byte * ptr;
switch(bmp->format->BytesPerPixel)
{
case 4:
default:
return *((dword *)((byte *)bmp->pixels+(y*bmp->pitch+x*4)));
case 3:
// 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:
return *((word *)((byte *)bmp->pixels+(y*bmp->pitch+x*2)));
}
}
/// Convert a SDL Palette to a grafx2 palette
void Get_SDL_Palette(const SDL_Palette * sdl_palette, T_Palette palette)
{
int i;
for (i=0; i<256; i++)
{
palette[i].R=sdl_palette->colors[i].r;
palette[i].G=sdl_palette->colors[i].g;
palette[i].B=sdl_palette->colors[i].b;
}
}
void Clear_border(byte color)
{
int width;
int height;
// This function can be called before the graphics mode is set.
// Nothing to do then.
if (!Screen_SDL)
return;
width = Screen_SDL->w - Screen_width*Pixel_width;
height = Screen_SDL->h - Screen_height*Pixel_height;
if (width)
{
SDL_Rect r;
r.x=Screen_SDL->w - width;
r.y=0;
r.h=Screen_SDL->h;
r.w=width;
SDL_FillRect(Screen_SDL,&r,color);
#ifdef ANDROID
SDL_BlitSurface(Screen_SDL, NULL, Screen_SDL_Hardware, NULL);
SDL_UpdateRect(Screen_SDL_Hardware, r.x, r.y, r.w, r.h);
#else
SDL_UpdateRect(Screen_SDL, r.x, r.y, r.w, r.h);
#endif
}
if (height)
{
SDL_Rect r;
r.x=0;
r.y=Screen_SDL->h - height;
r.h=height;
r.w=Screen_SDL->w - height;
SDL_FillRect(Screen_SDL,&r,color);
#ifdef ANDROID
SDL_BlitSurface(Screen_SDL, NULL, Screen_SDL_Hardware, NULL);
SDL_UpdateRect(Screen_SDL_Hardware, r.x, r.y, r.w, r.h);
#else
SDL_UpdateRect(Screen_SDL, r.x, r.y, r.w, r.h);
#endif
}
}
/// 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

@@ -0,0 +1,77 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 sdlscreen.h
/// Screen update (refresh) system, and some SDL-specific graphic functions.
//////////////////////////////////////////////////////////////////////////////
#ifndef SDLSCREEN_H_INCLUDED
#define SDLSCREEN_H_INCLUDED
#include <SDL.h>
#include "struct.h"
///
/// This is the number of bytes in a video line for the current mode.
/// On many platforms it will be the video mode's width (in pixels), rounded up
/// to be a multiple of 4.
#define VIDEO_LINE_WIDTH (Screen_SDL->pitch)
void Set_mode_SDL(int *,int *,int);
SDL_Rect ** List_SDL_video_modes;
byte* Screen_pixels;
void Update_rect(short x, short y, unsigned short width, unsigned short height);
void Flush_update(void);
void Update_status_line(short char_pos, short width);
///
/// Converts a SDL_Surface (indexed colors or RGB) into an array of bytes
/// (indexed colors).
/// If dest is NULL, it's allocated by malloc(). Otherwise, be sure to
/// pass a buffer of the right dimensions.
byte * Surface_to_bytefield(SDL_Surface *source, byte * dest);
/// Gets the RGB 24-bit color currently associated with a palette index.
SDL_Color Color_to_SDL_color(byte);
/// Reads a pixel in a 8-bit SDL surface.
byte Get_SDL_pixel_8(SDL_Surface *bmp, int x, int y);
/// Reads a pixel in a multi-byte SDL surface.
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
void Get_SDL_Palette(const SDL_Palette * sdl_palette, T_Palette palette);
///
/// Clears the parts of screen that are outside of the editing area.
/// There is such area only if the screen mode is not a multiple of the pixel
/// size, eg: 3x3 pixels in 1024x768 leaves 1 column on the right, 0 rows on bottom.
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

View File

@@ -0,0 +1,240 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Peter Gordon
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#if defined(__WIN32__)
#include <windows.h>
#include <io.h> // Mingw's _mkdir()
#elif defined(__macosx__)
#import <corefoundation/corefoundation.h>
#import <sys/param.h>
#elif defined(__FreeBSD__)
#import <sys/param.h>
#elif defined(__MINT__)
#include <mint/osbind.h>
#include <mint/sysbind.h>
#elif defined(__linux__)
#include <limits.h>
#include <unistd.h>
#endif
#include "struct.h"
#include "io.h"
#include "setup.h"
#if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__)
// This is a random default value ...
#define PATH_MAX 32768
#endif
int Create_ConfigDirectory(char * config_dir)
{
#ifdef __WIN32__
// Mingw's mkdir has a weird name and only one argument
return _mkdir(config_dir);
#else
return mkdir(config_dir,S_IRUSR|S_IWUSR|S_IXUSR);
#endif
}
#if defined(__macosx__) || defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__) && !defined(__VBCC__)
#define ARG_UNUSED __attribute__((unused))
#else
#define ARG_UNUSED
#endif
// Determine which directory contains the executable.
// IN: Main's argv[0], some platforms need it, some don't.
// OUT: Write into program_dir. Trailing / or \ is kept.
// Note : in fact this is only used to check for the datafiles and fonts in
// this same directory.
void Set_program_directory(ARG_UNUSED const char * argv0,char * program_dir)
{
#undef ARG_UNUSED
// MacOSX
#if defined(__macosx__)
CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
CFURLGetFileSystemRepresentation(url,true,(UInt8*)program_dir,MAXPATHLEN);
CFRelease(url);
// Append trailing slash
strcat(program_dir ,"/");
// AmigaOS and alike: hard-coded volume name.
#elif defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
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
#elif defined(ANDROID)
strcpy(program_dir, "./");
#elif defined(__linux__)
if (argv0[0]!='/')
{
char path[PATH_MAX];
readlink("/proc/self/exe", path, sizeof(path));
Extract_path(program_dir, path);
return;
}
Extract_path(program_dir, argv0);
// Others: The part of argv[0] before the executable name.
// Keep the last \ or /.
// On Windows, Mingw32 already provides the full path in all cases.
#else
Extract_path(program_dir, argv0);
#endif
}
// Determine which directory contains the read-only data.
// IN: The directory containing the executable
// OUT: Write into data_dir. Trailing / or \ is kept.
void Set_data_directory(const char * program_dir, char * data_dir)
{
// On all platforms, data is relative to the executable's directory
strcpy(data_dir,program_dir);
// On MacOSX, it is stored in a special folder:
#if defined(__macosx__)
strcat(data_dir,"Contents/Resources/");
// On GP2X, executable is not in bin/
#elif defined (__GP2X__) || defined (__gp2x__) || defined (__WIZ__) || defined (__CAANOO__) || defined(ANDROID)
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
#elif defined (__AROS__)
strcat(data_dir,"/share/grafx2/");
#else
strcat(data_dir,"../share/grafx2/");
#endif
}
// Determine which directory should store the user's configuration.
//
// For most Unix and Windows platforms:
// If a config file already exists in program_dir, it will return it in priority
// (Useful for development, and possibly for upgrading from DOS version)
// If the standard directory doesn't exist yet, this function will attempt
// to create it ($(HOME)/.grafx2, or %APPDATA%\GrafX2)
// If it cannot be created, this function will return the executable's
// own directory.
// IN: The directory containing the executable
// OUT: Write into config_dir. Trailing / or \ is kept.
void Set_config_directory(const char * program_dir, char * config_dir)
{
// AmigaOS4
#if defined(__amigaos4__) || defined(__AROS__)
strcpy(config_dir,"PROGDIR:");
// 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 an internal flash chip. So, keep these settings locals.
strcpy(config_dir,program_dir);
#elif defined(__MINT__)
strcpy(config_dir,program_dir);
#else
char filename[MAX_PATH_CHARACTERS];
// In priority: check root directory
strcpy(config_dir, program_dir);
// On all the remaining targets except OSX, the executable is in ./bin
#if !defined(__macosx__)
strcat(config_dir, "../");
#endif
strcpy(filename, config_dir);
strcat(filename, CONFIG_FILENAME);
if (!File_exists(filename))
{
char *config_parent_dir;
#if defined(__WIN32__)
// "%APPDATA%\GrafX2"
const char* Config_SubDir = "GrafX2";
config_parent_dir = getenv("APPDATA");
#elif defined(__BEOS__) || defined(__HAIKU__)
// "~/.grafx2", the BeOS way
const char* Config_SubDir = ".grafx2";
config_parent_dir = getenv("$HOME");
#elif defined(__macosx__)
// "~/Library/Preferences/com.googlecode.grafx2"
const char* Config_SubDir = "Library/Preferences/com.googlecode.grafx2";
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
// "~/.grafx2"
const char* Config_SubDir = ".grafx2";
config_parent_dir = getenv("HOME");
#endif
if (config_parent_dir && config_parent_dir[0]!='\0')
{
int size = strlen(config_parent_dir);
strcpy(config_dir, config_parent_dir);
if (config_parent_dir[size-1] != '\\' && config_parent_dir[size-1] != '/')
{
strcat(config_dir,PATH_SEPARATOR);
}
strcat(config_dir,Config_SubDir);
if (Directory_exists(config_dir))
{
// Répertoire trouvé, ok
strcat(config_dir,PATH_SEPARATOR);
}
else
{
// Tentative de création
if (!Create_ConfigDirectory(config_dir))
{
// Réussi
strcat(config_dir,PATH_SEPARATOR);
}
else
{
// Echec: on se rabat sur le repertoire de l'executable.
strcpy(config_dir,program_dir);
#if defined(__macosx__)
strcat(config_dir, "../");
#endif
}
}
}
}
#endif
}

View File

@@ -0,0 +1,157 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Peter Gordon
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 setup.h
/// Functions that determine where grafx2 is running, finds its data, and
/// reads and writes configuration files.
//////////////////////////////////////////////////////////////////////////////
///
/// Determine which directory contains the executable.
/// - IN: Main's argv[0], some platforms need it, some don't.
/// - OUT: Write into program_dir. Trailing / or \ is kept.
/// Note : in fact this is only used to check for the datafiles and fonts in this same directory.
void Set_program_directory(const char * argv0,char * program_dir);
///
/// Determine which directory contains the read-only data.
/// IN: The directory containing the executable
/// OUT: Write into data_dir. Trailing / or \ is kept.
void Set_data_directory(const char * program_dir, char * data_dir);
///
/// Determine which directory should store the user's configuration.
/// For most Unix and Windows platforms:
/// If a config file already exists in program_dir, it will return it in priority
/// (Useful for development, and possibly for upgrading from DOS version)
/// If the standard directory doesn't exist yet, this function will attempt
/// to create it ($(HOME)/.grafx2, or %APPDATA%\\GrafX2)
/// If it cannot be created, this function will return the executable's
/// own directory.
/// IN: The directory containing the executable
/// OUT: Write into config_dir. Trailing / or \ is kept.
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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 shade.h
/// Screens for Shade and Quick-shade settings.
//////////////////////////////////////////////////////////////////////////////
#ifndef SHADE_H_INCLUDED
#define SHADE_H_INCLUDED
void Button_Quick_shade_menu(void);
int Shade_settings_menu(void);
#endif // SHADE_H_INCLUDED

View File

@@ -0,0 +1,468 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#include <stdlib.h>
#include <string.h>
#include "const.h"
#include "struct.h"
#include "global.h"
#include "graph.h"
#include "engine.h"
#include "windows.h"
#include "special.h"
#include "pages.h"
#include "misc.h"
#include "buttons.h"
//---------------------- Modifier le pinceau spécial -------------------------
int Circle_squared_diameter(int diameter)
{
int result = diameter*diameter;
// Trick to make some circles rounder, even though
// mathematically incorrect.
if (diameter==3 || diameter==9)
return result-2;
if (diameter==11)
return result-6;
if (diameter==14)
return result-4;
return result;
}
void Set_paintbrush_size(int width, int height)
{
int x_pos,y_pos;
int x,y;
int radius2;
if (width<1) width=1;
if (height<1) height=1;
if (width>MAX_PAINTBRUSH_SIZE) width=MAX_PAINTBRUSH_SIZE;
if (height>MAX_PAINTBRUSH_SIZE) height=MAX_PAINTBRUSH_SIZE;
Paintbrush_width=width;
Paintbrush_height=height;
Paintbrush_offset_X=Paintbrush_width>>1;
Paintbrush_offset_Y=Paintbrush_height>>1;
switch (Paintbrush_shape)
{
case PAINTBRUSH_SHAPE_ROUND :
radius2=Circle_squared_diameter(Paintbrush_width);
for (y_pos=0, y=1-Paintbrush_height; y_pos<Paintbrush_height; y_pos++,y+=2)
for (x_pos=0, x=1-Paintbrush_width; x_pos<Paintbrush_width; x_pos++,x+=2)
{
Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=( ((x*x)+(y*y)) <= radius2 );
}
break;
case PAINTBRUSH_SHAPE_SQUARE :
for (x_pos=0,y_pos=0; x_pos<Paintbrush_height; x_pos++,y_pos+=MAX_PAINTBRUSH_SIZE)
memset(Paintbrush_sprite+y_pos,1,Paintbrush_width);
break;
case PAINTBRUSH_SHAPE_SIEVE_ROUND :
{
int reminder=0;
if (Paintbrush_width==1)
reminder = 1;
radius2=Circle_squared_diameter(Paintbrush_width);
for (y_pos=0, y=1-Paintbrush_height; y_pos<Paintbrush_height; y_pos++,y+=2)
for (x_pos=0, x=1-Paintbrush_width; x_pos<Paintbrush_width; x_pos++,x+=2)
{
Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=( ((x_pos+y_pos+reminder)&1) && (((x*x)+(y*y)) < radius2));
}
break;
}
case PAINTBRUSH_SHAPE_SIEVE_SQUARE:
for (y_pos=0; y_pos<Paintbrush_height; y_pos++)
for (x_pos=0; x_pos<Paintbrush_width; x_pos++)
Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=!((x_pos+y_pos)&1);
break;
case PAINTBRUSH_SHAPE_PLUS:
x=Paintbrush_width>>1;
for (y_pos=0; y_pos<Paintbrush_height; y_pos++)
for (x_pos=0; x_pos<Paintbrush_width; x_pos++)
Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=((x_pos==x) || (y_pos==x));
break;
case PAINTBRUSH_SHAPE_SLASH:
x=Paintbrush_width>>1;
for (y_pos=0; y_pos<Paintbrush_height; y_pos++)
for (x_pos=0; x_pos<Paintbrush_width; x_pos++)
Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=(x_pos==(Paintbrush_width-(y_pos+1)));
break;
case PAINTBRUSH_SHAPE_ANTISLASH:
x=Paintbrush_width>>1;
for (y_pos=0; y_pos<Paintbrush_height; y_pos++)
for (x_pos=0; x_pos<Paintbrush_width; x_pos++)
Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=(x_pos==y_pos);
break;
case PAINTBRUSH_SHAPE_HORIZONTAL_BAR:
memset(Paintbrush_sprite,1,Paintbrush_width);
break;
case PAINTBRUSH_SHAPE_VERTICAL_BAR:
for (y_pos=0; y_pos<Paintbrush_height; y_pos++)
Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)]=1;
break;
case PAINTBRUSH_SHAPE_CROSS:
x=Paintbrush_width>>1;
for (y_pos=0; y_pos<Paintbrush_height; y_pos++)
for (x_pos=0; x_pos<Paintbrush_width; x_pos++)
Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=( (x_pos==y_pos) || (x_pos==(Paintbrush_height-(y_pos+1))) );
break;
case PAINTBRUSH_SHAPE_DIAMOND:
x=Paintbrush_width>>1;
for (y_pos=0; y_pos<Paintbrush_height; y_pos++)
for (x_pos=0; x_pos<Paintbrush_width; x_pos++)
{
if (x_pos<=x)
y=x-x_pos;
else
y=x_pos-x;
if (y_pos<=x)
y+=x-y_pos;
else
y+=y_pos-x;
Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=(y<=x);
}
break;
case PAINTBRUSH_SHAPE_RANDOM:
// Init with blank
for (y_pos=0; y_pos<Paintbrush_height; y_pos++)
memset(Paintbrush_sprite+y_pos*MAX_PAINTBRUSH_SIZE,0,Paintbrush_width);
radius2=Circle_squared_diameter(Paintbrush_width);
for (y_pos=0, y=1-Paintbrush_height; y_pos<Paintbrush_height; y_pos++,y+=2)
for (x_pos=0, x=1-Paintbrush_width; x_pos<Paintbrush_width; x_pos++,x+=2)
{
if ((x*x)+(y*y) < radius2 && !(rand()&7))
{
Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=1;
// This prevents having a pixels that touch each other.
if (x_pos>0)
Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos-1]=0;
if (y_pos>0)
Paintbrush_sprite[((y_pos-1)*MAX_PAINTBRUSH_SIZE)+x_pos]=0;
}
}
}
}
void Smaller_paintbrush(void)
{
if ( (Paintbrush_shape<PAINTBRUSH_SHAPE_MISC)
&& ( (Paintbrush_width>1)
|| (Paintbrush_height>1) ) )
{
Hide_cursor();
switch (Paintbrush_shape)
{
case PAINTBRUSH_SHAPE_CROSS:
case PAINTBRUSH_SHAPE_PLUS:
case PAINTBRUSH_SHAPE_DIAMOND:
if (Paintbrush_width&1)
Set_paintbrush_size(Paintbrush_width-2,Paintbrush_height-2);
else
Set_paintbrush_size(Paintbrush_width-1,Paintbrush_height-1);
break;
case PAINTBRUSH_SHAPE_SQUARE:
case PAINTBRUSH_SHAPE_SLASH:
case PAINTBRUSH_SHAPE_ANTISLASH:
case PAINTBRUSH_SHAPE_SIEVE_SQUARE:
case PAINTBRUSH_SHAPE_ROUND:
case PAINTBRUSH_SHAPE_SIEVE_ROUND:
case PAINTBRUSH_SHAPE_RANDOM:
Set_paintbrush_size(Paintbrush_width-1,Paintbrush_height-1);
break;
case PAINTBRUSH_SHAPE_HORIZONTAL_BAR:
Set_paintbrush_size(Paintbrush_width-1,1);
break;
case PAINTBRUSH_SHAPE_VERTICAL_BAR:
Set_paintbrush_size(1,Paintbrush_height-1);
}
Display_paintbrush_in_menu();
Display_cursor();
}
}
void Bigger_paintbrush(void)
{
if ( (Paintbrush_shape<PAINTBRUSH_SHAPE_MISC)
&& ( (Paintbrush_width<MAX_PAINTBRUSH_SIZE)
|| (Paintbrush_height<MAX_PAINTBRUSH_SIZE) ) )
{
Hide_cursor();
switch (Paintbrush_shape)
{
case PAINTBRUSH_SHAPE_CROSS:
case PAINTBRUSH_SHAPE_PLUS:
case PAINTBRUSH_SHAPE_DIAMOND:
if (Paintbrush_width&1)
Set_paintbrush_size(Paintbrush_width+2,Paintbrush_height+2);
else
Set_paintbrush_size(Paintbrush_width+1,Paintbrush_height+1);
break;
case PAINTBRUSH_SHAPE_SQUARE:
case PAINTBRUSH_SHAPE_SLASH:
case PAINTBRUSH_SHAPE_ANTISLASH:
case PAINTBRUSH_SHAPE_SIEVE_SQUARE:
case PAINTBRUSH_SHAPE_ROUND:
case PAINTBRUSH_SHAPE_SIEVE_ROUND:
case PAINTBRUSH_SHAPE_RANDOM:
Set_paintbrush_size(Paintbrush_width+1,Paintbrush_height+1);
break;
case PAINTBRUSH_SHAPE_HORIZONTAL_BAR:
Set_paintbrush_size(Paintbrush_width+1,1);
break;
case PAINTBRUSH_SHAPE_VERTICAL_BAR:
Set_paintbrush_size(1,Paintbrush_height+1);
}
Display_paintbrush_in_menu();
Display_cursor();
}
}
//--------------------- Increase the ForeColor -----------------------
void Special_next_forecolor(void)
{
Hide_cursor();
Set_fore_color(Fore_color+1);
Display_cursor();
}
//--------------------- Decrease the ForeColor -----------------------
void Special_previous_forecolor(void)
{
Hide_cursor();
Set_fore_color(Fore_color-1);
Display_cursor();
}
//--------------------- Increase the BackColor -----------------------
void Special_next_backcolor(void)
{
Hide_cursor();
Set_back_color(Back_color+1);
Display_cursor();
}
//--------------------- Decrease the BackColor -----------------------
void Special_previous_backcolor(void)
{
Hide_cursor();
Set_back_color(Back_color-1);
Display_cursor();
}
/// Picks the next foreground color, according to current shade table
void Special_next_user_forecolor(void)
{
Hide_cursor();
Set_fore_color(Shade_table_left[Fore_color]);
Display_cursor();
}
/// Picks the previous foreground color, according to current shade table
void Special_previous_user_forecolor(void)
{
Hide_cursor();
Set_fore_color(Shade_table_right[Fore_color]);
Display_cursor();
}
/// Picks the next background color, according to current shade table
void Special_next_user_backcolor(void)
{
Hide_cursor();
Set_back_color(Shade_table_left[Back_color]);
Display_cursor();
}
/// Picks the previous background color, according to current shade table
void Special_previous_user_backcolor(void)
{
Hide_cursor();
Set_back_color(Shade_table_right[Back_color]);
Display_cursor();
}
// ------------------- Scroller l'écran (pas en mode loupe) ------------------
void Scroll_screen(short delta_x,short delta_y)
{
short temp_x_offset;
short temp_y_offset;
temp_x_offset=Main_offset_X+delta_x;
temp_y_offset=Main_offset_Y+delta_y;
if (temp_x_offset+Screen_width>Main_image_width)
temp_x_offset=Main_image_width-Screen_width;
if (temp_y_offset+Menu_Y>Main_image_height)
temp_y_offset=Main_image_height-Menu_Y;
if (temp_x_offset<0)
temp_x_offset=0;
if (temp_y_offset<0)
temp_y_offset=0;
if ( (Main_offset_X!=temp_x_offset) ||
(Main_offset_Y!=temp_y_offset) )
{
Hide_cursor();
Main_offset_X=temp_x_offset;
Main_offset_Y=temp_y_offset;
Compute_limits();
Compute_paintbrush_coordinates();
Display_all_screen(); // <=> Display_screen + Display_image_limits
Display_cursor();
}
}
// ---------------------- Scroller la fenêtre de la loupe --------------------
void Scroll_magnifier(short delta_x,short delta_y)
{
short temp_x_offset;
short temp_y_offset;
temp_x_offset=Main_magnifier_offset_X+delta_x;
temp_y_offset=Main_magnifier_offset_Y+delta_y;
Clip_magnifier_offsets(&temp_x_offset, &temp_y_offset);
if ( (Main_magnifier_offset_X!=temp_x_offset) ||
(Main_magnifier_offset_Y!=temp_y_offset) )
{
Hide_cursor();
Main_magnifier_offset_X=temp_x_offset;
Main_magnifier_offset_Y=temp_y_offset;
Position_screen_according_to_zoom();
Compute_limits();
Compute_paintbrush_coordinates();
Display_all_screen();
Display_cursor();
}
}
// -------------- Changer le Zoom (grâce aux touches [+] et [-]) -------------
void Zoom(short delta)
{
short index;
for (index=0; ZOOM_FACTOR[index]!=Main_magnifier_factor; index++);
index+=delta;
if ( (index>=0) && (index<NB_ZOOM_FACTORS) )
{
Hide_cursor();
Change_magnifier_factor(index,1);
if (Main_magnifier_mode)
Display_all_screen();
Display_cursor();
}
}
/**
Set zoom value. Negative value means no zoom.
*/
void Zoom_set(int index)
{
Hide_cursor();
if (index<0)
{
/* Zoom 1:1 */
if (Main_magnifier_mode)
Unselect_button(BUTTON_MAGNIFIER);
}
else
{
Change_magnifier_factor(index,1);
if (!Main_magnifier_mode)
Select_button(BUTTON_MAGNIFIER,1);
Display_all_screen();
}
Display_cursor();
}
void Transparency_set(byte amount)
{
const int doubleclick_delay = Config.Double_key_speed;
static long time_click = 0;
long time_previous;
if (!Colorize_mode)
{
// Activate mode
switch(Colorize_current_mode)
{
case 0 :
Effect_function=Effect_interpolated_colorize;
break;
case 1 :
Effect_function=Effect_additive_colorize;
break;
case 2 :
Effect_function=Effect_substractive_colorize;
break;
case 3 :
Effect_function=Effect_alpha_colorize;
}
Shade_mode=0;
Quick_shade_mode=0;
Smooth_mode=0;
Tiling_mode=0;
Colorize_mode=1;
}
time_previous = time_click;
time_click = SDL_GetTicks();
// Check if it's a quick re-press
if (time_click - time_previous < doubleclick_delay)
{
// Use the typed amount as units, keep the tens.
Colorize_opacity = ((Colorize_opacity%100) /10 *10) + amount;
if (Colorize_opacity == 0)
Colorize_opacity = 100;
}
else
{
// Use 10% units: "1"=10%, ... "0"=100%
if (amount == 0)
Colorize_opacity = 100;
else
Colorize_opacity = amount*10;
}
Compute_colorize_table();
}

View File

@@ -0,0 +1,58 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#include "struct.h"
//////////////////////////////////////////////////////////////////////////////
///@file special.h
/// Editor functions that can be hooked to a keyboard shortcut, but don't have
/// a menu button associated to them.
//////////////////////////////////////////////////////////////////////////////
void Set_paintbrush_size(int width, int height);
void Smaller_paintbrush(void);
void Bigger_paintbrush(void);
void Special_next_forecolor(void);
void Special_previous_forecolor(void);
void Special_next_backcolor(void);
void Special_previous_backcolor(void);
void Special_next_user_forecolor(void);
void Special_previous_user_forecolor(void);
void Special_next_user_backcolor(void);
void Special_previous_user_backcolor(void);
void Scroll_screen(short delta_x,short delta_y);
void Scroll_magnifier(short delta_x,short delta_y);
void Zoom(short delta);
void Zoom_set(int index);
void Display_stored_brush_in_window(word x,word y,int number);
void Store_brush(int index);
byte Restore_brush(int index);
/*!
Command that sets the transparency level.
*/
void Transparency_set(byte amount);

View File

@@ -0,0 +1,539 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 struct.h
/// Structures that can be used in the whole program.
//////////////////////////////////////////////////////////////////////////////
#ifndef _STRUCT_H_
#define _STRUCT_H_
#if defined(__BEOS__) || defined(__TRU64__)
#include <inttypes.h>
#else
#include <stdint.h>
#endif
#include "const.h"
// POSIX calls it strcasecmp, Windows uses stricmp... no ANSI standard.
#ifdef WIN32
#define strcasecmp stricmp
#endif
// Definition of the base data types
/// 8bit unsigned integer
#define byte uint8_t
/// 16bit unsigned integer
#define word uint16_t
/// 32bit unsigned integer
#define dword uint32_t
/// 64bit unsigned integer
#define qword uint64_t
// Named function prototypes
// GrafX2 use a lot of function pointer to do the drawing depending in the "fake hardware zoom" and the magnifier status.
typedef void (* Func_action) (void); ///< An action. Used when you click a menu button or trigger a keyboard shortcut.
typedef void (* Func_pixel) (word,word,byte); ///< Set pixel at position (x,y) to color c. Used in load screen to write the data to brush, picture, or preview area.
typedef byte (* Func_read) (word,word); ///< Read a pixel at position (x,y) on something. Used for example in save to tell if the data is a brush or a picture
typedef void (* Func_clear) (byte);
typedef void (* Func_display) (word,word,word);
typedef byte (* Func_effect) (word,word,byte); ///< Called by all drawing tools to draw with a special effect (smooth, transparency, shade, ...)
typedef void (* Func_block) (word,word,word,word,byte);
typedef void (* Func_line_XOR) (word,word,word); ///< Draw an XOR line on the picture view of the screen. Use a different function when in magnify mode.
typedef void (* Func_display_brush_color) (word,word,word,word,word,word,byte,word);
typedef void (* Func_display_brush_mono) (word,word,word,word,word,word,byte,byte,word);
typedef void (* Func_gradient) (long,short,short);
typedef void (* Func_remap) (word,word,word,word,byte *);
typedef void (* Func_procsline) (word,word,word,byte *);
typedef void (* Func_display_zoom) (word,word,word,byte *);
typedef void (* Func_display_brush_color_zoom) (word,word,word,word,word,word,byte,word,byte *);
typedef void (* Func_display_brush_mono_zoom) (word,word,word,word,word,word,byte,byte,word,byte *);
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
/// 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)
typedef struct
{
byte R; ///< Red
byte G; ///< Green
byte B; ///< Blue
} T_Components, T_Palette[256] ; ///< A complete 256-entry RGB palette (768 bytes).
#pragma pack()
#endif
/// A normal rectangular button in windows and menus.
typedef struct T_Normal_button
{
short Number; ///< Unique identifier for all controls
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 Width; ///< Width before scaling
word Height; ///< Height before scaling
byte Clickable; ///< Boolean, unused.
byte Repeatable; ///< Boolean, true if the button activates repeatedly until you release the mouse button. Used for "+" buttons, for example.
word Shortcut; ///< Keyboard shortcut that will emulate a click on this button.
struct T_Normal_button * Next;///< Pointer to the next normal button of current window.
} T_Normal_button;
/// A window control that shows a complete 256-color palette
typedef struct T_Palette_button
{
short Number; ///< Unique identifier for all controls
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.
struct T_Palette_button * Next;///< Pointer to the next palette of current window.
} T_Palette_button;
/// A window control that represents a scrollbar, with a slider, and two arrow buttons.
typedef struct T_Scroller_button
{
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_Y; ///< Coordinate for left of button, relative to the window, before scaling.
word Length; ///< Length before scaling.
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 Position; ///< Current position of the slider: which item it's pointing.
word Cursor_length; ///< Dimension of the slider, in pixels before scaling.
struct T_Scroller_button * Next;///< Pointer to the next scroller of current window.
} T_Scroller_button;
/// Special invisible button
/// A window control that only has a rectangular "active" area which catches mouse clicks,
// but no visible shape. It's used for custom controls where the drawing is done on
// a case by case basis.
typedef struct T_Special_button
{
short Number; ///< Unique identifier for all controls
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 Width; ///< Width before scaling
word Height; ///< Height before scaling
struct T_Special_button * Next;///< Pointer to the next special button of current window.
} T_Special_button;
/// Data for a dropdown item, ie. one proposed choice.
typedef struct T_Dropdown_choice
{
short Number; ///< Value that identifies the choice (for this dropdown only)
const char * Label; ///< String to display in the dropdown panel
struct T_Dropdown_choice * Next;///< Pointer to the next choice for this dropdown.
} T_Dropdown_choice;
/// A window control that behaves like a dropdown button.
typedef struct T_Dropdown_button
{
short Number; ///< Unique identifier for all controls
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 Width; ///< Width before scaling
word Height; ///< Height before scaling
byte Display_choice; ///< Boolean, true if the engine should print the selected item's label in the dropdown area when the user chooses it.
byte Display_centered; ///< Boolean, true to center the labels (otherwise, align left)
byte Display_arrow; ///< Boolean, true to display a "down" arrow box in top right
byte Bottom_up; ///< Boolean, true to make the dropdown panel go above its button instead of below it
byte Active_button; ///< Determines which mouse button(s) cause the dropdown panel to open: LEFT_SIDE || RIGHT_SIDE || (LEFT_SIDE|RIGHT_SIDE)
word Dropdown_width; ///< Width of the dropdown panel when it's open. Use 0 for "same as the dropdown button"
T_Dropdown_choice * First_item; ///< Linked list with the choices available for this dropdown.
struct T_Dropdown_button * Next;///< Pointer to the next dropdown button of current window.
} T_Dropdown_button;
/// Data for one item (file, directory) in a fileselector.
typedef struct T_Fileselector_item
{
char Full_name[256]; ///< Filesystem value.
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 * 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;
/// Data for a fileselector
typedef struct T_Fileselector
{
/// Number of elements in the current fileselector's ::Filelist
short Nb_elements;
/// Number of files in the current fileselector's ::Filelist
short Nb_files;
/// Number of directories in the current fileselector's ::Filelist
short Nb_directories;
/// Head of the linked list for the fileselector.
T_Fileselector_item * First;
/// Index for direct access to element number N
T_Fileselector_item ** Index;
} T_Fileselector;
/// "List" button as used in the font selection, skin selection, and brush factory screens. It's like a limited filelist.
/// The screenmode selection and load/save screen were written before this existed so they use their own code. It would be nice if they were updated to use this one.
typedef struct T_List_button
{
short Number; ///< Unique identifier for all controls
short List_start; ///< Index of the font to appear as first line
short Cursor_position; ///< Index of the selected line (0=top)
T_Special_button * Entry_button; ///< Pointer to the associated selection control.
T_Scroller_button * Scroller; ///< Pointer to the associated scroller
Func_draw_list_item Draw_list_item; ///< Function to call for each item to draw its line
byte Color_index; ///< Background color: From 0->MC_Black to 3->MC_White
struct T_List_button * Next; ///< Pointer to the next list button of current window.
} 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.
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 * Text; ///< Displayed string.
int Line_parameter; ///< Generic parameter depending on line type. For 'K' lines: a shortcut identifier. For others: unused.
} T_Help_table;
/// Data for one section of the "Help" screens, ie a page.
typedef struct
{
const T_Help_table* Help_table; ///< Pointer to the array of ::T_Help_table that contains the lines
word Length; ///< Size of the array of lines
} T_Help_section;
/// Data for one setting of gradients. Warning, this one is saved/loaded as binary.
typedef struct
{
byte Start; ///< First color
byte End; ///< Last color
dword Inverse; ///< Boolean, true if the gradient goes in descending order
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)
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.
typedef struct
{
word List[512]; ///< List of entries, each one is either a color (0-255) or -1 for empty.
byte Step; ///< Step to increment/decrement on left-clicks.
byte Mode; ///< Shade mode: Normal, Loop, or No-saturation see ::SHADE_MODES
} T_Shade;
/// Data for one fullscreen video mode in configuration file. Warning, this one is saved/loaded as binary.
typedef struct
{
byte State; ///< How good is the mode supported. 0:Good (white) 1:OK (light) 2:So-so (dark) 4:User-disabled (black); +128 => System doesn't support it at all.
word Width; ///< Videomode width in pixels.
word Height;///< Videomode height in pixels.
} T_Config_video_mode;
/// Header for gfx2.cfg
typedef struct
{
char Signature[3]; ///< Signature for the file format. "CFG".
byte Version1; ///< Major version number (ex: 2)
byte Version2; ///< Minor version number (ex: 0)
byte Beta1; ///< Major beta version number (ex: 96)
byte Beta2; ///< Major beta version number (ex: 5)
} T_Config_header;
/// Header for a config chunk in for gfx2.cfg
typedef struct
{
byte Number; ///< Section identfier. Possible values are in enum ::CHUNKS_CFG
word Size; ///< Size of the configuration block that follows, in bytes.
} T_Config_chunk;
/// Configuration for one keyboard shortcut in gfx2.cfg
typedef struct
{
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 Key2; ///< Alternate keyboard shortcut: SDLK_something, or -1 for none
} T_Config_shortcut_info;
/// This structure holds all the settings saved and loaded as gfx2.ini.
typedef struct
{
char *Font_file; ///< Name of the font used in the menus. Matches file skins/font_*.png (Case-sensitive on some filesystems)
char *Skin_file; ///< String, name of the file where all the graphic data is stored
int Show_hidden_files; ///< Boolean, true to show hidden files in fileselectors.
int Show_hidden_directories; ///< Boolean, true to show hidden directories in fileselectors.
// int Show_system_directories; ///< (removed when converted from DOS)
byte Display_image_limits; ///< Boolean, true to display a dotted line at the borders of the image if it's smaller than screen.
byte Cursor; ///< Mouse cursor aspect: 1 Solid, 2 Transparent, 3 Thin
byte Maximize_preview; ///< Boolean, true to make previews in fileselector fit the whole rectangle.
byte Auto_set_res; ///< Boolean, true to make grafx2 switch to a new resolution whenever you load an image.
byte Coords_rel; ///< Boolean, true to display coordinates as relative (instead of absolute)
byte Backup; ///< Boolean, true to backup the original file whenever you save an image.
byte Adjust_brush_pick; ///< Boolean, true to omit the right and bottom edges when grabbing a brush in Grid mode.
byte Auto_save; ///< Boolean, true to save configuration when exiting program.
byte Max_undo_pages; ///< Number of steps to memorize for Undo/Redo.
byte Mouse_sensitivity_index_x; ///< Mouse sensitivity in X axis
byte Mouse_sensitivity_index_y; ///< Mouse sensitivity in Y axis
byte Mouse_merge_movement; ///< Number of SDL mouse events that are merged into a single change of mouse coordinates.
byte Delay_left_click_on_slider; ///< Delay (in 1/100s) between two activations of a repeatable button when you hold left-click.
byte Delay_right_click_on_slider; ///< Delay (in 1/100s) between two activations of a repeatable button when you hold left-click.
long Timer_delay; ///< Delay (in 1/55s) before showing a preview in a fileselector.
T_Components Fav_menu_colors[4]; ///< Favorite colors to use for the menu.
int Nb_max_vertices_per_polygon; ///< Limit for the number of vertices in polygon tools.
byte Clear_palette; ///< Boolean, true to reset the palette (to black) before loading an image.
byte Set_resolution_according_to; ///< When Auto_set_res is on, this determines if the mode should be chosen according to the "original screen" information in the file (1) or the picture dimensons (2)
int8_t Ratio; ///< Determines the scaling of menu and windows: 0 no scaling, 1 scaling, 2 slight scaling, negative= opposite of max scaling
byte Fast_zoom; ///< Boolean, true if the magnifier shortcut should automatically view the mouse area.
byte Find_file_fast; ///< In fileselectors, this determines which entries should be sought when typing letters: 0 all, 1 files only, 2 directories only.
byte Separate_colors; ///< Boolean, true if the menu palette should separate color cells with a black outline.
word Palette_cells_X; ///< Number of colors to show in a row of the menu palette.
word Palette_cells_Y; ///< Number of colors to show in a column of the menu palette.
byte Palette_vertical; ///< Boolean, true if the menu palette should go top to bottom instead of left to right
byte FX_Feedback; ///< Boolean, true if drawing effects should read the image being modified (instead of the image before clicking)
byte Safety_colors; ///< Boolean, true to make the palette automatically re-create menu colors if needed after a "Zap" or color reduction.
byte Opening_message; ///< Boolean, true to display the splash screen on strtup.
byte Clear_with_stencil; ///< Boolean, true to take the stencil into effect (if active) when using the Clear function.
byte Auto_discontinuous; ///< Boolean, true to automatically switch to the discontinuous freehand draw after grabbing a brush.
byte Screen_size_in_GIF; ///< Boolean, true to store current resolution in GIF files.
byte Auto_nb_used; ///< Boolean, true to count colors in Palette screen.
byte Default_resolution; ///< Default video mode to use on startup. Index in ::Video_mode.
char *Bookmark_directory[NB_BOOKMARKS];///< Bookmarked directories in fileselectors: This is the full directory name.
char Bookmark_label[NB_BOOKMARKS][8+1];///< Bookmarked directories in fileselectors: This is the displayed name.
int Window_pos_x; ///< Last window x position (9999 if unsupportd/irrelevant for the platform)
int Window_pos_y; ///< Last window y position (9999 if unsupportd/irrelevant for the platform)
word Double_click_speed; ///< Maximum delay for double-click, 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 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.
char Scripts_directory[MAX_PATH_CHARACTERS];///< Full pathname of directory for Lua scripts
byte Allow_multi_shortcuts; ///< Boolean, true if the same key combination can trigger multiple shortcuts.
} T_Config;
// Structures utilisées pour les descriptions de pages et de liste de pages.
// Lorsqu'on gérera les animations, il faudra aussi des listes de listes de
// pages.
// Ces structures sont manipulées à travers des fonctions de gestion du
// backup dans "graph.c".
/// This is the data for one step of Undo/Redo, for one image.
/// This structure is resized dynamically to hold pointers to all of the layers in the picture.
/// The pointed layers are just byte* holding the raw pixel data. But at Image[0]-1 you will find a short that is used as a reference counter for each layer.
/// This way we can use the same pixel data in many undo pages when the user edit only one of the layers (which is what they usually do).
typedef struct T_Page
{
int Width; ///< Image width in pixels.
int Height; ///< Image height in pixels.
T_Palette Palette; ///< Image palette.
char Comment[COMMENT_SIZE+1]; ///< Comment to store in the image file.
char File_directory[MAX_PATH_CHARACTERS];///< Directory that contains the file.
char Filename[MAX_PATH_CHARACTERS]; ///< Filename without directory.
byte File_format; ///< File format, in enum ::FILE_FORMATS
struct T_Page *Next; ///< Pointer to the next 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 Transparent_color; ///< Index of transparent color. 0 to 255.
byte Nb_layers; ///< Number of layers
#if __GNUC__ < 3
byte * Image[0];
#else
byte * Image[]; ///< Pixel data for the (first layer of) image.
#endif
// Define as Image[0] if you have an old gcc which is not C99.
// No field after Image[] ! Dynamic layer allocation for Image[1], [2] etc.
} T_Page;
/// Collection of undo/redo steps.
typedef struct
{
int List_size; ///< Number of ::T_Page in the vector "Pages".
T_Page * Pages; ///< Head of a linked list of pages, each one being a undo/redo step.
} T_List_of_pages;
/// A single image bitmap
/// This struct is used to store a flattened view of the current picture.
typedef struct
{
int Width; ///< Image width in pixels.
int Height; ///< Image height in pixels.
byte * Image; ///< Pixel data for the image.
} T_Bitmap;
/// A single memorized brush from the Brush Container
typedef struct
{
byte Paintbrush_shape; ///< Kind of brush
byte Thumbnail[BRUSH_CONTAINER_PREVIEW_WIDTH][BRUSH_CONTAINER_PREVIEW_HEIGHT];
// Data for color brush
word Width;
word Height;
byte * Brush; /// < Color brush (if any)
T_Palette Palette;
byte Colormap[256];
byte Transp_color;
} T_Brush_template;
/// GUI skin data
typedef struct
{
// Mouse
/// X coordinate of the mouse cursor's "hot spot". It is < ::CURSOR_SPRITE_WIDTH
word Cursor_offset_X[NB_CURSOR_SPRITES];
/// Y coordinate of the mouse cursor's "hot spot". It is < ::CURSOR_SPRITE_HEIGHT
word Cursor_offset_Y[NB_CURSOR_SPRITES];
/// Graphic resources for the mouse cursor.
byte Cursor_sprite[NB_CURSOR_SPRITES][CURSOR_SPRITE_HEIGHT][CURSOR_SPRITE_WIDTH];
// Sieve patterns
/// Preset sieve patterns, stored as binary (one word per line)
word Sieve_pattern[12][16];
// Menu and other graphics
/// Bitmap data for the menu, a single rectangle.
byte Menu_block[3][35][MENU_WIDTH];
byte Layerbar_block[3][10][144];
byte Statusbar_block[3][9][20];
/// Bitmap data for the icons that are displayed over the menu.
byte Menu_sprite[2][NB_MENU_SPRITES][MENU_SPRITE_HEIGHT][MENU_SPRITE_WIDTH];
/// Bitmap data for the different "effects" icons.
byte Effect_sprite[NB_EFFECTS_SPRITES][EFFECT_SPRITE_HEIGHT][EFFECT_SPRITE_WIDTH];
/// Bitmap data for the different Layer icons.
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.
byte Logo_grafx2[231*56];
/// Bitmap data for the 6x8 font used in help screens.
byte Help_font_norm [256][6][8];
/// Bitmap data for the 6x8 font used in help screens ("bold" verstion).
byte Bold_font [256][6][8];
// 12
// 34
/// Bitmap data for the title font used in help screens. Top-left quarter.
byte Help_font_t1 [64][6][8];
/// Bitmap data for the title font used in help screens. Top-right quarter.
byte Help_font_t2 [64][6][8];
/// Bitmap data for the title font used in help screens. Bottom-left quarter.
byte Help_font_t3 [64][6][8];
/// Bitmap data for the title font used in help screens. Bottom-right quarter.
byte Help_font_t4 [64][6][8];
/// Bitmap data for the small 8x8 icons.
byte Icon_sprite[NB_ICON_SPRITES][ICON_SPRITE_HEIGHT][ICON_SPRITE_WIDTH];
/// A default 256-color palette.
T_Palette Default_palette;
/// Preview for displaying in the skin dialog
byte Preview[16][173];
/// GUI color indices in skin palette: black, dark, light, white.
byte Color[4];
/// Transparent GUI color index in skin file
byte Color_trans;
} 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.
typedef struct {
word Width;
word Height;
byte Visible;
word Top; ///< Relative to the top line of the menu, hidden bars don't count.
byte* Skin[3]; ///< [0] has normal buttons, [1] has selected buttons, [2] is current.
word Skin_width;
byte Last_button_index;
} T_Menu_Bar;
typedef enum {
MENUBAR_STATUS = 0, // MUST be 0
MENUBAR_LAYERS,
MENUBAR_TOOLS,
MENUBAR_COUNT
} T_Menubars;
#endif

View File

@@ -0,0 +1,667 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2008 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
// Pour désactiver le support TrueType, définir NOTTF
// To disable TrueType support, define NOTTF
#include <string.h>
#include <stdlib.h>
#include <ctype.h> // tolower()
// TrueType
#ifndef NOTTF
#if defined(__macosx__)
#include <SDL_ttf/SDL_ttf.h>
#else
#include <SDL_ttf.h>
#endif
#if defined(__CAANOO__) || defined(__WIZ__) || defined(__GP2X__) || defined(ANDROID)
// No X11
#elif defined(__linux__)
#include <X11/Xlib.h>
#endif
#endif
#if defined(__macosx__)
#include <Carbon/Carbon.h>
#import <corefoundation/corefoundation.h>
#import <sys/param.h>
#endif
#include <SDL_image.h>
#include "SFont.h"
#include "struct.h"
#include "global.h"
#include "sdlscreen.h"
#include "io.h"
#include "errors.h"
#include "windows.h"
#include "misc.h"
#include "setup.h"
typedef struct T_Font
{
char * Name;
int Is_truetype;
int Is_bitmap;
char Label[22];
// Liste chainée simple
struct T_Font * Next;
struct T_Font * Previous;
} T_Font;
// Liste chainée des polices de texte
T_Font * font_list_start;
int Nb_fonts;
// Inspiré par Allegro
#define EXTID(a,b,c) ((((a)&255)<<16) | (((b)&255)<<8) | (((c)&255)))
#define EXTID4(a,b,c,d) ((((a)&255)<<24) | (((b)&255)<<16) | (((c)&255)<<8) | (((d)&255)))
int Compare_fonts(T_Font * font_1, T_Font * font_2)
{
if (font_1->Is_bitmap && !font_2->Is_bitmap)
return -1;
if (font_2->Is_bitmap && !font_1->Is_bitmap)
return 1;
return strcmp(font_1->Label, font_2->Label);
}
// Ajout d'une fonte à la liste.
void Add_font(const char *name)
{
char * font_name;
T_Font * font;
int size=strlen(name)+1;
int index;
// Détermination du type:
#if defined(__macosx__)
if (size < 6) return;
char strFontName[512];
CFStringRef CFSFontName;// = CFSTR(name);
CFSFontName = CFStringCreateWithBytes(NULL, (UInt8 *) name, size - 1, kCFStringEncodingASCII, false);
// Fix some funny names
CFStringGetCString(CFSFontName, strFontName, 512, kCFStringEncodingASCII);
// Now we have a printable font name, use it
name = strFontName;
#else
if (size<5 ||
name[size-5]!='.')
return;
#endif
font = (T_Font *)malloc(sizeof(T_Font));
switch (EXTID(tolower(name[size-4]), tolower(name[size-3]), tolower(name[size-2])))
{
case EXTID('t','t','f'):
case EXTID('f','o','n'):
case EXTID('o','t','f'):
case EXTID('p','f','b'):
font->Is_truetype = 1;
font->Is_bitmap = 0;
break;
case EXTID('b','m','p'):
case EXTID('g','i','f'):
case EXTID('j','p','g'):
case EXTID('l','b','m'):
case EXTID('p','c','x'):
case EXTID('p','n','g'):
case EXTID('t','g','a'):
case EXTID('t','i','f'):
case EXTID('x','c','f'):
case EXTID('x','p','m'):
case EXTID('.','x','v'):
font->Is_truetype = 0;
font->Is_bitmap = 1;
break;
default:
#if defined(__macosx__)
if(strcasecmp(&name[size-6], "dfont") == 0)
{
font->Is_truetype = 1;
font->Is_bitmap = 0;
}
else
{
free(font);
return;
}
#else
free(font);
return;
#endif
}
font->Name = (char *)malloc(size);
strcpy(font->Name, name);
// Label
strcpy(font->Label, " ");
if (font->Is_truetype)
font->Label[17]=font->Label[18]='T'; // Logo TT
font_name=Find_last_slash(font->Name);
if (font_name==NULL)
font_name=font->Name;
else
font_name++;
for (index=0; index < 17 && font_name[index]!='\0' && font_name[index]!='.'; index++)
font->Label[index]=font_name[index];
// Gestion Liste
font->Next = NULL;
font->Previous = NULL;
if (font_list_start==NULL)
{
// Premiere (liste vide)
font_list_start = font;
Nb_fonts++;
}
else
{
int compare;
compare = Compare_fonts(font, font_list_start);
if (compare<=0)
{
if (compare==0 && !strcmp(font->Name, font_list_start->Name))
{
// Doublon
free(font->Name);
free(font);
return;
}
// Avant la premiere
font->Next=font_list_start;
font_list_start=font;
Nb_fonts++;
}
else
{
T_Font *searched_font;
searched_font=font_list_start;
while (searched_font->Next && (compare=Compare_fonts(font, searched_font->Next))>0)
searched_font=searched_font->Next;
// Après searched_font
if (compare==0 && strcmp(font->Name, searched_font->Next->Name)==0)
{
// Doublon
free(font->Name);
free(font);
return;
}
font->Next=searched_font->Next;
searched_font->Next=font;
Nb_fonts++;
}
}
}
// Trouve le nom d'une fonte par son numéro
char * Font_name(int index)
{
T_Font *font = font_list_start;
if (index<0 ||index>=Nb_fonts)
return "";
while (index--)
font = font->Next;
return font->Name;
}
// Trouve le libellé d'affichage d'une fonte par son numéro
// Renvoie un pointeur sur un buffer statique de 20 caracteres.
char * Font_label(int index)
{
T_Font *font;
static char label[20];
strcpy(label, " ");
// Recherche de la fonte
font = font_list_start;
if (index<0 ||index>=Nb_fonts)
return label;
while (index--)
font = font->Next;
// Libellé
strcpy(label, font->Label);
return label;
}
// Vérifie si une fonte donnée est TrueType
int TrueType_font(int index)
{
T_Font *font = font_list_start;
if (index<0 ||index>=Nb_fonts)
return 0;
while (index--)
font = font->Next;
return font->Is_truetype;
}
// Initialisation à faire une fois au début du programme
void Init_text(void)
{
char directory_name[MAX_PATH_CHARACTERS];
#ifndef NOTTF
// Initialisation de TTF
TTF_Init();
#endif
// Initialisation des fontes
font_list_start = NULL;
Nb_fonts=0;
// Parcours du répertoire "fonts"
strcpy(directory_name, Data_directory);
strcat(directory_name, FONTS_SUBDIRECTORY);
For_each_file(directory_name, Add_font);
#if defined(__WIN32__)
// Parcours du répertoire systeme windows "fonts"
#ifndef NOTTF
{
char * WindowsPath=getenv("windir");
if (WindowsPath)
{
sprintf(directory_name, "%s\\FONTS", WindowsPath);
For_each_file(directory_name, Add_font);
}
}
#endif
#elif defined(__macosx__)
// Récupération de la liste des fonts avec fontconfig
#ifndef NOTTF
int i,number;
char home_dir[MAXPATHLEN];
char *font_path_list[3] = {
"/System/Library/Fonts",
"/Library/Fonts"
};
number = 3;
// Make sure we also search into the user's fonts directory
CFURLRef url = (CFURLRef) CFCopyHomeDirectoryURLForUser(NULL);
CFURLGetFileSystemRepresentation(url, true, (UInt8 *) home_dir, MAXPATHLEN);
strcat(home_dir, "/Library/Fonts");
font_path_list[2] = home_dir;
for(i=0;i<number;i++)
For_each_file(*(font_path_list+i),Add_font);
CFRelease(url);
#endif
#elif defined(__CAANOO__) || defined(__WIZ__) || defined(__GP2X__) || defined(ANDROID)
// No X11 : Only use fonts from Grafx2
#elif defined(__linux__)
#ifndef NOTTF
#define USE_XLIB
#ifdef USE_XLIB
{
int i,number;
Display* dpy = XOpenDisplay(NULL);
char** font_path_list = XGetFontPath(dpy,&number);
XCloseDisplay(dpy);
for(i=0;i<number;i++)
For_each_file(*(font_path_list+i),Add_font);
XFreeFontPath(font_path_list);
}
#endif
#endif
#elif defined(__amigaos4__) || defined(__amigaos__)
#ifndef NOTTF
For_each_file( "FONTS:_TrueType", Add_font );
#endif
#elif defined(__BEOS__)
#ifndef NOTTF
For_each_file("/etc/fonts/ttfonts", Add_font);
#endif
#elif defined(__HAIKU__)
#ifndef NOTTF
For_each_file("/boot/system/data/fonts/ttfonts/", Add_font);
#endif
#elif defined(__SKYOS__)
#ifndef NOTTF
For_each_file("/boot/system/fonts", Add_font);
#endif
#elif defined(__MINT__)
#ifndef NOTTF
For_each_file("C:/BTFONTS", Add_font);
#endif
#endif
}
// Informe si texte.c a été compilé avec l'option de support TrueType ou pas.
int TrueType_is_supported()
{
#ifdef NOTTF
return 0;
#else
return 1;
#endif
}
#ifndef NOTTF
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;
SDL_Surface * text_surface;
byte * new_brush;
int style;
SDL_Color fg_color;
SDL_Color bg_color;
// Chargement de la fonte
font=TTF_OpenFont(Font_name(font_number), size);
if (!font)
{
return NULL;
}
// Style
style=0;
if (italic)
style|=TTF_STYLE_ITALIC;
if (bold)
style|=TTF_STYLE_BOLD;
TTF_SetFontStyle(font, style);
// 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;
// Text rendering: creates a 8bit surface with its dedicated palette
if (antialias)
text_surface=TTF_RenderText_Shaded(font, str, fg_color, bg_color );
else
text_surface=TTF_RenderText_Solid(font, str, fg_color);
if (!text_surface)
{
TTF_CloseFont(font);
return NULL;
}
new_brush=Surface_to_bytefield(text_surface, NULL);
if (!new_brush)
{
SDL_FreeSurface(text_surface);
TTF_CloseFont(font);
return NULL;
}
// Import palette
Get_SDL_Palette(text_surface->format->palette, palette);
if (antialias)
{
int black_col;
// 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 (palette[black_col].R==0 && palette[black_col].G==0 && palette[black_col].B==0)
break;
} // If not found: c = 256 = 0 (byte)
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;
}
}
else
{
// 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)
{
new_fore=Best_color_perceptual_except(Main_palette[Back_color].R, Main_palette[Back_color].G, Main_palette[Back_color].B, Back_color);
}
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);
return new_brush;
}
#endif
byte *Render_text_SFont(const char *str, int font_number, int *width, int *height, T_Palette palette)
{
SFont_Font *font;
SDL_Surface * text_surface;
SDL_Surface *font_surface;
byte * new_brush;
SDL_Rect rectangle;
// Chargement de la fonte
font_surface=IMG_Load(Font_name(font_number));
if (!font_surface)
{
Verbose_message("Warning","Error loading font.\nThe file may be corrupt.");
return NULL;
}
// 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)
{
DEBUG("Font init failed",1);
SDL_FreeSurface(font_surface);
return NULL;
}
// Calcul des dimensions
*height=SFont_TextHeight(font, str);
*width=SFont_TextWidth(font, str);
// Allocation d'une surface SDL
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 transparent color
rectangle.x=0;
rectangle.y=0;
rectangle.w=*width;
rectangle.h=*height;
SDL_FillRect(text_surface, &rectangle, font->Transparent);
// Rendu du texte
SFont_Write(text_surface, font, 0, 0, str);
if (!text_surface)
{
DEBUG("Rendering failed",2);
SFont_FreeFont(font);
return NULL;
}
new_brush=Surface_to_bytefield(text_surface, NULL);
if (!new_brush)
{
DEBUG("Converting failed",3);
SDL_FreeSurface(text_surface);
SFont_FreeFont(font);
return NULL;
}
Get_SDL_Palette(font_surface->format->palette, palette);
// Swap current BG color with font's transparent color
if (font->Transparent != Back_color)
{
int c;
byte colmap[256];
// Swap palette entries
SWAP_BYTES(palette[font->Transparent].R, palette[Back_color].R)
SWAP_BYTES(palette[font->Transparent].G, palette[Back_color].G)
SWAP_BYTES(palette[font->Transparent].B, palette[Back_color].B)
// Define a colormap
for (c=0; c<256; c++)
colmap[c]=c;
// The swap
colmap[font->Transparent]=Back_color;
colmap[Back_color]=font->Transparent;
Remap_general_lowlevel(colmap, new_brush, new_brush, text_surface->w,text_surface->h, text_surface->w);
}
SDL_FreeSurface(text_surface);
SFont_FreeFont(font);
return new_brush;
}
#ifdef NOTTF
#define TTFONLY __attribute__((unused))
#else
#define TTFONLY
#endif
// 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,
// 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, T_Palette palette)
{
T_Font *font = font_list_start;
int index=font_number;
// Verification type de la fonte
if (font_number<0 ||font_number>=Nb_fonts)
return NULL;
while (index--)
font = font->Next;
if (font->Is_truetype)
{
#ifndef NOTTF
return Render_text_TTF(str, font_number, size, antialias, bold, italic, width, height, palette);
#else
return NULL;
#endif
}
else
{
return Render_text_SFont(str, font_number, width, height, palette);
}
}

View File

@@ -0,0 +1,57 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2008 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 text.h
/// Functions related to rendering text as a brush, using TrueType or SFont.
//////////////////////////////////////////////////////////////////////////////
/// Initialization of text settings, needs to be called once on program startup.
void Init_text(void);
/// Returns true if text.c was compiled with TrueType support.
int TrueType_is_supported(void);
/// Add a new font to the list to propose to the user.
void Add_font(const char *name);
///
/// Creates a brush, from the parameters given:
/// @param str The text to render
/// @param font_number The index of the font to use. Pass 0 for the first font you declared with ::Add_font(), 1 for the second etc.
/// @param size The size in points (unused for bitmap fonts)
/// @param antialias Boolean, true to use antialiasing in TrueType
/// @param bold Boolean, true to use bold 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 height Returns the height of the created brush, in pixels.
/// @param palette Returns the custom palette for the brush.
/// 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, T_Palette palette);
/// Finds a label to display for a font declared with ::Add_font().
char * Font_label(int index);
/// Finds the filename of a font declared with ::Add_font().
char * Font_name(int index);
/// Returns true if the font of this number is TrueType, false if it's a SFont bitmap.
int TrueType_font(int index);
///
/// Number of fonts declared with a series of ::Add_font(). This is public for
/// convenience, but functionaly it is read-only.
extern int Nb_fonts;

View File

@@ -0,0 +1,446 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2009 Yves Rizoud
Copyright 2009 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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/>
*/
#include <string.h>
#include <stdlib.h>
#include "global.h"
#include "struct.h"
#include "transform.h"
#include "engine.h"
#include "sdlscreen.h"
#include "windows.h"
#include "input.h"
#include "help.h"
#include "misc.h" // Num2str
#include "readline.h"
#include "buttons.h" // Message_out_of_memory()
#include "pages.h" // Backup_with_new_dimensions()
/// Reduces a fraction A/B to its smallest representation. ie (40,60) becomes (2/3)
void Factorize(short *a, short *b)
{
// Method: brute-force.
short factor;
factor=2;
while (factor<=*a && factor<=*b)
{
if (((*a % factor) == 0) && ((*b % factor) == 0))
{
// common factor is found
*a/=factor;
*b/=factor;
// restart
factor=2;
}
else
factor++;
}
}
/// Multiplies original_size by new_ratio/old_ratio, but keeps result in 1-9999 range.
short Compute_dimension(short original_size, short new_ratio, short old_ratio)
{
long amount;
amount = (long)original_size*new_ratio/old_ratio;
if (amount>9999)
return 9999;
else if (amount<1)
return 1;
else
return amount;
}
void Button_Transform_menu(void)
{
enum RESIZE_UNIT {
UNIT_PIXELS = 1,
UNIT_PERCENT = 2,
UNIT_RATIO = 3
};
char buffer[5];
short clicked_button;
const char * unit_label[] = {
"",
"Pixels ",
"Percent",
"Ratio "};
short last_unit_index = -1;
short old_ratio_width;
short old_ratio_height;
short new_ratio_width;
short new_ratio_height;
short new_width=Main_image_width;
short new_height=Main_image_height;
byte need_display_size = 0;
// Persistent data
static short unit_index = 1; // 1= Pixels, 2= Percent, 3=Ratio
static short ratio_is_locked = 1; // True if X and Y resize should go together
T_Dropdown_button * unit_button;
T_Special_button * input_button[4];
short *input_value[4];
// Set initial ratio
if (unit_index == UNIT_PERCENT)
new_ratio_width=old_ratio_width=new_ratio_height=old_ratio_height=100;
else
new_ratio_width=old_ratio_width=new_ratio_height=old_ratio_height=1;
Open_window(215,165,"Picture transform");
Window_display_frame( 5, 15,205,91);
Window_display_frame( 5,110, 55,49);
Window_display_frame(64,110, 85,49);
Window_set_normal_button(154,140, 54,14,"Cancel",0,1,KEY_ESC); // 1
Print_in_window( 9,114,"Mirror",MC_Dark,MC_Light);
Window_set_normal_button( 17,125, 27,14,"X\035" ,1,1,SDLK_x); // 2
Window_set_normal_button( 17,140, 27,14,"Y\022" ,1,1,SDLK_y); // 3
Print_in_window( 84,114,"Rotate",MC_Dark,MC_Light);
Window_set_normal_button( 69,125, 37,14,"-90°" ,0,1,SDLK_LAST); // 4
Window_set_normal_button(107,125, 37,14,"+90°" ,0,1,SDLK_LAST); // 5
Window_set_normal_button( 69,140, 75,14,"180°" ,0,1,SDLK_LAST); // 6
Print_in_window( 87, 19,"Resize",MC_Dark,MC_Light);
Window_set_normal_button( 80, 86, 60,14,"RESIZE",1,1,SDLK_r); // 7
Print_in_window( 51, 34,"New",MC_Dark,MC_Light);
Print_in_window( 96, 34,"Old",MC_Dark,MC_Light);
Print_in_window( 30, 44,"X:",MC_Dark,MC_Light);
Print_in_window( 30, 59,"Y:",MC_Dark,MC_Light);
Print_in_window( 80, 44,":",MC_Dark,MC_Light);
Print_in_window( 80, 59,":",MC_Dark,MC_Light);
Print_in_window( 44, 75,"Lock proportions",MC_Dark,MC_Light);
Window_set_normal_button( 28, 72, 13,13,ratio_is_locked?"X":" ",0,1,SDLK_l);// 8
unit_button = Window_set_dropdown_button(128,50,69,11,69,unit_label[unit_index],1,0,1,LEFT_SIDE|RIGHT_SIDE,0);// 9
Window_dropdown_add_item(unit_button,UNIT_PIXELS,unit_label[UNIT_PIXELS]);
Window_dropdown_add_item(unit_button,UNIT_PERCENT,unit_label[UNIT_PERCENT]);
Window_dropdown_add_item(unit_button,UNIT_RATIO,unit_label[UNIT_RATIO]);
input_button[0] = Window_set_input_button(45,43,4); // 10
input_button[1] = Window_set_input_button(89,43,4); // 11
input_button[2] = Window_set_input_button(45,58,4); // 12
input_button[3] = Window_set_input_button(89,58,4); // 13
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
// Display the coordinates with the right unit
if (last_unit_index != unit_index)
{
switch(unit_index)
{
case UNIT_PIXELS:
default:
input_value[0]=&new_width;
input_value[1]=&Main_image_width; // Don't worry, it's read-only
input_value[2]=&new_height;
input_value[3]=&Main_image_height; // Don't worry, it's read-only
break;
case UNIT_PERCENT:
case UNIT_RATIO:
input_value[0]=&new_ratio_width;
input_value[1]=&old_ratio_width;
input_value[2]=&new_ratio_height;
input_value[3]=&old_ratio_height;
break;
}
need_display_size=1;
last_unit_index=unit_index;
}
if (need_display_size)
{
short i;
Hide_cursor();
for (i=0;i<4;i++)
{
// "Old" values are not editable, unless the unit is "ratio"
byte color = ((unit_index!=UNIT_RATIO) && (i==1 || i==3)) ? MC_Dark : MC_Black;
Num2str(*(input_value[i]),buffer,4);
Print_in_window_limited(input_button[i]->Pos_X+2,input_button[i]->Pos_Y+2,buffer,input_button[i]->Width/8,color,MC_Light);
}
Display_cursor();
need_display_size=0;
}
clicked_button=Window_clicked_button();
// Contextual help
if (Is_shortcut(Key,0x100+BUTTON_HELP))
{
Key=0;
Window_help(BUTTON_ADJUST, "PICTURE TRANSFORM");
}
else if (Is_shortcut(Key,0x200+BUTTON_ADJUST))
clicked_button=1;
else switch(clicked_button)
{
case 9: // Unit
switch(Window_attribute2)
{
case UNIT_PIXELS:
// Do nothing, pixel size was already computed.
break;
case UNIT_PERCENT:
if (unit_index == UNIT_RATIO)
{
// Approximate from current ratio
new_ratio_width = Compute_dimension(new_ratio_width,100,old_ratio_width);
new_ratio_height = Compute_dimension(new_ratio_height,100,old_ratio_height);
old_ratio_width = 100;
old_ratio_height = 100;
// Update pixel dimensions, to match percentage exactly
new_width=Compute_dimension(Main_image_width, new_ratio_width, old_ratio_width);
new_height=Compute_dimension(Main_image_height, new_ratio_height, old_ratio_height);
}
else // unit_index == UNIT_PIXELS
{
// Approximate from current pixel size
new_ratio_width = new_width*100/Main_image_width;
new_ratio_height = new_height*100/Main_image_height;
old_ratio_width = 100;
old_ratio_height = 100;
}
break;
case UNIT_RATIO:
if (unit_index == UNIT_PERCENT)
{
// Compute simplest ratio from current %
Factorize(&new_ratio_width, &old_ratio_width);
Factorize(&new_ratio_height, &old_ratio_height);
}
else // unit_index == UNIT_PIXELS
{
// Compute simplest ratio from current pixel size
new_ratio_width = new_width;
new_ratio_height = new_height;
old_ratio_width = Main_image_width;
old_ratio_height = Main_image_height;
Factorize(&new_ratio_width, &old_ratio_width);
Factorize(&new_ratio_height, &old_ratio_height);
}
break;
}
unit_index = Window_attribute2;
break;
case 8: // Lock proportions
ratio_is_locked = ! ratio_is_locked;
Hide_cursor();
Print_in_window(31,75,(ratio_is_locked)?"X":" ",MC_Black,MC_Light);
Display_cursor();
break;
case 11: // input old width
case 13: // input old height
// "Old" values are not editable, unless the unit is "ratio"
if (unit_index!=UNIT_RATIO)
break;
case 10: // input new width
case 12: // input new height
Num2str(*( input_value[clicked_button-10]),buffer,4);
Hide_cursor();
if (Readline(input_button[clicked_button-10]->Pos_X+2,
input_button[clicked_button-10]->Pos_Y+2,
buffer,
4,
INPUT_TYPE_INTEGER))
{
// Accept entered value
*(input_value[clicked_button-10])=atoi(buffer);
// 0 is not acceptable size
if (*(input_value[clicked_button-10])==0)
{
*(input_value[clicked_button-10])=1;
}
// Adapt the other coordinate if X and Y are locked
if (ratio_is_locked)
{
if (clicked_button == 10 || clicked_button == 11 )
{
// Get Y value because X changed
if (unit_index == UNIT_PIXELS)
{
new_height=Compute_dimension(Main_image_height, new_width, Main_image_width);
}
else
{
// Copy the whole ratio
new_ratio_height=new_ratio_width;
old_ratio_height=old_ratio_width;
}
}
else // (clicked_button == 12 || clicked_button == 13)
{
// Get X value because Y changed
if (unit_index == UNIT_PIXELS)
{
new_width=Compute_dimension(Main_image_width, new_height, Main_image_height);
}
else
{
// Copy the whole ratio
new_ratio_width=new_ratio_height;
old_ratio_width=old_ratio_height;
}
}
}
// Re-compute ratio from size in pixels
if (unit_index == UNIT_PIXELS)
{
//new_width=(long)Main_image_width*new_ratio_width/old_ratio_width;
//new_height=(long)Main_image_height*new_ratio_height/old_ratio_height;
}
else // Re-compute size in pixels from ratio
{
new_width=Compute_dimension(Main_image_width,new_ratio_width,old_ratio_width);
new_height=Compute_dimension(Main_image_height,new_ratio_height,old_ratio_height);
}
need_display_size=1;
}
Display_cursor();
break;
}
}
while (clicked_button<=0 || clicked_button>=8);
Close_window();
// The Scroll operation uses the same button as transformation menu.
if (Current_operation != OPERATION_SCROLL)
Unselect_button(BUTTON_ADJUST);
if (clicked_button != 1) // 1 is Cancel
{
short old_width;
short old_height;
// Determine new image dimensions
switch (clicked_button)
{
case 7 : // Resize
// Keep new_width and new_height as entered.
break;
case 2 : // Flip X
case 3 : // Flip Y
case 6 : // 180° Rotation
new_width=Main_image_width;
new_height=Main_image_height;
break;
case 4 : // -90° Rotation
case 5 : // +90° Rotation
new_width=Main_image_height;
new_height=Main_image_width;
break;
}
// Memorize the current dimensions
old_width=Main_image_width;
old_height=Main_image_height;
Upload_infos_page_main(Main_backups->Pages);
// Allocate a new page
if (Backup_with_new_dimensions(new_width,new_height))
{
// The new image is allocated, the new dimensions are already updated.
Main_image_is_modified=1;
// Process the transformation:
switch(clicked_button)
{
int i;
case 2 : // Flip X
for (i=0; i<Main_backups->Pages->Nb_layers; i++)
{
memcpy(Main_backups->Pages->Image[i],Main_backups->Pages->Next->Image[i],Main_image_width*Main_image_height);
Flip_X_lowlevel(Main_backups->Pages->Image[i], Main_image_width, Main_image_height);
}
break;
case 3 : // Flip Y
for (i=0; i<Main_backups->Pages->Nb_layers; i++)
{
memcpy(Main_backups->Pages->Image[i],Main_backups->Pages->Next->Image[i],Main_image_width*Main_image_height);
Flip_Y_lowlevel(Main_backups->Pages->Image[i], Main_image_width, Main_image_height);
}
break;
case 4 : // -90° Rotation
for (i=0; i<Main_backups->Pages->Nb_layers; i++)
{
Rotate_270_deg_lowlevel(Main_backups->Pages->Next->Image[i], Main_backups->Pages->Image[i], old_width, old_height);
}
break;
case 5 : // +90° Rotation
for (i=0; i<Main_backups->Pages->Nb_layers; i++)
{
Rotate_90_deg_lowlevel(Main_backups->Pages->Next->Image[i], Main_backups->Pages->Image[i], old_width, old_height);
}
break;
case 6 : // 180° Rotation
for (i=0; i<Main_backups->Pages->Nb_layers; i++)
{
memcpy(Main_backups->Pages->Image[i],Main_backups->Pages->Next->Image[i],Main_image_width*Main_image_height);
Rotate_180_deg_lowlevel(Main_backups->Pages->Image[i], Main_image_width, Main_image_height);
}
break;
case 7 : // Resize
for (i=0; i<Main_backups->Pages->Nb_layers; i++)
{
Rescale(Main_backups->Pages->Next->Image[i], old_width, old_height, Main_backups->Pages->Image[i], Main_image_width, Main_image_height, 0, 0);
}
break;
}
/*
for (i=0; i<NB_LAYERS; i++)
{
Copy_part_of_image_to_another(
Main_backups->Pages->Next->Image[i],0,0,Min(old_width,Main_image_width),
Min(old_height,Main_image_height),old_width,
Main_backups->Pages->Image[i],0,0,Main_image_width);
}
*/
Redraw_layered_image();
Display_all_screen();
End_of_modification();
}
else
{
Display_cursor();
Message_out_of_memory();
Hide_cursor();
}
}
Display_cursor();
}

View File

@@ -0,0 +1,29 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2009 Yves Rizoud
Copyright 2009 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 transform.h
/// Screen and functions for picture transform.
//////////////////////////////////////////////////////////////////////////////
/// Opens and handles the Picture transform screen.
void Button_Transform_menu(void);

View File

@@ -0,0 +1 @@
char SVN_revision[]="1781";

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,116 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007-2008 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
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 windows.h
/// Graphical interface management functions (windows, menu, cursor)
//////////////////////////////////////////////////////////////////////////////
#ifndef __WINDOWS_H_
#define __WINDOWS_H_
#include "struct.h"
#define ToWinX(x) (((x)*Menu_factor_X)+Window_pos_X)
#define ToWinY(y) (((y)*Menu_factor_Y)+Window_pos_Y)
#define ToWinL(l) ((l)*Menu_factor_X)
#define ToWinH(h) ((h)*Menu_factor_Y)
#define Update_window_area(x,y,w,h) Update_rect(Window_pos_X+(x)*Menu_factor_X,Window_pos_Y+(y)*Menu_factor_Y,(w)*Menu_factor_X,(h)*Menu_factor_Y);
void Display_cursor(void);
void Hide_cursor(void);
void Remap_screen_after_menu_colors_change(void);
void Compute_optimal_menu_colors(T_Components * palette);
void Remap_menu_sprites();
void Position_screen_according_to_zoom(void);
void Compute_separator_data(void);
void Compute_magnifier_data(void);
void Clip_magnifier_offsets(short *x_offset, short *y_offset);
void Compute_limits(void);
void Compute_paintbrush_coordinates(void);
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_window(word x,word y,byte color);
void Set_fore_color(byte color);
void Set_back_color(byte color);
void Frame_menu_color(byte id);
void Display_menu_palette(void);
void Display_menu(void);
void Display_layerbar(void);
void Reposition_palette(void);
void Change_palette_cells(void);
int Pick_color_in_palette(void);
word Palette_cells_X(void);
word Palette_cells_Y(void);
void Print_general(short x,short y,const char * str,byte text_color,byte background_color);
void Print_in_window(short x,short y,const char * str,byte text_color,byte background_color);
void Print_in_window_limited(short x,short y,const char * str,byte size,byte text_color,byte background_color);
void Print_char_in_window(short x_pos,short y_pos,const unsigned char c,byte text_color,byte background_color);
void Print_in_menu(const char * str, short position);
void Print_coordinates(void);
void Print_filename(void);
void Print_counter(short x,short y,const char * str,byte text_color,byte background_color);
byte Confirmation_box(char * message);
void Warning_message(char * message);
void Verbose_message(const char * caption, const char * message);
int Requester_window(char* message, int initial_value);
void Display_image_limits(void);
void Display_all_screen(void);
void Window_rectangle(word x_pos,word y_pos,word width,word height,byte color);
void Window_display_frame_generic(word x_pos,word y_pos,word width,word height,
byte color_tl,byte color_br,byte color_s,byte color_tlc,byte color_brc);
void Window_display_frame_mono(word x_pos,word y_pos,word width,word height,byte color);
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(word x_pos,word y_pos,word width,word height);
void Display_sprite_in_menu(int btn_number,char sprite_number);
void Display_paintbrush_in_menu(void);
void Display_paintbrush_in_window(word x,word y,int number);
void Draw_thingumajig(word x,word y, byte color, short direction);
void Display_grad_block_in_window(word x_pos,word y_pos,word block_start,word block_end);
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_nonexcluded(byte red,byte green,byte blue);
byte Best_color_perceptual(byte r,byte g,byte b);
byte Best_color_perceptual_except(byte r,byte g,byte b, byte except);
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 Change_magnifier_factor(byte factor_index, byte point_at_mouse);
/// Width of one layer button, in pixels before scaling
extern word Layer_button_width;
/// Copy viewport settings and offsets from the Main to the Spare.
void Copy_view_to_spare(void);
#endif

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