grafx2/src/SFont.c 0000644 0000764 0001040 00000014237 11532235570 014430 0 ustar vig Administrator /* 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 .
Karl Bartel
Cecilienstr. 14
12307 Berlin
GERMANY
karlb@gmx.net
*/
#include
#include
#include
#include
#include "SFont.h"
static Uint32 GetPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y)
{
Uint8 *bits;
Uint32 Bpp;
assert(X>=0);
assert(Xw);
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_widthCharWidth[(int)*c]==0)
{
width += Font->Space;
continue;
}
width += Font->CharWidth[(int)*c];
}
return previous_widthSurface->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);
}
*/
grafx2/src/brush.c 0000644 0000764 0001040 00000167120 11525510216 014515 0 ustar vig Administrator /* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Franck Charlet
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
********************************************************************************
Brush manipulation functions
*/
#include
#include
#include // memset()
#include "global.h"
#include "graph.h"
#include "misc.h"
#include "errors.h"
#include "windows.h"
#include "sdlscreen.h"
#include "brush.h"
// Calcul de redimensionnement du pinceau pour viter les dbordements de
// l'cran et de l'image
void Compute_clipped_dimensions(short * x,short * y,short * width,short * height)
{
if ((*x)(Limit_right+1))
{
(*width)=(Limit_right-(*x))+1;
}
if ((*y)(Limit_bottom+1))
{
(*height)=(Limit_bottom-(*y))+1;
}
}
// -- Calcul de redimensionnement du pinceau pour viter les dbordements
// de l'cran zoom et de l'image --
void Compute_clipped_dimensions_zoom(short * x,short * y,short * width,short * height)
{
if ((*x)(Limit_right_zoom+1))
{
(*width)=(Limit_right_zoom-(*x))+1;
}
if ((*y)(Limit_bottom_zoom+1))
{
(*height)=(Limit_bottom_zoom-(*y))+1;
}
}
// -- Afficher le pinceau (de faon dfinitive ou non) --
void Display_paintbrush(short x,short y,byte color,byte is_preview)
// x,y: position du centre du pinceau
// color: couleur appliquer au pinceau
// is_preview: "Il ne faut l'afficher qu' l'cran"
{
short start_x; // Position X (dans l'image) partir de laquelle on
// affiche la brosse/pinceau
short start_y; // Position Y (dans l'image) partir de laquelle on
// affiche la brosse/pinceau
short width; // width dans l'cran selon laquelle on affiche la
// brosse/pinceau
short height; // height dans l'cran selon laquelle on affiche la
// brosse/pinceau
short start_x_counter; // Position X (dans la brosse/pinceau) partir
// de laquelle on affiche la brosse/pinceau
short start_y_counter; // Position Y (dans la brosse/pinceau) partir
// de laquelle on affiche la brosse/pinceau
short x_pos; // Position X (dans l'image) en cours d'affichage
short y_pos; // Position Y (dans l'image) en cours d'affichage
short counter_x; // Position X (dans la brosse/pinceau) en cours
// d'affichage
short counter_y; // Position Y (dans la brosse/pinceau) en cours
// d'affichage
short end_counter_x; // Position X ou s'arrte l'affichade de la
// brosse/pinceau
short end_counter_y; // Position Y ou s'arrte l'affichade de la
// brosse/pinceau
byte temp_color; // color de la brosse en cours d'affichage
int position;
byte * temp;
if (is_preview==0 || Mouse_K==0) // pas de curseur si on est en preview et
// en train de cliquer
switch (Paintbrush_shape)
{
case PAINTBRUSH_SHAPE_NONE : // No paintbrush. for colorpicker for example
break;
case PAINTBRUSH_SHAPE_POINT : // !!! TOUJOURS EN PREVIEW !!!
if ( (Paintbrush_X>=Limit_left)
&& (Paintbrush_X<=Limit_right)
&& (Paintbrush_Y>=Limit_top)
&& (Paintbrush_Y<=Limit_bottom) )
{
Pixel_preview(Paintbrush_X,Paintbrush_Y,color);
Update_part_of_screen(x,y,1,1);
}
break;
case PAINTBRUSH_SHAPE_COLOR_BRUSH : // Brush en couleur
start_x=x-Brush_offset_X;
start_y=y-Brush_offset_Y;
width=Brush_width;
height=Brush_height;
Compute_clipped_dimensions(&start_x,&start_y,&width,&height);
if (width<=0 || height<=0)
break;
start_x_counter=start_x-(x-Brush_offset_X);
start_y_counter=start_y-(y-Brush_offset_Y);
end_counter_x=start_x_counter+width;
end_counter_y=start_y_counter+height;
if (is_preview != 0)
{
if ( (width>0) && (height>0) )
Display_brush_color(
start_x-Main_offset_X,
start_y-Main_offset_Y,
start_x_counter,
start_y_counter,
width,
height,
Back_color,
Brush_width
);
if (Main_magnifier_mode != 0)
{
Compute_clipped_dimensions_zoom(&start_x,&start_y,&width,
&height
);
start_x_counter=start_x-(x-Brush_offset_X);
start_y_counter=start_y-(y-Brush_offset_Y);
if ( (width>0) && (height>0) )
{
// Corrections dues au Zoom:
start_x=(start_x-Main_magnifier_offset_X)*Main_magnifier_factor;
start_y=(start_y-Main_magnifier_offset_Y)*Main_magnifier_factor;
height=start_y+(height*Main_magnifier_factor);
if (height>Menu_Y)
height=Menu_Y;
Display_brush_color_zoom(Main_X_zoom+start_x,start_y,
start_x_counter,start_y_counter,
width,height,Back_color,
Brush_width,
Horizontal_line_buffer);
}
}
Update_part_of_screen(x-Brush_offset_X,y-Brush_offset_Y,Brush_width,Brush_height);
}
else
{
if ((Smear_mode != 0) && (Shade_table==Shade_table_left))
{
if (Smear_start != 0)
{
if ((width>0) && (height>0))
{
Copy_part_of_image_to_another(
Main_screen, start_x, start_y, width, height,
Main_image_width, Smear_brush,
start_x_counter, start_y_counter,
Smear_brush_width
);
Update_part_of_screen(start_x,start_y,width,height);
}
Smear_start=0;
}
else
{
for (y_pos = start_y, counter_y = start_y_counter;
counter_y < end_counter_y;
y_pos++, counter_y++
)
for (x_pos = start_x, counter_x = start_x_counter;
counter_x < end_counter_x;
x_pos++, counter_x++
)
{
temp_color = Read_pixel_from_current_screen(
x_pos,y_pos
);
position = (counter_y * Smear_brush_width)+ counter_x;
if ( (Read_pixel_from_brush(counter_x,counter_y) != Back_color)
&& (counter_y=Smear_min_Y) && (counter_x>=Smear_min_X) )
Display_pixel(x_pos,y_pos,Smear_brush[position]);
Smear_brush[position]=temp_color;
}
Update_part_of_screen(start_x,start_y,width,height);
}
Smear_min_X=start_x_counter;
Smear_min_Y=start_y_counter;
Smear_max_X=end_counter_x;
Smear_max_Y=end_counter_y;
}
else
{
if (Shade_table==Shade_table_left)
for (y_pos=start_y,counter_y=start_y_counter;counter_y0) && (height>0) )
Display_brush_mono(start_x-Main_offset_X,
start_y-Main_offset_Y,
start_x_counter,start_y_counter,
width,height,
Back_color,Fore_color,
Brush_width);
if (Main_magnifier_mode != 0)
{
Compute_clipped_dimensions_zoom(&start_x,&start_y,&width,&height);
start_x_counter=start_x-(x-Brush_offset_X);
start_y_counter=start_y-(y-Brush_offset_Y);
if ( (width>0) && (height>0) )
{
// Corrections dues au Zoom:
start_x=(start_x-Main_magnifier_offset_X)*Main_magnifier_factor;
start_y=(start_y-Main_magnifier_offset_Y)*Main_magnifier_factor;
height=start_y+(height*Main_magnifier_factor);
if (height>Menu_Y)
height=Menu_Y;
Display_brush_mono_zoom(Main_X_zoom+start_x,start_y,
start_x_counter,start_y_counter,
width,height,
Back_color,Fore_color,
Brush_width,
Horizontal_line_buffer);
}
}
Update_part_of_screen(x-Brush_offset_X,y-Brush_offset_Y,Brush_width,Brush_height);
}
else
{
if ((Smear_mode != 0) && (Shade_table==Shade_table_left))
{
if (Smear_start != 0)
{
if ((width>0) && (height>0))
{
Copy_part_of_image_to_another(Main_screen,
start_x,start_y,
width,height,
Main_image_width,
Smear_brush,
start_x_counter,
start_y_counter,
Smear_brush_width);
Update_part_of_screen(start_x,start_y,width,height);
}
Smear_start=0;
}
else
{
for (y_pos=start_y,counter_y=start_y_counter;counter_y=Smear_min_Y) && (counter_x>=Smear_min_X) )
Display_pixel(x_pos,y_pos,Smear_brush[position]);
Smear_brush[position]=temp_color;
}
Update_part_of_screen(start_x,start_y,width,height);
}
Smear_min_X=start_x_counter;
Smear_min_Y=start_y_counter;
Smear_max_X=end_counter_x;
Smear_max_Y=end_counter_y;
}
else
{
for (y_pos=start_y,counter_y=start_y_counter;counter_y0) && (height>0) )
Display_brush_mono(start_x-Main_offset_X,
start_y-Main_offset_Y,
start_x_counter,start_y_counter,
width,height,
0,Fore_color,
MAX_PAINTBRUSH_SIZE);
if (Main_magnifier_mode != 0)
{
Compute_clipped_dimensions_zoom(&start_x,&start_y,&width,&height);
start_x_counter=start_x-(x-Paintbrush_offset_X);
start_y_counter=start_y-(y-Paintbrush_offset_Y);
if ( (width>0) && (height>0) )
{
// Corrections dues au Zoom:
start_x=(start_x-Main_magnifier_offset_X)*Main_magnifier_factor;
start_y=(start_y-Main_magnifier_offset_Y)*Main_magnifier_factor;
height=start_y+(height*Main_magnifier_factor);
if (height>Menu_Y)
height=Menu_Y;
Display_brush_mono_zoom(Main_X_zoom+start_x,start_y,
start_x_counter,start_y_counter,
width,height,
0,Fore_color,
MAX_PAINTBRUSH_SIZE,
Horizontal_line_buffer);
}
}
Brush=temp;
}
else
{
if ((Smear_mode != 0) && (Shade_table==Shade_table_left))
{
if (Smear_start != 0)
{
if ((width>0) && (height>0))
{
Copy_part_of_image_to_another(Main_screen,
start_x,start_y,
width,height,
Main_image_width,
Smear_brush,
start_x_counter,
start_y_counter,
Smear_brush_width);
Update_part_of_screen(start_x,start_y,width,height);
}
Smear_start=0;
}
else
{
for (y_pos=start_y,counter_y=start_y_counter;counter_y=Smear_min_Y) && (counter_x>=Smear_min_X)
// On clippe l'effet smear entre Smear_Min et Smear_Max
)
Display_pixel(x_pos,y_pos,Smear_brush[position]);
Smear_brush[position]=temp_color;
}
Update_part_of_screen(start_x, start_y, width, height);
}
Smear_min_X=start_x_counter;
Smear_min_Y=start_y_counter;
Smear_max_X=end_counter_x;
Smear_max_Y=end_counter_y;
}
else
{
for (y_pos=start_y,counter_y=start_y_counter;counter_yMAX_PAINTBRUSH_SIZE)?new_brush_width:MAX_PAINTBRUSH_SIZE;
new_smear_brush_height=(new_brush_height>MAX_PAINTBRUSH_SIZE)?new_brush_height:MAX_PAINTBRUSH_SIZE;
new_smear_brush=NULL;
if ( (((long)Smear_brush_height)*Smear_brush_width) !=
(((long)new_smear_brush_width)*new_smear_brush_height) )
{
new_smear_brush=(byte *)malloc(((long)new_smear_brush_height)*new_smear_brush_width);
if (new_smear_brush == NULL)
{
Error(0);
if (old_brush)
*old_brush=NULL;
if (!new_brush_is_provided)
free(new_brush);
return 2;
}
}
new_brush_remapped=NULL;
if ( (((long)Brush_height)*Brush_width) !=
(((long)new_brush_height)*new_brush_width) )
{
new_brush_remapped=(byte *)malloc(((long)new_brush_height)*new_brush_width);
if (new_brush_remapped == NULL)
{
Error(0);
free(new_smear_brush);
if (old_brush)
*old_brush=NULL;
if (!new_brush_is_provided)
free(new_brush);
return 3;
}
}
// All allocations successful: can replace globals
Brush_width=new_brush_width;
Brush_height=new_brush_height;
Brush_original_back_color=Back_color;
if (new_smear_brush)
{
free(Smear_brush);
Smear_brush=new_smear_brush;
}
Smear_brush_width=new_smear_brush_width;
Smear_brush_height=new_smear_brush_height;
// Save or free the old brush pixels
if (old_brush)
*old_brush=Brush_original_pixels;
else
free(old_brush);
Brush_original_pixels=new_brush;
// Assign new brush
if (new_brush_remapped)
{
free(Brush);
Brush=new_brush_remapped;
}
return 0;
}
// -- Effacer le pinceau -- //
//
void Hide_paintbrush(short x,short y)
// x,y: position du centre du pinceau
{
short start_x; // Position X (dans l'image) partir de laquelle on
// affiche la brosse/pinceau
short start_y; // Position Y (dans l'image) partir de laquelle on
// affiche la brosse/pinceau
short width; // width dans l'cran selon laquelle on affiche la
// brosse/pinceau
short height; // height dans l'cran selon laquelle on affiche la
// brosse/pinceau
short start_x_counter; // Position X (dans la brosse/pinceau) partir
// de laquelle on affiche la brosse/pinceau
short start_y_counter; // Position Y (dans la brosse/pinceau) partir
// de laquelle on affiche la brosse/pinceau
//short x_pos; // Position X (dans l'image) en cours d'affichage
//short y_pos; // Position Y (dans l'image) en cours d'affichage
//short counter_x; // Position X (dans la brosse/pinceau) en cours
//d'affichage
//short counter_y; // Position Y (dans la brosse/pinceau) en cours d'affichage
short end_counter_x; // Position X ou s'arrte l'affichage de la brosse/pinceau
short end_counter_y; // Position Y ou s'arrte l'affichage de la brosse/pinceau
byte * temp;
if (Mouse_K == 0)
switch (Paintbrush_shape)
{
case PAINTBRUSH_SHAPE_POINT :
if ( (Paintbrush_X>=Limit_left)
&& (Paintbrush_X<=Limit_right)
&& (Paintbrush_Y>=Limit_top)
&& (Paintbrush_Y<=Limit_bottom) )
{
Pixel_preview(Paintbrush_X,Paintbrush_Y,Read_pixel_from_current_screen(Paintbrush_X,Paintbrush_Y));
Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1);
}
break;
case PAINTBRUSH_SHAPE_COLOR_BRUSH : // Brush en couleur
case PAINTBRUSH_SHAPE_MONO_BRUSH : // Brush monochrome
start_x=x-Brush_offset_X;
start_y=y-Brush_offset_Y;
width=Brush_width;
height=Brush_height;
Compute_clipped_dimensions(&start_x,&start_y,&width,&height);
start_x_counter=start_x-(x-Brush_offset_X);
start_y_counter=start_y-(y-Brush_offset_Y);
end_counter_x=start_x_counter+width;
end_counter_y=start_y_counter+height;
if ( (width>0) && (height>0) )
Clear_brush(start_x-Main_offset_X,
start_y-Main_offset_Y,
start_x_counter,start_y_counter,
width,height,Back_color,
Main_image_width);
if (Main_magnifier_mode != 0)
{
Compute_clipped_dimensions_zoom(&start_x,&start_y,&width,&height);
start_x_counter=start_x;
start_y_counter=start_y;
if ( (width>0) && (height>0) )
{
// Corrections dues au Zoom:
start_x=(start_x-Main_magnifier_offset_X)*Main_magnifier_factor;
start_y=(start_y-Main_magnifier_offset_Y)*Main_magnifier_factor;
height=start_y+(height*Main_magnifier_factor);
if (height>Menu_Y)
height=Menu_Y;
Clear_brush_scaled(Main_X_zoom+start_x,start_y,
start_x_counter,start_y_counter,
width,height,Back_color,
Main_image_width,
Horizontal_line_buffer);
}
}
break;
default: // Pinceau
start_x=x-Paintbrush_offset_X;
start_y=y-Paintbrush_offset_Y;
width=Paintbrush_width;
height=Paintbrush_height;
Compute_clipped_dimensions(&start_x,&start_y,&width,&height);
start_x_counter=start_x-(x-Paintbrush_offset_X);
start_y_counter=start_y-(y-Paintbrush_offset_Y);
end_counter_x=start_x_counter+width;
end_counter_y=start_y_counter+height;
temp=Brush;
Brush=Paintbrush_sprite;
if ( (width>0) && (height>0) )
{
Clear_brush(start_x-Main_offset_X,
start_y-Main_offset_Y,
start_x_counter,start_y_counter,
width,height,0,
Main_image_width);
}
if (Main_magnifier_mode != 0)
{
Compute_clipped_dimensions_zoom(&start_x,&start_y,&width,&height);
start_x_counter=start_x;
start_y_counter=start_y;
if ( (width>0) && (height>0) )
{
// Corrections dues au Zoom:
start_x=(start_x-Main_magnifier_offset_X)*Main_magnifier_factor;
start_y=(start_y-Main_magnifier_offset_Y)*Main_magnifier_factor;
height=start_y+(height*Main_magnifier_factor);
if (height>Menu_Y)
height=Menu_Y;
Clear_brush_scaled(Main_X_zoom+start_x,start_y,
start_x_counter,start_y_counter,
width,height,0,
Main_image_width,
Horizontal_line_buffer);
}
}
Brush=temp;
break;
}
}
void Capture_brush(short start_x,short start_y,short end_x,short end_y,short clear)
{
short temp;
short x_pos;
short y_pos;
word new_brush_width;
word new_brush_height;
// On commence par "redresser" les bornes:
if (start_x>end_x)
{
temp=start_x;
start_x =end_x;
end_x =temp;
}
if (start_y>end_y)
{
temp=start_y;
start_y =end_y;
end_y =temp;
}
// On ne capture la nouvelle brosse que si elle est au moins partiellement
// dans l'image:
if ((start_xMain_image_width)
new_brush_width=Main_image_width-start_x;
if (start_y+new_brush_height>Main_image_height)
new_brush_height=Main_image_height-start_y;
if (Realloc_brush(new_brush_width, new_brush_height, NULL, NULL))
return; // Unable to allocate the new brush, keep the old one.
Copy_image_to_brush(start_x,start_y,Brush_width,Brush_height,Main_image_width);
// On regarde s'il faut effacer quelque chose:
if (clear != 0)
{
for (y_pos=start_y;y_pos>1);
Brush_offset_Y=(Brush_height>>1);
}
}
void Rotate_90_deg(void)
{
byte * old_brush;
if (Realloc_brush(Brush_height, Brush_width, NULL, &old_brush))
{
Error(0);
return;
}
Rotate_90_deg_lowlevel(old_brush,Brush_original_pixels,Brush_height,Brush_width);
free(old_brush);
// Remap according to the last used remap table
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
// On centre la prise sur la brosse
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
}
void Remap_brush(void)
{
short x_pos; // Variable de balayage de la brosse
short y_pos; // Variable de balayage de la brosse
int color;
// On commence par initialiser le tableau de boolens faux
for (color=0;color<=255;color++)
Brush_colormap[color]=0;
// On calcule la table d'utilisation des couleurs
for (y_pos=0;y_pos>1);
Brush_offset_Y=(Brush_height>>1);
free(old_brush); // Libration de l'ancienne brosse
}
void Nibble_brush(void)
{
long x_pos,y_pos;
byte state;
byte * old_brush;
word old_width;
word old_height;
int i;
if ( (Brush_width>2) && (Brush_height>2) )
{
old_width=Brush_width;
old_height=Brush_height;
SWAP_PBYTES(Brush, Brush_original_pixels);
if (Realloc_brush(Brush_width-2, Brush_height-2, NULL, &old_brush))
{
Error(0);
SWAP_PBYTES(Brush, Brush_original_pixels);
return;
}
// On copie l'ancienne brosse dans la nouvelle
Copy_part_of_image_to_another(old_brush, // source
1,
1,
old_width-2,
old_height-2,
old_width,
Brush, // Destination
0,
0,
Brush_width);
// 1er balayage (horizontal)
for (y_pos=0; y_pos0)
Pixel_in_brush(x_pos-1,y_pos,Back_color);
state=0;
}
}
else
{
if (state == 0)
{
Pixel_in_brush(x_pos,y_pos,Back_color);
state=1;
}
}
}
// Cas du dernier pixel droite de la ligne
if (old_brush[((y_pos+1)*old_width)+x_pos+1]==Back_color)
Pixel_in_brush(x_pos-1,y_pos,Back_color);
}
// 2me balayage (vertical)
for (x_pos=0; x_pos0)
Pixel_in_brush(x_pos,y_pos-1,Back_color);
state=0;
}
}
else
{
if (state == 0)
{
Pixel_in_brush(x_pos,y_pos,Back_color);
state=1;
}
}
}
// Cas du dernier pixel en bas de la colonne
if (old_brush[((y_pos+1)*old_width)+x_pos+1]==Back_color)
Pixel_in_brush(x_pos,y_pos-1,Back_color);
}
free(old_brush);
// Adopt the current palette.
memcpy(Brush_original_palette, Main_palette,sizeof(T_Palette));
memcpy(Brush_original_pixels, Brush, (long)Brush_width*Brush_height);
for (i=0; i<256; i++)
Brush_colormap[i]=i;
//--
// On recentre la prise sur la brosse
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
}
}
void Capture_brush_with_lasso(int vertices, short * points,short clear)
{
short start_x=Limit_right+1;
short start_y=Limit_bottom+1;
short end_x=Limit_left-1;
short end_y=Limit_top-1;
unsigned short temp;
short x_pos;
short y_pos;
word new_brush_width;
word new_brush_height;
// On recherche les bornes de la brosse:
for (temp=0; temp<2*vertices; temp+=2)
{
x_pos=points[temp];
y_pos=points[temp+1];
if (x_posend_x)
end_x=x_pos;
if (y_posend_y)
end_y=y_pos;
}
// On clippe ces bornes l'cran:
if (start_xLimit_right)
end_x=Limit_right;
if (start_yLimit_bottom)
end_y=Limit_bottom;
// On ne capture la nouvelle brosse que si elle est au moins partiellement
// dans l'image:
if ((start_x>1);
Brush_offset_Y=(Brush_height>>1);
}
}
//------------------------- Etirement de la brosse ---------------------------
void Stretch_brush(short x1, short y1, short x2, short y2)
{
byte * new_brush;
int new_brush_width; // Width de la nouvelle brosse
int new_brush_height; // Height de la nouvelle brosse
int x_flipped, y_flipped;
// Compute new brush dimensions
if ((new_brush_width=x1-x2)<0)
{
x_flipped=1;
new_brush_width=-new_brush_width;
}
new_brush_width++;
if ((new_brush_height=y1-y2)<0)
{
y_flipped=1;
new_brush_height=-new_brush_height;
}
new_brush_height++;
new_brush=((byte *)malloc(new_brush_width*new_brush_height));
if (!new_brush)
{
Error(0);
return;
}
Rescale(Brush_original_pixels, Brush_width, Brush_height, new_brush, new_brush_width, new_brush_height, x2>1);
Brush_offset_Y=(Brush_height>>1);
}
void Stretch_brush_preview(short x1, short y1, short x2, short y2)
{
int src_x_pos,src_y_pos;
int initial_src_x_pos,initial_src_y_pos;
int delta_x,delta_y;
int dest_x_pos,dest_y_pos;
int initial_dest_x_pos,initial_dest_y_pos;
int final_dest_x_pos,final_dest_y_pos;
int dest_width,dest_height;
byte color;
// 1er calcul des positions destination extremes:
initial_dest_x_pos=Min(x1,x2);
initial_dest_y_pos=Min(y1,y2);
final_dest_x_pos =Max(x1,x2);
final_dest_y_pos =Max(y1,y2);
// Calcul des dimensions de la destination:
dest_width=final_dest_x_pos-initial_dest_x_pos+1;
dest_height=final_dest_y_pos-initial_dest_y_pos+1;
// Calcul des vecteurs d'incrmentation :
delta_x=(Brush_width<<16)/dest_width;
delta_y=(Brush_height<<16)/dest_height;
// 1er calcul de la position X initiale dans la source:
initial_src_x_pos=(Brush_width<<16)*
(Max(initial_dest_x_pos,Limit_left)-
initial_dest_x_pos)/dest_width;
// Calcul du clip de la destination:
initial_dest_x_pos=Max(initial_dest_x_pos,Limit_left);
final_dest_x_pos =Min(final_dest_x_pos ,Limit_visible_right);
// On discute selon l'inversion en X
if (x1>x2)
{
// Inversion -> Inversion du signe de delta_x
delta_x=-delta_x;
initial_src_x_pos=(Brush_width<<16)-1-initial_src_x_pos;
}
// 1er calcul de la position Y initiale dans la source:
initial_src_y_pos=(Brush_height<<16)*
(Max(initial_dest_y_pos,Limit_top)-
initial_dest_y_pos)/dest_height;
// Calcul du clip de la destination:
initial_dest_y_pos=Max(initial_dest_y_pos,Limit_top);
final_dest_y_pos =Min(final_dest_y_pos ,Limit_visible_bottom);
// On discute selon l'inversion en Y
if (y1>y2)
{
// Inversion -> Inversion du signe de delta_y
delta_y=-delta_y;
initial_src_y_pos=(Brush_height<<16)-1-initial_src_y_pos;
}
// Pour chaque ligne :
src_y_pos=initial_src_y_pos;
for (dest_y_pos=initial_dest_y_pos;dest_y_pos<=final_dest_y_pos;dest_y_pos++)
{
// Pour chaque colonne:
src_x_pos=initial_src_x_pos;
for (dest_x_pos=initial_dest_x_pos;dest_x_pos<=final_dest_x_pos;dest_x_pos++)
{
color=Read_pixel_from_brush(src_x_pos>>16,src_y_pos>>16);
if (color!=Back_color)
Pixel_preview(dest_x_pos,dest_y_pos,color);
src_x_pos+=delta_x;
}
src_y_pos+=delta_y;
}
Update_part_of_screen(initial_dest_x_pos,initial_dest_y_pos,dest_width,dest_height);
}
/// Returns the minimum of 4 integers.
int Min4(long int a, long int b, long int c, long int d)
{
if (ab)
if (c>d)
return a>c?a:c;
else
return a>d?a:d;
else
if (c>d)
return b>c?b:c;
else
return b>d?b:d;
}
// Recursive function for linear distortion.
void Draw_brush_linear_distort(unsigned long int tex_min_x,
unsigned long int tex_min_y,
unsigned long int tex_max_x,
unsigned long int tex_max_y,
long int x1,
long int y1,
long int x2,
long int y2,
long int x3,
long int y3,
long int x4,
long int y4)
{
static byte color;
// bounding rectangle
static long int min_x, max_x, min_y, max_y;
min_x=Min4(x1,x2,x3,x4);
max_x=Max4(x1,x2,x3,x4);
min_y=Min4(y1,y2,y3,y4);
max_y=Max4(y1,y2,y3,y4);
if ((max_x>>16) - (min_x>>16) <= 1 && (max_y>>16) - (min_y>>16) <= 1)
//if (max_x - min_x <= 1<<16 && max_y - min_y <= 1<<16)
{
if ((min_x<(max_x&0x7FFF0000)) && (min_y<(max_y&0x7FFF0000)))
{
color=Read_pixel_from_brush((tex_min_x)>>16,(tex_min_y)>>16);
if (color!=Back_color)
Pixel_for_distort(min_x>>16,min_y>>16,color);
}
return;
}
// Cut in 4 quarters and repeat
// "top left"
Draw_brush_linear_distort(tex_min_x,
tex_min_y,
(tex_min_x+tex_max_x)>>1,
(tex_min_y+tex_max_y)>>1,
x1,
y1,
(x1+x2)>>1,
(y1+y2)>>1,
(x1+x2+x3+x4)>>2,
(y1+y2+y3+y4)>>2,
(x1+x4)>>1,
(y1+y4)>>1);
// "top right"
Draw_brush_linear_distort((tex_min_x+tex_max_x)>>1,
tex_min_y,
tex_max_x,
(tex_min_y+tex_max_y)>>1,
(x1+x2)>>1,
(y1+y2)>>1,
x2,
y2,
(x2+x3)>>1,
(y2+y3)>>1,
(x1+x2+x3+x4)>>2,
(y1+y2+y3+y4)>>2);
// "bottom right"
Draw_brush_linear_distort((tex_min_x+tex_max_x)>>1,
(tex_min_y+tex_max_y)>>1,
tex_max_x,
tex_max_y,
(x1+x2+x3+x4)>>2,
(y1+y2+y3+y4)>>2,
(x2+x3)>>1,
(y2+y3)>>1,
x3,
y3,
(x3+x4)>>1,
(y3+y4)>>1);
// "bottom left"
Draw_brush_linear_distort(tex_min_x,
(tex_min_y+tex_max_y)>>1,
(tex_min_x+tex_max_x)>>1,
tex_max_y,
(x1+x4)>>1,
(y1+y4)>>1,
(x1+x2+x3+x4)>>2,
(y1+y2+y3+y4)>>2,
(x3+x4)>>1,
(y3+y4)>>1,
x4,
y4);
return;
}
/// Draws a distorted version of the brush, mapped over the given quad (picture coordinates).
void Distort_brush_preview(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4)
{
Pixel_for_distort=Pixel_figure_preview;
Draw_brush_linear_distort(0, 0, (Brush_width<<16), (Brush_height<<16), (x1<<16), (y1<<16), (x2<<16), (y2<<16), (x3<<16), (y3<<16), (x4<<16), (y4<<16));
}
/// Modifies the current brush, mapping it over the given quad.
void Distort_brush(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4)
{
short min_x, max_x, min_y, max_y;
short width, height;
byte * new_brush;
// Move all coordinates to start on (0,0)
min_x=Min4(x1,x2,x3,x4);
max_x=Max4(x1,x2,x3,x4);
min_y=Min4(y1,y2,y3,y4);
max_y=Max4(y1,y2,y3,y4);
x1-=min_x;
x2-=min_x;
x3-=min_x;
x4-=min_x;
y1-=min_y;
y2-=min_y;
y3-=min_y;
y4-=min_y;
width=Max(max_x-min_x, 1);
height=Max(max_y-min_y, 1);
new_brush=((byte *)malloc((long)width*height));
if (!new_brush)
{
// Out of memory while allocating new brush
Error(0);
return;
}
// Fill the new brush with backcolor, originally.
memset(new_brush,Back_color,((long)width)*height);
// Call distort routine
Pixel_for_distort=Pixel_in_distort_buffer;
Distort_buffer=new_brush;
Distort_buffer_width=width;
Draw_brush_linear_distort(0, 0, (Brush_width<<16), (Brush_height<<16), (x1<<16), (y1<<16), (x2<<16), (y2<<16), (x3<<16), (y3<<16), (x4<<16), (y4<<16));
if (Realloc_brush(width, height, new_brush, NULL))
{
free(new_brush);
Error(0);
return;
}
// Remap according to the last used remap table
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
// Re-center brush handle
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
}
//------------------------- Rotation de la brosse ---------------------------
#ifndef NAN
#define NAN (-1.0e20F)
#define isnan(x) ((x)==NAN)
#endif
float * ScanY_Xt[2];
float * ScanY_Yt[2];
float * ScanY_X[2];
void Interpolate_texture(int start_x,int start_y,int xt1,int yt1,
int end_x ,int end_y ,int xt2,int yt2,int height)
{
int x_pos,y_pos;
int incr_x,incr_y;
int i,cumul;
int delta_x,delta_y;
int delta_xt=xt2-xt1;
int delta_yt=yt2-yt1;
int delta_x2=end_x-start_x;
int delta_y2=end_y-start_y;
float xt,yt;
x_pos=start_x;
y_pos=start_y;
if (start_xdelta_y)
{
cumul=delta_x>>1;
for (i=0; i<=delta_x; i++)
{
if (cumul>=delta_x)
{
cumul-=delta_x;
y_pos+=incr_y;
}
if ((y_pos>=0) && (y_pos=ScanY_X[0][y_pos])
{
if (isnan(ScanY_X[1][y_pos]) // Droit non dfini
|| (x_pos>ScanY_X[1][y_pos]))
{
ScanY_X[1][y_pos]=(float)x_pos;
ScanY_Xt[1][y_pos]=xt;
ScanY_Yt[1][y_pos]=yt;
}
}
else
{
if (isnan(ScanY_X[1][y_pos])) // Droit non dfini
{
ScanY_X[1][y_pos]=ScanY_X[0][y_pos];
ScanY_Xt[1][y_pos]=ScanY_Xt[0][y_pos];
ScanY_Yt[1][y_pos]=ScanY_Yt[0][y_pos];
ScanY_X[0][y_pos]=(float)x_pos;
ScanY_Xt[0][y_pos]=xt;
ScanY_Yt[0][y_pos]=yt;
}
else
{
ScanY_X[0][y_pos]=(float)x_pos;
ScanY_Xt[0][y_pos]=xt;
ScanY_Yt[0][y_pos]=yt;
}
}
}
}
x_pos+=incr_x;
cumul+=delta_y;
}
}
else
{
cumul=delta_y>>1;
for (i=0; i<=delta_y; i++)
{
if (cumul>=delta_y)
{
cumul-=delta_y;
x_pos+=incr_x;
}
if ((y_pos>=0) && (y_pos=ScanY_X[0][y_pos])
{
if (isnan(ScanY_X[1][y_pos]) // Droit non dfini
|| (x_pos>ScanY_X[1][y_pos]))
{
ScanY_X[1][y_pos]=(float)x_pos;
ScanY_Xt[1][y_pos]=xt;
ScanY_Yt[1][y_pos]=yt;
}
}
else
{
if (isnan(ScanY_X[1][y_pos])) // Droit non dfini
{
ScanY_X[1][y_pos]=ScanY_X[0][y_pos];
ScanY_Xt[1][y_pos]=ScanY_Xt[0][y_pos];
ScanY_Yt[1][y_pos]=ScanY_Yt[0][y_pos];
ScanY_X[0][y_pos]=(float)x_pos;
ScanY_Xt[0][y_pos]=xt;
ScanY_Yt[0][y_pos]=yt;
}
else
{
ScanY_X[0][y_pos]=(float)x_pos;
ScanY_Xt[0][y_pos]=xt;
ScanY_Yt[0][y_pos]=yt;
}
}
}
}
y_pos+=incr_y;
cumul+=delta_x;
}
}
}
void Compute_quad_texture(int x1,int y1,int xt1,int yt1,
int x2,int y2,int xt2,int yt2,
int x3,int y3,int xt3,int yt3,
int x4,int y4,int xt4,int yt4,
byte * buffer, int width, int height)
{
int x_min,/*x_max,*/y_min/*,y_max*/;
int x,y,xt,yt;
int start_x,end_x,line_width;
float temp;
//byte color;
x_min=Min(Min(x1,x2),Min(x3,x4));
y_min=Min(Min(y1,y2),Min(y3,y4));
ScanY_Xt[0]=(float *)malloc(height*sizeof(float));
ScanY_Xt[1]=(float *)malloc(height*sizeof(float));
ScanY_Yt[0]=(float *)malloc(height*sizeof(float));
ScanY_Yt[1]=(float *)malloc(height*sizeof(float));
ScanY_X[0] =(float *)malloc(height*sizeof(float));
ScanY_X[1] =(float *)malloc(height*sizeof(float));
// Fill_general avec des valeurs gales NAN.
for (y=0; y=0 && yt>=0)
buffer[x+(y*width)]=*(Brush_original_pixels + yt * Brush_width + xt);
}
for (; x>1);
start_y=1-(Brush_height>>1);
end_x=start_x+Brush_width-1;
end_y=start_y+Brush_height-1;
Transform_point(start_x,start_y, cos_a,sin_a, &x1,&y1);
Transform_point(end_x ,start_y, cos_a,sin_a, &x2,&y2);
Transform_point(start_x,end_y , cos_a,sin_a, &x3,&y3);
Transform_point(end_x ,end_y , cos_a,sin_a, &x4,&y4);
// Calcul des nouvelles dimensions de la brosse:
x_min=Min(Min((int)x1,(int)x2),Min((int)x3,(int)x4));
x_max=Max(Max((int)x1,(int)x2),Max((int)x3,(int)x4));
y_min=Min(Min((int)y1,(int)y2),Min((int)y3,(int)y4));
y_max=Max(Max((int)y1,(int)y2),Max((int)y3,(int)y4));
new_brush_width=x_max+1-x_min;
new_brush_height=y_max+1-y_min;
new_brush=(byte *)malloc(new_brush_width*new_brush_height);
if (!new_brush)
{
Error(0);
return;
}
// Et maintenant on calcule la nouvelle brosse tourne.
Compute_quad_texture(x1,y1, 0, 0,
x2,y2,Brush_width-1, 0,
x3,y3, 0,Brush_height-1,
x4,y4,Brush_width-1,Brush_height-1,
new_brush,new_brush_width,new_brush_height);
if (Realloc_brush(new_brush_width, new_brush_height, new_brush, NULL))
{
free(new_brush);
return;
}
// Remap according to the last used remap table
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
// Center offsets
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
}
void Draw_quad_texture_preview(int x1,int y1,int xt1,int yt1,
int x2,int y2,int xt2,int yt2,
int x3,int y3,int xt3,int yt3,
int x4,int y4,int xt4,int yt4)
{
int x_min,x_max,y_min,y_max;
int x,y,xt,yt;
int y_,y_min_;
int start_x,end_x,width,height;
float temp;
byte color;
x_min=Min(Min(x1,x2),Min(x3,x4));
x_max=Max(Max(x1,x2),Max(x3,x4));
y_min=Min(Min(y1,y2),Min(y3,y4));
y_max=Max(Max(y1,y2),Max(y3,y4));
height=1+y_max-y_min;
ScanY_Xt[0]=(float *)malloc(height*sizeof(float));
ScanY_Xt[1]=(float *)malloc(height*sizeof(float));
ScanY_Yt[0]=(float *)malloc(height*sizeof(float));
ScanY_Yt[1]=(float *)malloc(height*sizeof(float));
ScanY_X[0] =(float *)malloc(height*sizeof(float));
ScanY_X[1] =(float *)malloc(height*sizeof(float));
// Fill_general avec des valeurs gales NAN.
for (y=0; yLimit_bottom) y_max=Limit_bottom;
for (y_=y_min; y_<=y_max; y_++)
{
y=y_-y_min_;
start_x=Round(ScanY_X[0][y]);
end_x =Round(ScanY_X[1][y]);
width=1+end_x-start_x;
if (start_xLimit_right) end_x=Limit_right;
for (x=start_x; x<=end_x; x++)
{
temp=(float)(0.5+(float)x-ScanY_X[0][y])/(float)width;
xt=Round((float)(ScanY_Xt[0][y])+(temp*(ScanY_Xt[1][y]-ScanY_Xt[0][y])));
yt=Round((float)(ScanY_Yt[0][y])+(temp*(ScanY_Yt[1][y]-ScanY_Yt[0][y])));
if (xt>=0 && yt>=0)
{
color=Read_pixel_from_brush(xt,yt);
if (color!=Back_color)
Pixel_preview(x,y_,color);
}
}
}
free(ScanY_Xt[0]);
free(ScanY_Xt[1]);
free(ScanY_Yt[0]);
free(ScanY_Yt[1]);
free(ScanY_X[0]);
free(ScanY_X[1]);
ScanY_Xt[0] = ScanY_Xt[1] = ScanY_Yt[0] = ScanY_Yt[1] = ScanY_X[0] = ScanY_X[1] = NULL;
}
void Rotate_brush_preview(float angle)
{
short x1,y1,x2,y2,x3,y3,x4,y4;
int start_x,end_x,start_y,end_y;
float cos_a=cos(angle);
float sin_a=sin(angle);
// Calcul des coordonnes des 4 coins:
// 1 2
// 3 4
start_x=1-(Brush_width>>1);
start_y=1-(Brush_height>>1);
end_x=start_x+Brush_width-1;
end_y=start_y+Brush_height-1;
Transform_point(start_x,start_y, cos_a,sin_a, &x1,&y1);
Transform_point(end_x ,start_y, cos_a,sin_a, &x2,&y2);
Transform_point(start_x,end_y , cos_a,sin_a, &x3,&y3);
Transform_point(end_x ,end_y , cos_a,sin_a, &x4,&y4);
x1+=Brush_rotation_center_X;
y1+=Brush_rotation_center_Y;
x2+=Brush_rotation_center_X;
y2+=Brush_rotation_center_Y;
x3+=Brush_rotation_center_X;
y3+=Brush_rotation_center_Y;
x4+=Brush_rotation_center_X;
y4+=Brush_rotation_center_Y;
// Et maintenant on dessine la brosse tourne.
Draw_quad_texture_preview(x1,y1, 0, 0,
x2,y2,Brush_width-1, 0,
x3,y3, 0,Brush_height-1,
x4,y4,Brush_width-1,Brush_height-1);
start_x=Min(Min(x1,x2),Min(x3,x4));
end_x=Max(Max(x1,x2),Max(x3,x4));
start_y=Min(Min(y1,y2),Min(y3,y4));
end_y=Max(Max(y1,y2),Max(y3,y4));
Update_part_of_screen(start_x,start_y,end_x-start_x+1,end_y-start_y+1);
}
/*
/// Sets brush's original palette and color mapping.
void Brush_set_palette(T_Palette *palette)
{
int i;
byte need_remap;
need_remap=0;
memcpy(Brush_original_palette,palette,sizeof(T_Palette));
for (i=0;i<256;i++)
{
if (Brush_original_palette[i].R!=Main_palette[i].R
|| Brush_original_palette[i].G!=Main_palette[i].G
|| Brush_original_palette[i].B!=Main_palette[i].B)
{
need_remap=1;
}
}
}
*/ grafx2/src/brush_ops.c 0000644 0000764 0001040 00000077123 11517642570 015413 0 ustar vig Administrator /* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues
Copyright 2009 Franck Charlet
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
*/
//////////////////////////////////////////////////////////////////////////////
///@file brush_ops.c
/// Code for operations about the brush (grabbing, rotating, ...) and magnifier
//////////////////////////////////////////////////////////////////////////////
#include
#include
#include "brush.h"
#include "buttons.h"
#include "engine.h"
#include "global.h"
#include "graph.h"
#include "misc.h"
#include "operatio.h"
#include "pages.h"
#include "sdlscreen.h"
#include "windows.h"
#if defined(__VBCC__) || defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__)
#define M_PI 3.141592653589793238462643
#endif
/// Simulates clicking the "Draw" button.
void Return_to_draw_mode(void)
{
// Comme l'enclenchement du bouton efface le curseur, il faut l'afficher au
// pralable:
Display_cursor();
if (Mouse_K)
Wait_end_of_click();
// !!! Efface la croix puis affiche le viseur !!!
Select_button(BUTTON_DRAW,LEFT_SIDE); // Dsenclenche au passage le bouton brosse
if (Config.Auto_discontinuous)
{
// On se place en mode Dessin discontinu la main
while (Current_operation!=OPERATION_DISCONTINUOUS_DRAW)
Select_button(BUTTON_DRAW,RIGHT_SIDE);
}
// Maintenant, il faut reffacer le curseur parce qu'il sera raffich en fin
// d'appel cette action:
Hide_cursor();
// On passe en brosse couleur:
Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
if ((Config.Coords_rel) && (Menu_is_visible))
Print_in_menu("X: Y:",0);
Print_coordinates();
}
// ---------------------------------------------------------- OPERATION_MAGNIFY
void Magnifier_12_0(void)
// Opration : 4 (item d'une Loupe)
// Click Souris: 1 ou 2
// Taille_Pile : 0
//
// Souris efface: Oui
{
// On passe en mode loupe
Main_magnifier_mode=1;
// La fonction d'affichage dans la partie image est dsormais un affichage
// spcial loupe.
Pixel_preview=Pixel_preview_magnifier;
// On calcule l'origine de la loupe
Main_magnifier_offset_X=Mouse_X-(Main_magnifier_width>>1);
Main_magnifier_offset_Y=Mouse_Y-(Main_magnifier_height>>1);
// Calcul des coordonnes absolues de ce coin DANS L'IMAGE
Main_magnifier_offset_X+=Main_offset_X;
Main_magnifier_offset_Y+=Main_offset_Y;
Clip_magnifier_offsets(&Main_magnifier_offset_X, &Main_magnifier_offset_Y);
// On calcule les bornes visibles dans l'cran
Position_screen_according_to_zoom();
Compute_limits();
Display_all_screen();
// Repositionner le curseur en fonction des coordonnes visibles
Compute_paintbrush_coordinates();
// On fait de notre mieux pour restaurer l'ancienne opration:
Start_operation_stack(Operation_before_interrupt);
Display_cursor();
Wait_end_of_click();
}
/////////////////////////////////////////////////////////// OPERATION_COLORPICK
void Colorpicker_12_0(void)
//
// Opration : OPERATION_COLORPICK
// Click Souris: 1 ou 2
// Taille_Pile : 0
//
// Souris efface: Oui
//
{
Init_start_operation();
if (Mouse_K==LEFT_SIDE)
{
Set_fore_color(Colorpicker_color);
}
else
{
Set_back_color(Colorpicker_color);
}
Operation_push(Mouse_K);
}
void Colorpicker_1_1(void)
//
// Opration : OPERATION_COLORPICK
// Click Souris: 1
// Taille_Pile : 1
//
// Souris efface: Non
//
{
char str[4];
if ( (Paintbrush_X>=0) && (Paintbrush_Y>=0)
&& (Paintbrush_X=0) && (Paintbrush_Y>=0)
&& (Paintbrush_X=0) && (Paintbrush_Y>=0)
&& (Paintbrush_X=Main_X_zoom) ) )
Print_in_menu("X: Y: ",0);
Print_coordinates();
Display_cursor();
}
////////////////////////////////////////////////////// OPERATION_GRAB_BRUSH
void Brush_12_0(void)
//
// Opration : OPERATION_GRAB_BRUSH
// Click Souris: 1 ou 2
// Taille_Pile : 0
//
// Souris efface: Oui
//
{
Init_start_operation();
if (Mouse_K==RIGHT_SIDE) // Besoin d'effacer la brosse aprs ?
{
Operation_push(1);
// Puisque la zone o on prend la brosse sera efface, on fait un backup
Backup();
}
else
Operation_push(0);
// On laisse une trace du curseur pour que l'utilisateur puisse visualiser
// o demarre sa brosse:
Display_cursor();
Operation_push(Paintbrush_X); // Dbut X
Operation_push(Paintbrush_Y); // Dbut Y
Operation_push(Paintbrush_X); // Dernire position X
Operation_push(Paintbrush_Y); // Dernire position Y
if ((Config.Coords_rel) && (Menu_is_visible))
Print_in_menu("\035: 1 \022: 1",0);
}
void Brush_12_5(void)
//
// Opration : OPERATION_GRAB_BRUSH
// Click Souris: 1 ou 2
// Taille_Pile : 5
//
// Souris efface: Non
//
{
char str[5];
short start_x;
short start_y;
short old_x;
short old_y;
short width;
short height;
Operation_pop(&old_y);
Operation_pop(&old_x);
if ( (Menu_is_visible) && ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y)) )
{
if (Config.Coords_rel)
{
Operation_pop(&start_y);
Operation_pop(&start_x);
Operation_push(start_x);
Operation_push(start_y);
width=((start_x1) width--;
if (height>1) height--;
}
Num2str(width,str,4);
Print_in_menu(str,2);
Num2str(height,str,4);
Print_in_menu(str,11);
}
else
Print_coordinates();
}
Display_all_screen();
x=Paintbrush_X;
y=Paintbrush_Y;
if (Snap_mode && Config.Adjust_brush_pick)
{
dx=Paintbrush_X-start_x;
dy=Paintbrush_Y-start_y;
if (dx<0) x++; else {if (dx>0) x--;}
if (dy<0) y++; else {if (dy>0) y--;}
Stretch_brush_preview(start_x,start_y,x,y);
}
else
Stretch_brush_preview(start_x,start_y,Paintbrush_X,Paintbrush_Y);
old_x=Paintbrush_X;
old_y=Paintbrush_Y;
Paintbrush_X=start_x;
Paintbrush_Y=start_y;
Display_cursor();
Paintbrush_X=old_x;
Paintbrush_Y=old_y;
Display_cursor();
Operation_stack_size-=2;
Operation_push(x);
Operation_push(y);
Operation_push(start_x);
Operation_push(start_y);
}
Operation_push(Paintbrush_X);
Operation_push(Paintbrush_Y);
Operation_push(2);
}
void Stretch_brush_0_7(void)
//
// Opration : OPERATION_STRETCH_BRUSH
// Click Souris: 0
// Taille_Pile : 7
//
// Souris efface: Non
//
{
char str[5];
short start_x;
short start_y;
short old_x;
short old_y;
short width=0;
short height=0;
byte size_change;
short prev_state;
Operation_pop(&prev_state);
Operation_pop(&old_y);
Operation_pop(&old_x);
Operation_pop(&start_y);
Operation_pop(&start_x);
if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) || (prev_state!=3))
{
if (Menu_is_visible)
{
if (Config.Coords_rel)
{
width=((start_x1)?start_x+(Brush_width>>1)-1:1;
height=(Brush_height>1)?start_y+(Brush_height>>1)-1:1;
break;
case 'X': // Moiti X
width=(Brush_width>1)?start_x+(Brush_width>>1)-1:1;
height=start_y+Brush_height-1;
break;
case 'Y': // Moiti Y
width=start_x+Brush_width-1;
height=(Brush_height>1)?start_y+(Brush_height>>1)-1:1;
break;
case 'n': // Normal
width=start_x+Brush_width-1;
height=start_y+Brush_height-1;
break;
default :
size_change=0;
}
Key_ANSI=0;
}
else
size_change=0;
if (size_change)
{
// On efface la preview de la brosse (et la croix)
Display_all_screen();
old_x=Paintbrush_X;
old_y=Paintbrush_Y;
Paintbrush_X=start_x;
Paintbrush_Y=start_y;
Display_cursor();
Paintbrush_X=old_x;
Paintbrush_Y=old_y;
Stretch_brush_preview(start_x,start_y,width,height);
Display_cursor();
Operation_stack_size-=2;
Operation_push(width);
Operation_push(height);
}
Operation_push(start_x);
Operation_push(start_y);
Operation_push(Paintbrush_X);
Operation_push(Paintbrush_Y);
Operation_push(3);
}
void Stretch_brush_2_7(void)
//
// Opration : OPERATION_STRETCH_BRUSH
// Click Souris: 2
// Taille_Pile : 7
//
// Souris efface: Oui
//
{
short computed_x;
short computed_y;
short start_x;
short start_y;
Operation_stack_size-=3;
Operation_pop(&start_y);
Operation_pop(&start_x);
Operation_pop(&computed_y);
Operation_pop(&computed_x);
// On efface la preview de la brosse (et la croix)
Display_all_screen();
// Et enfin on stocke pour de bon la nouvelle brosse tire
Stretch_brush(start_x,start_y,computed_x,computed_y);
Return_to_draw_mode();
}
//////////////////////////////////////////////////// OPERATION_ROTATE_BRUSH
void Rotate_brush_12_0(void)
//
// Opration : OPERATION_ROTATE_BRUSH
// Click Souris: 1 ou 2
// Taille_Pile : 0
//
// Souris efface: Oui
//
{
Init_start_operation();
if (Mouse_K==LEFT_SIDE)
{
Brush_rotation_center_X=Paintbrush_X+(Brush_width>>1)-Brush_width;
Brush_rotation_center_Y=Paintbrush_Y;
Brush_rotation_center_is_defined=1;
Operation_push(Paintbrush_X); // Dernire position calcule X
Operation_push(Paintbrush_Y); // Dernire position calcule Y
Operation_push(Paintbrush_X); // Dernire position X
Operation_push(Paintbrush_Y); // Dernire position Y
Operation_push(1); // State prcdent
if ((Config.Coords_rel) && (Menu_is_visible))
Print_in_menu("Angle: 0 ",0);
}
else
{
Start_operation_stack(Operation_before_interrupt);
Wait_end_of_click(); // FIXME: celui-la il donne un rsultat pas trs chouette en visuel
}
}
void Rotate_brush_1_5(void)
//
// Opration : OPERATION_ROTATE_BRUSH
// Click Souris: 1
// Taille_Pile : 5
//
// Souris efface: Non
//
{
char str[4];
short old_x;
short old_y;
short prev_state;
float angle;
int dx,dy;
Operation_pop(&prev_state);
Operation_pop(&old_y);
Operation_pop(&old_x);
// On corrige les coordonnes de la ligne si la touche shift est appuye...
if(SDL_GetModState() & KMOD_SHIFT)
Clamp_coordinates_regular_angle(Brush_rotation_center_X,Brush_rotation_center_Y,&Paintbrush_X,&Paintbrush_Y);
if ( (Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) || (prev_state!=2) )
{
if ( (Brush_rotation_center_X==Paintbrush_X)
&& (Brush_rotation_center_Y==Paintbrush_Y) )
angle=0.0;
else
{
dx=Paintbrush_X-Brush_rotation_center_X;
dy=Paintbrush_Y-Brush_rotation_center_Y;
angle=acos(((float)dx)/sqrt((dx*dx)+(dy*dy)));
if (dy>0) angle=M_2PI-angle;
}
if (Menu_is_visible)
{
if (Config.Coords_rel)
{
Num2str((int)(angle*180.0/M_PI),str,3);
Print_in_menu(str,7);
}
else
Print_coordinates();
}
Display_all_screen();
Rotate_brush_preview(angle);
Display_cursor();
Operation_stack_size-=2;
Operation_push(Paintbrush_X);
Operation_push(Paintbrush_Y);
}
Operation_push(Paintbrush_X);
Operation_push(Paintbrush_Y);
Operation_push(2);
}
void Rotate_brush_0_5(void)
//
// Opration : OPERATION_ROTATE_BRUSH
// Click Souris: 0
// Taille_Pile : 5
//
// Souris efface: Non
//
{
char str[4];
short old_x;
short old_y;
short computed_x=0;
short computed_y=0;
byte angle_change;
short prev_state;
float angle=0.0;
int dx,dy;
Operation_pop(&prev_state);
Operation_pop(&old_y);
Operation_pop(&old_x);
// On corrige les coordonnes de la ligne si la touche shift est appuye...
if(SDL_GetModState() & KMOD_SHIFT)
Clamp_coordinates_regular_angle(Brush_rotation_center_X,Brush_rotation_center_Y,&Paintbrush_X,&Paintbrush_Y);
if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) || (prev_state!=3))
{
if ( (Brush_rotation_center_X==Paintbrush_X)
&& (Brush_rotation_center_Y==Paintbrush_Y) )
angle=0.0;
else
{
dx=Paintbrush_X-Brush_rotation_center_X;
dy=Paintbrush_Y-Brush_rotation_center_Y;
angle=acos(((float)dx)/sqrt((dx*dx)+(dy*dy)));
if (dy>0) angle=M_2PI-angle;
}
if (Menu_is_visible)
{
if (Config.Coords_rel)
{
Num2str(Round(angle*180.0/M_PI),str,3);
Print_in_menu(str,7);
}
else
Print_coordinates();
}
}
// Utilise Key_ANSI au lieu de Key, car Get_input() met ce dernier
// zero si une operation est en cours (Operation_stack_size!=0)
if (Key_ANSI)
{
angle_change=1;
computed_x=Brush_rotation_center_X;
computed_y=Brush_rotation_center_Y;
switch (Key_ANSI)
{
case '6': angle= 0.0 ; computed_x++; break;
case '9': angle=M_PI*0.25; computed_x++; computed_y--; break;
case '8': angle=M_PI*0.5 ; computed_y--; break;
case '7': angle=M_PI*0.75; computed_x--; computed_y--; break;
case '4': angle=M_PI ; computed_x--; break;
case '1': angle=M_PI*1.25; computed_x--; computed_y++; break;
case '2': angle=M_PI*1.5 ; computed_y++; break;
case '3': angle=M_PI*1.75; computed_x++; computed_y++; break;
default :
angle_change=0;
}
Key_ANSI=0;
}
else
angle_change=0;
if (angle_change)
{
// On efface la preview de la brosse
Display_all_screen();
Rotate_brush_preview(angle);
Display_cursor();
Operation_stack_size-=2;
Operation_push(computed_x);
Operation_push(computed_y);
}
Operation_push(Paintbrush_X);
Operation_push(Paintbrush_Y);
Operation_push(3);
}
void Rotate_brush_2_5(void)
//
// Opration : OPERATION_ROTATE_BRUSH
// Click Souris: 2
// Taille_Pile : 5
//
// Souris efface: Oui
//
{
short computed_x;
short computed_y;
int dx,dy;
float angle;
// On efface la preview de la brosse
Display_all_screen();
Operation_stack_size-=3;
Operation_pop(&computed_y);
Operation_pop(&computed_x);
// Calcul de l'angle par rapport la dernire position calcule
if ( (Brush_rotation_center_X==computed_x)
&& (Brush_rotation_center_Y==computed_y) )
angle=0.0;
else
{
dx=computed_x-Brush_rotation_center_X;
dy=computed_y-Brush_rotation_center_Y;
angle=acos(((float)dx)/sqrt((dx*dx)+(dy*dy)));
if (dy>0) angle=M_2PI-angle;
}
// Et enfin on stocke pour de bon la nouvelle brosse tire
Rotate_brush(angle);
Return_to_draw_mode();
}
///////////////////////////////////////////////////// OPERATION_DISTORT_BRUSH
/// Draws a 2x2 XOR square at the specified picture coordinates, on the screen.
void Draw_stretch_spot(short x_pos, short y_pos)
{
short x,y;
for (y=y_pos-1;y=Limit_top && y<=Limit_visible_bottom)
for (x=x_pos-1;x=Limit_left && x<=Limit_visible_right)
Pixel_preview(x,y,~Read_pixel(x-Main_offset_X,y-Main_offset_Y));
Update_part_of_screen(x_pos-1, y_pos-1, 2, 2);
}
void Distort_brush_0_0(void)
//
// Opration : OPERATION_DISTORT_BRUSH
// Click Souris: 0
// Taille_Pile : 0
//
// Souris efface: Non
//
{
if ( Menu_is_visible )
{
Print_in_menu("POSITION BRUSH TO START ",0);
}
}
void Distort_brush_1_0(void)
//
// Opration : OPERATION_DISTORT_BRUSH
// Click Souris: 1
// Taille_Pile : 0
//
// Souris efface: Non
//
{
short x_pos, y_pos;
Init_start_operation();
Paintbrush_hidden=1;
Hide_cursor();
// Top left angle
x_pos=Paintbrush_X-Brush_offset_X;
y_pos=Paintbrush_Y-Brush_offset_Y;
Draw_stretch_spot(x_pos,y_pos);
Operation_push(x_pos);
Operation_push(y_pos);
// Top right angle
x_pos+=Brush_width;
Draw_stretch_spot(x_pos,y_pos);
Operation_push(x_pos);
Operation_push(y_pos);
// Bottom right angle
y_pos+=Brush_height;
Draw_stretch_spot(x_pos,y_pos);
Operation_push(x_pos);
Operation_push(y_pos);
// Bottom left angle
x_pos-=Brush_width;
Draw_stretch_spot(x_pos,y_pos);
Operation_push(x_pos);
Operation_push(y_pos);
Distort_brush_preview(
Operation_stack[1],
Operation_stack[2],
Operation_stack[3],
Operation_stack[4],
Operation_stack[5],
Operation_stack[6],
Operation_stack[7],
Operation_stack[8]);
Display_cursor();
Update_part_of_screen(Paintbrush_X-Brush_offset_X, Paintbrush_Y-Brush_offset_Y, Brush_width, Brush_height);
Wait_end_of_click();
// Erase the message in status bar
if ( (Config.Coords_rel) && (Menu_is_visible) )
{
Print_in_menu("X: Y: ",0);
}
}
void Distort_brush_1_8(void)
//
// Opration : OPERATION_DISTORT_BRUSH
// Click Souris: 1
// Taille_Pile : 8
//
// Souris efface: No
//
{
// How far (in pixels) you can catch a handle
#define REACH_DISTANCE 100
short i;
short x[4];
short y[4];
long best_distance=REACH_DISTANCE;
short best_spot=-1;
for (i=3;i>=0;i--)
{
long distance;
Operation_pop(&y[i]);
Operation_pop(&x[i]);
distance=Distance(Paintbrush_X,Paintbrush_Y,x[i],y[i]);
if (distance-1)
{
Operation_push(best_spot);
}
if ( (Config.Coords_rel) && (Menu_is_visible) )
{
Print_in_menu("X: Y: ",0);
Print_coordinates();
}
}
void Distort_brush_1_9(void)
//
// Opration : OPERATION_DISTORT_BRUSH
// Click Souris: 1
// Taille_Pile : 9
//
// Souris efface: No
//
{
short i;
short x[4];
short y[4];
short selected_corner;
// Pop all arguments
Operation_pop(&selected_corner);
for (i=3;i>=0;i--)
{
Operation_pop(&y[i]);
Operation_pop(&x[i]);
}
if (Paintbrush_X!=x[selected_corner] || Paintbrush_Y!=y[selected_corner])
{
Hide_cursor();
// Easiest refresh mode: make no assumptions on how the brush was
// displayed before.
Display_all_screen();
x[selected_corner]=Paintbrush_X;
y[selected_corner]=Paintbrush_Y;
for (i=0;i<4;i++)
Draw_stretch_spot(x[i],y[i]);
Distort_brush_preview(x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]);
Display_cursor();
if ( (Config.Coords_rel) && (Menu_is_visible) )
{
Print_in_menu("X: Y: ",0);
Print_coordinates();
}
Update_rect(0,0,Screen_width,Menu_Y);
}
// Push back all arguments
for (i=0;i<4;i++)
{
Operation_push(x[i]);
Operation_push(y[i]);
}
Operation_push(selected_corner);
}
void Distort_brush_0_9(void)
//
// Opration : OPERATION_DISTORT_BRUSH
// Click Souris: 0
// Taille_Pile : 9
//
// Souris efface: No
//
{
short selected_corner;
Operation_pop(&selected_corner);
}
void Distort_brush_2_0(void)
//
// Opration : OPERATION_DISTORT_BRUSH
// Click Souris: 2
// Taille_Pile : 0
//
// Souris efface: Oui
//
{
Paintbrush_hidden=0;
Display_all_screen();
// Erase the message in status bar
if ( (Config.Coords_rel) && (Menu_is_visible) )
{
Print_in_menu("X: Y: ",0);
}
Return_to_draw_mode();
}
void Distort_brush_2_8(void)
//
// Opration : OPERATION_DISTORT_BRUSH
// Click Souris: 2
// Taille_Pile : 8
//
// Souris efface: Oui
//
{
short i;
short x[4];
short y[4];
// Pop all arguments
for (i=3;i>=0;i--)
{
Operation_pop(&y[i]);
Operation_pop(&x[i]);
}
Distort_brush(x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]);
Paintbrush_hidden=0;
Display_all_screen();
Return_to_draw_mode();
}
grafx2/src/buttons.c 0000644 0000764 0001040 00000473560 11553130706 015103 0 ustar vig Administrator /* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Gralski
Copyright 2008 Yves Rizoud
Copyright 2007-2010 Adrien Destugues (PulkoMandy)
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
*/
#if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
#include
#include
#include
#elif defined(__WIN32__)
#include
#include
#else
#include
#endif
#define _XOPEN_SOURCE 500
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "const.h"
#include "struct.h"
#include "global.h"
#include "misc.h"
#include "graph.h"
#include "engine.h"
#include "readline.h"
#include "filesel.h"
#include "loadsave.h"
#include "init.h"
#include "buttons.h"
#include "operatio.h"
#include "pages.h"
#include "palette.h"
#include "errors.h"
#include "readini.h"
#include "saveini.h"
#include "shade.h"
#include "io.h"
#include "help.h"
#include "text.h"
#include "sdlscreen.h"
#include "windows.h"
#include "brush.h"
#include "input.h"
#include "special.h"
#include "setup.h"
#ifdef __VBCC__
#define __attribute__(x)
#endif
#if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
#include
#include
#elif defined(__MINT__)
#include
#include
#elif defined(__WIN32__)
#include
#include
#else
#include
#endif
extern char Program_version[]; // generated in pversion.c
extern short Old_MX;
extern short Old_MY;
//-- MODELE DE BOUTON DE MENU ------------------------------------------------
/*
void Bouton_***(void)
{
short clicked_button;
Open_window(310,190,"***");
Window_set_normal_button(103,137,80,14,"OK",0,1,SDLK_RETURN); // 1
Window_set_scroller_button(18,44,88,16,4,0); // 2
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
clicked_button=Window_clicked_button();
}
while (clicked_button!=1);
Close_window();
Unselect_button(BOUTON_***);
Display_cursor();
}
*/
void Message_out_of_memory(void)
{
short clicked_button;
Open_window(216,76,"Not enough memory!");
Print_in_window(8,20,"Please consult the manual",MC_Black,MC_Light);
Print_in_window(24,28,"to know how to obtain",MC_Black,MC_Light);
Print_in_window(36,36,"more memory space.",MC_Black,MC_Light);
Window_set_normal_button(60,53,40,14,"OK",1,1,SDLK_RETURN); // 1
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
clicked_button=Window_clicked_button();
while ((clicked_button<=0) && (Key!=KEY_ESC) && (Key!=SDLK_o));
if(clicked_button<=0) Key=0;
Close_window();
Display_cursor();
}
void Button_Message_initial(void)
{
char str[30];
int x_pos,offs_y,x,y;
strcpy(str,"GrafX2 version ");
strcat(str,Program_version);
Open_window(260,172,str);
Window_display_frame_in(10,20,239,62);
Block(Window_pos_X+(Menu_factor_X*11),
Window_pos_Y+(Menu_factor_Y*21),
Menu_factor_X*237,Menu_factor_Y*60,MC_Black);
for (y=23,offs_y=0; y<79; offs_y+=231,y++)
for (x=14,x_pos=0; x_pos<231; x_pos++,x++)
Pixel_in_window(x,y,Gfx->Logo_grafx2[offs_y+x_pos]);
Print_in_window(130-4*26,88,"Copyright (c) 2007-2011 by",MC_Dark,MC_Light);
Print_in_window(130-4*23,96,"the Grafx2 project team",MC_Black,MC_Light);
Print_in_window(130-4*26,112,"Copyright (c) 1996-2001 by",MC_Dark,MC_Light);
Print_in_window(130-4*13,120,"Sunset Design",MC_Black,MC_Light);
//Print_in_window( 120-4*13,128,"(placeholder)",MC_Dark,MC_Light);
Print_in_window(130-4*28,136,"http://grafx2.googlecode.com",MC_Dark,MC_Light);
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
while(!Mouse_K && !Key)
Get_input(20);
if (Mouse_K)
Wait_end_of_click();
Close_window();
Display_cursor();
}
void Change_paintbrush_shape(byte shape)
{
Paintbrush_shape=shape;
Display_paintbrush_in_menu();
switch (Current_operation)
{
case OPERATION_FILL :
Paintbrush_shape_before_fill=shape;
Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
break;
case OPERATION_COLORPICK :
Paintbrush_shape_before_colorpicker=shape;
Paintbrush_shape=PAINTBRUSH_SHAPE_NONE;
break;
// Note: Il existe un Paintbrush_shape_before_lasso, mais comme le lasso aura
// t automatiquement dsactiv avant d'arriver ici, y'a pas de problme.
}
}
//-------------------------------- UNDO/REDO ---------------------------------
void Button_Undo(void)
{
Hide_cursor();
Undo();
Set_palette(Main_palette);
Compute_optimal_menu_colors(Main_palette);
Display_all_screen();
Unselect_button(BUTTON_UNDO);
Draw_menu_button(BUTTON_MAGNIFIER,Main_magnifier_mode);
Display_menu();
Display_cursor();
}
void Button_Redo(void)
{
Hide_cursor();
Redo();
Set_palette(Main_palette);
Compute_optimal_menu_colors(Main_palette);
Display_all_screen();
Unselect_button(BUTTON_UNDO);
Draw_menu_button(BUTTON_MAGNIFIER,Main_magnifier_mode);
Display_menu();
Display_cursor();
}
//---------------------------- SCROLL PALETTE LEFT ---------------------------
void Button_Pal_left(void)
{
short cells;
cells = (Config.Palette_vertical)?Palette_cells_X():Palette_cells_Y();
Hide_cursor();
if (First_color_in_palette)
{
if (First_color_in_palette>=cells)
First_color_in_palette-=cells;
else
First_color_in_palette=0;
Display_menu_palette();
}
Unselect_button(BUTTON_PAL_LEFT);
Display_cursor();
}
void Button_Pal_left_fast(void)
{
short cells_x = Palette_cells_X();
short cells_y = Palette_cells_Y();
Hide_cursor();
if (First_color_in_palette)
{
if (First_color_in_palette>=cells_y*cells_x)
First_color_in_palette-=cells_y*cells_x;
else
First_color_in_palette=0;
Display_menu_palette();
}
Unselect_button(BUTTON_PAL_LEFT);
Display_cursor();
}
//--------------------------- SCROLL PALETTE RIGHT ---------------------------
void Button_Pal_right(void)
{
short cells;
cells = (Config.Palette_vertical)?Palette_cells_X():Palette_cells_Y();
Hide_cursor();
if ((int)First_color_in_palette+Palette_cells_X()*Palette_cells_Y()<256)
{
First_color_in_palette+=cells;
Display_menu_palette();
}
Unselect_button(BUTTON_PAL_RIGHT);
Display_cursor();
}
void Button_Pal_right_fast(void)
{
short cells_x = Palette_cells_X();
short cells_y = Palette_cells_Y();
Hide_cursor();
if ((int)First_color_in_palette+cells_y*cells_x<256)
{
if ((int)First_color_in_palette+(cells_y)*cells_x*2<256)
First_color_in_palette+=cells_x*cells_y;
else
First_color_in_palette=255/cells_y*cells_y-(cells_x-1)*cells_y;
Display_menu_palette();
}
Unselect_button(BUTTON_PAL_RIGHT);
Display_cursor();
}
//-------------------- item de la forecolor dans le menu --------------------
void Button_Select_forecolor(void)
{
static long time_click = 0;
long time_previous;
int color;
time_previous = time_click;
time_click = SDL_GetTicks();
color=Pick_color_in_palette();
if (color == Fore_color)
{
// Check if it's a double-click
if (time_click - time_previous < Config.Double_click_speed)
{
// Open palette window
Button_Palette();
return;
}
}
do
{
if (color != Fore_color && color!=-1)
{
Hide_cursor();
Set_fore_color(color);
Display_cursor();
}
// Wait loop after initial click
while(Mouse_K)
{
Get_input(20);
if (Button_under_mouse()==BUTTON_CHOOSE_COL)
{
color=Pick_color_in_palette();
if (color != Fore_color && color!=-1)
{
Hide_cursor();
Status_print_palette_color(color);
Set_fore_color(color);
Display_cursor();
}
}
}
} while(Mouse_K);
}
//-------------------- item de la backcolor dans le menu --------------------
void Button_Select_backcolor(void)
{
int color;
do
{
color=Pick_color_in_palette();
if (color!=-1 && color != Back_color)
{
Hide_cursor();
Status_print_palette_color(color);
Set_back_color(color);
Display_cursor();
}
// Wait loop after initial click
do
{
Get_input(20);
if (Button_under_mouse()==BUTTON_CHOOSE_COL)
break; // This will repeat this button's action
} while(Mouse_K);
} while(Mouse_K);
}
void Button_Hide_menu(void)
{
Hide_cursor();
if (Menu_is_visible)
{
Menu_is_visible=0;
Menu_Y=Screen_height;
if (Main_magnifier_mode)
{
Compute_magnifier_data();
}
// On repositionne le dcalage de l'image pour qu'il n'y ait pas d'in-
// -cohrences lorsqu'on sortira du mode Loupe.
if (Main_offset_Y+Screen_height>Main_image_height)
{
if (Screen_height>Main_image_height)
Main_offset_Y=0;
else
Main_offset_Y=Main_image_height-Screen_height;
}
// On fait pareil pour le brouillon
if (Spare_offset_Y+Screen_height>Spare_image_height)
{
if (Screen_height>Spare_image_height)
Spare_offset_Y=0;
else
Spare_offset_Y=Spare_image_height-Screen_height;
}
Compute_magnifier_data();
if (Main_magnifier_mode)
Position_screen_according_to_zoom();
Compute_limits();
Compute_paintbrush_coordinates();
Display_all_screen();
}
else
{
byte current_menu;
Menu_is_visible=1;
Menu_Y=Screen_height;
for (current_menu = 0; current_menu < MENUBAR_COUNT; current_menu++)
if (Menu_bars[current_menu].Visible)
Menu_Y -= Menu_bars[current_menu].Height * Menu_factor_Y;
Compute_magnifier_data();
if (Main_magnifier_mode)
Position_screen_according_to_zoom();
Compute_limits();
Compute_paintbrush_coordinates();
Display_menu();
if (Main_magnifier_mode)
Display_all_screen();
}
Unselect_button(BUTTON_HIDE);
Display_cursor();
}
void Set_bar_visibility(word bar, byte visible)
{
if (!visible && Menu_bars[bar].Visible)
{
// Hide it
Menu_bars[bar].Visible=0;
Compute_menu_offsets();
if (Main_magnifier_mode)
{
Compute_magnifier_data();
}
// On repositionne le dcalage de l'image pour qu'il n'y ait pas d'in-
// -cohrences lorsqu'on sortira du mode Loupe.
if (Main_offset_Y+Screen_height>Main_image_height)
{
if (Screen_height>Main_image_height)
Main_offset_Y=0;
else
Main_offset_Y=Main_image_height-Screen_height;
}
// On fait pareil pour le brouillon
if (Spare_offset_Y+Screen_height>Spare_image_height)
{
if (Screen_height>Spare_image_height)
Spare_offset_Y=0;
else
Spare_offset_Y=Spare_image_height-Screen_height;
}
Compute_magnifier_data();
if (Main_magnifier_mode)
Position_screen_according_to_zoom();
Compute_limits();
Compute_paintbrush_coordinates();
Display_menu();
Display_all_screen();
}
else if (visible && !Menu_bars[bar].Visible)
{
// Show it
Menu_bars[bar].Visible = 1;
Compute_menu_offsets();
Compute_magnifier_data();
if (Main_magnifier_mode)
Position_screen_according_to_zoom();
Compute_limits();
Compute_paintbrush_coordinates();
Display_menu();
if (Main_magnifier_mode)
Display_all_screen();
}
}
void Button_Toggle_toolbar(void)
{
T_Dropdown_button dropdown;
T_Dropdown_choice *item;
static char menu_name[2][9]= {
" Tools",
" Layers"
};
menu_name[0][0] = Menu_bars[MENUBAR_TOOLS ].Visible ? 22 : ' ';
menu_name[1][0] = Menu_bars[MENUBAR_LAYERS].Visible ? 22 : ' ';
Hide_cursor();
dropdown.Pos_X =Buttons_Pool[BUTTON_HIDE].X_offset;
dropdown.Pos_Y =Buttons_Pool[BUTTON_HIDE].Y_offset;
dropdown.Height =Buttons_Pool[BUTTON_HIDE].Height;
dropdown.Dropdown_width=70;
dropdown.First_item =NULL;
dropdown.Bottom_up =1;
Window_dropdown_add_item(&dropdown, 0, menu_name[0]);
Window_dropdown_add_item(&dropdown, 1, menu_name[1]);
item=Dropdown_activate(&dropdown,0,Menu_Y+Menu_bars[MENUBAR_STATUS].Top*Menu_factor_Y);
if (item)
{
switch (item->Number)
{
case 0:
Set_bar_visibility(MENUBAR_TOOLS, !Menu_bars[MENUBAR_TOOLS].Visible);
break;
case 1:
Set_bar_visibility(MENUBAR_LAYERS, !Menu_bars[MENUBAR_LAYERS].Visible);
break;
}
}
// Closing
Window_dropdown_clear_items(&dropdown);
Unselect_button(BUTTON_HIDE);
Display_cursor();
}
void Button_Toggle_all_toolbars(void)
{
// This is used to memorize the bars' visibility when temporarily hidden
static word Last_visibility = 0xFFFF;
int i;
word current_visibility;
Hide_cursor();
// Check which bars are visible
current_visibility=0;
for (i=MENUBAR_STATUS+1;iPages->Filename, Main_backups->Pages->File_directory);
if ( (!File_exists(filename)) || Confirmation_box("Erase old file ?") )
{
T_IO_Context save_context;
Hide_cursor();
old_cursor_shape=Cursor_shape;
Cursor_shape=CURSOR_SHAPE_HOURGLASS;
Display_cursor();
Init_context_layered_image(&save_context, Main_backups->Pages->Filename, Main_backups->Pages->File_directory);
Save_image(&save_context);
Destroy_context(&save_context);
Hide_cursor();
Cursor_shape=old_cursor_shape;
Display_cursor();
if (!File_error)
// L'ayant sauve avec succs,
return 1; // On peut quitter
else
// Il y a eu une erreur lors de la sauvegarde,
return 0; // On ne peut donc pas quitter
}
else
// L'utilisateur ne veut pas craser l'ancien fichier,
return 0; // On doit donc rester
case 3 : return 1; // Quitter
}
return 0;
}
void Button_Quit(void)
{
//short clicked_button;
if (Button_Quit_local_function())
{
if (Spare_image_is_modified)
{
Button_Page(); // On passe sur le brouillon
// Si l'utilisateur prsente les derniers symptomes de l'abandon
if (Button_Quit_local_function())
Quitting=1;
}
else
Quitting=1;
}
if ( (Menu_is_visible) && (Mouse_Y+8>Menu_Y) )
Hide_cursor();
Unselect_button(BUTTON_QUIT);
if ( (Menu_is_visible) && (Mouse_Y+8>Menu_Y) )
Display_cursor();
}
//---------------------------- Effacer l'cran -------------------------------
void Button_Clear(void)
{
Hide_cursor();
Backup();
if (Stencil_mode && Config.Clear_with_stencil)
Clear_current_image_with_stencil(Main_backups->Pages->Transparent_color,Stencil);
else
Clear_current_image(Main_backups->Pages->Transparent_color);
Redraw_layered_image();
End_of_modification();
Display_all_screen();
Unselect_button(BUTTON_CLEAR);
Display_cursor();
}
void Button_Clear_with_backcolor(void)
{
Hide_cursor();
Backup();
if (Stencil_mode && Config.Clear_with_stencil)
Clear_current_image_with_stencil(Back_color,Stencil);
else
Clear_current_image(Back_color);
Redraw_layered_image();
End_of_modification();
Display_all_screen();
Unselect_button(BUTTON_CLEAR);
Display_cursor();
}
//------------------------------- Paramtres ---------------------------------
#define SETTING_PER_PAGE 11
#define SETTING_PAGES 5
#define SETTING_HEIGHT 12
typedef struct {
const char* Label; // Use NULL label to stop an array
int Code;
} T_Lookup;
const T_Lookup Lookup_YesNo[] = {
{"NO",0},
{"YES",1},
{NULL,-1},
};
const T_Lookup Lookup_FFF[] = {
{"All",0},
{"Files",1},
{"Dirs.",2},
{NULL,-1},
};
const T_Lookup Lookup_AutoRes[] = {
{"Internal",1},
{"Real",2},
{NULL,-1},
};
const T_Lookup Lookup_Coords[] = {
{"Relative",1},
{"Absolute",2},
{NULL,-1},
};
const T_Lookup Lookup_MenuRatio[] = {
{"None",0},
{"x2",254}, // -2
{"x3",253}, // -3
{"x4",252}, // -4
{"Moderate",2},
{"Maximum",1},
{NULL,-1},
};
const T_Lookup Lookup_MouseSpeed[] = {
{"Normal",1},
{"/2",2},
{"/3",3},
{"/4",4},
{NULL,-1},
};
const T_Lookup Lookup_SwapButtons[] = {
{"None",0},
{"Control",MOD_CTRL},
{"Alt",MOD_ALT},
{NULL,-1},
};
typedef struct {
const char* Label;
byte Type; // 0: label, 1+: setting (size in bytes)
void * Value;
int Min_value;
int Max_value;
int Digits; // Could be computed from Max_value...but don't bother.
const T_Lookup * Lookup;
} T_Setting;
long int Get_setting_value(T_Setting *item)
{
switch(item->Type)
{
case 1:
return *((byte *)(item->Value));
break;
case 2:
return *((word *)(item->Value));
break;
case 4:
default:
return *((long int *)(item->Value));
break;
}
}
void Set_setting_value(T_Setting *item, long int value)
{
switch(item->Type)
{
case 1:
*((byte *)(item->Value)) = value;
break;
case 2:
*((word *)(item->Value)) = value;
break;
case 4:
default:
*((long int *)(item->Value)) = value;
break;
}
}
// Fetch a label in a lookup table. Unknown values get label 0.
const char *Lookup_code(int code, const T_Lookup *lookup)
{
int i;
for(i=0; lookup[i].Label!=NULL; i++)
{
if (lookup[i].Code == code)
return lookup[i].Label;
}
return lookup[0].Label;
}
/// Increase an enum to next-higher value (wrapping).
int Lookup_next(int code, const T_Lookup *lookup)
{
int i;
for(i=0; lookup[i].Label!=NULL; i++)
{
if (lookup[i].Code == code)
{
if (lookup[i+1].Label==NULL)
return lookup[0].Code;
return lookup[i+1].Code;
}
}
return 0;
}
/// Decrease an enum to previous value (wrapping).
int Lookup_previous(int code, const T_Lookup *lookup)
{
int count;
int current=-1;
for(count=0; lookup[count].Label!=NULL; count++)
{
if (lookup[count].Code == code)
current=count;
}
return lookup[(current + count - 1) % count].Code;
}
void Settings_display_config(T_Setting *setting, T_Config * conf, T_Special_button *panel)
{
int i;
// A single button
Print_in_window(155,166,(conf->Auto_save)?"YES":" NO",MC_Black,MC_Light);
// Clear all
Window_rectangle(panel->Pos_X, panel->Pos_Y, panel->Width, panel->Height+1, MC_Light);
for (i=0; iPos_X+3, panel->Pos_Y+i*SETTING_HEIGHT+(SETTING_HEIGHT-6)/2, setting[i].Label, i==0?MC_White:MC_Dark, MC_Light);
if(setting[i].Value)
{
int value = Get_setting_value(&setting[i]);
if (setting[i].Lookup)
{
// Use a lookup table to print a label
const char *str;
str = Lookup_code(value,setting[i].Lookup);
Print_in_window(panel->Pos_X+3+176, panel->Pos_Y+i*SETTING_HEIGHT+(SETTING_HEIGHT-6)/2, str, MC_Black, MC_Light);
}
else
{
// Print a number
char str[10];
Num2str(value,str,setting[i].Digits);
Print_in_window(panel->Pos_X+3+176, panel->Pos_Y+i*SETTING_HEIGHT+(SETTING_HEIGHT-6)/2, str, MC_Black, MC_Light);
}
}
}
Update_window_area(panel->Pos_X, panel->Pos_Y, panel->Width, panel->Height+1);
}
void Settings_save_config(T_Config * conf)
{
if (Save_CFG())
Error(0);
else
if (Save_INI(conf))
Error(0);
}
void Settings_load_config(T_Config * conf)
{
if (Load_CFG(0))
Error(0);
else
if (Load_INI(conf))
Error(0);
}
void Button_Settings(void)
{
short clicked_button;
T_Config selected_config;
byte config_is_reloaded=0;
T_Special_button *panel;
byte need_redraw=1;
static byte current_page=0;
// Definition of settings pages
// Label,Type (0 = label, 1+ = setting size in bytes),
// Value, min, max, digits, Lookup)
T_Setting setting[SETTING_PER_PAGE*SETTING_PAGES] = {
{" --- GUI ---",0,NULL,0,0,0,NULL},
{"Opening message:",1,&(selected_config.Opening_message),0,1,0,Lookup_YesNo},
{"Menu ratio adapt:",1,&(selected_config.Ratio),0,1,0,Lookup_MenuRatio},
{"Draw limits:",1,&(selected_config.Display_image_limits),0,1,0,Lookup_YesNo},
{"Coordinates:",1,&(selected_config.Coords_rel),0,1,0,Lookup_Coords},
{"Separate colors:",1,&(selected_config.Separate_colors),0,1,0,Lookup_YesNo},
{"Safety colors:",1,&(selected_config.Safety_colors),0,1,0,Lookup_YesNo},
{"Grid XOR color:",1,&(selected_config.Grid_XOR_color),0,255,3,NULL},
{"Sync views:",1,&(selected_config.Sync_views),0,1,0,Lookup_YesNo},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{" --- Input ---",0,NULL,0,0,0,NULL},
{"Scrollbar speed",0,NULL,0,0,0,NULL},
{" on left click:",1,&(selected_config.Delay_left_click_on_slider),1,255,4,NULL},
{" on right click:",1,&(selected_config.Delay_right_click_on_slider),1,255,4,NULL},
{"Merge movement:",1,&(selected_config.Mouse_merge_movement),0,100,4,NULL},
{"Double click speed:",2,&(selected_config.Double_click_speed),1,1999,4,NULL},
{"Double key speed:",2,&(selected_config.Double_key_speed),1,1999,4,NULL},
//{"Mouse speed (fullscreen)",0,NULL,0,0,0,NULL},
//{" horizontally:",1,&(selected_config.Mouse_sensitivity_index_x),1,4,0,Lookup_MouseSpeed},
//{" vertically:",1,&(selected_config.Mouse_sensitivity_index_y),1,4,0,Lookup_MouseSpeed},
{"Key to swap buttons:",2,&(selected_config.Swap_buttons),0,0,0,Lookup_SwapButtons},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{" --- Editing ---",0,NULL,0,0,0,NULL},
{"Adjust brush pick:",1,&(selected_config.Adjust_brush_pick),0,1,0,Lookup_YesNo},
{"Undo pages:",1,&(selected_config.Max_undo_pages),1,99,5,NULL},
{"Vertices per polygon:",4,&(selected_config.Nb_max_vertices_per_polygon),2,16384,5,NULL},
{"Fast zoom:",1,&(selected_config.Fast_zoom),0,1,0,Lookup_YesNo},
{"Clear with stencil:",1,&(selected_config.Clear_with_stencil),0,1,0,Lookup_YesNo},
{"Auto discontinuous:",1,&(selected_config.Auto_discontinuous),0,1,0,Lookup_YesNo},
{"Auto count colors:",1,&(selected_config.Auto_nb_used),0,1,0,Lookup_YesNo},
{"Right click colorpick:",1,&(selected_config.Right_click_colorpick),0,1,0,Lookup_YesNo},
{"Multi shortcuts:",1,&(selected_config.Allow_multi_shortcuts),0,1,0,Lookup_YesNo},
{"",0,NULL,0,0,0,NULL},
{" --- File selector ---",0,NULL,0,0,0,NULL},
{"Show in fileselector",0,NULL,0,0,0,NULL},
{" Hidden files:",4,&(selected_config.Show_hidden_files),0,1,0,Lookup_YesNo},
{" Hidden dirs:",4,&(selected_config.Show_hidden_directories),0,1,0,Lookup_YesNo},
{"Preview delay:",4,&(selected_config.Timer_delay), 1,256,3,NULL},
{"Maximize preview:",1,&(selected_config.Maximize_preview), 0,1,0,Lookup_YesNo},
{"Find file fast:",1,&(selected_config.Find_file_fast), 0,2,0,Lookup_FFF},
{"Auto set resolution:",1,&(selected_config.Auto_set_res), 0,1,0,Lookup_YesNo},
{" According to:",1,&(selected_config.Set_resolution_according_to), 1,2,0,Lookup_AutoRes},
{"Backup:",1,&(selected_config.Backup), 0,1,0,Lookup_YesNo},
{"",0,NULL,0,0,0,NULL},
{" --- Format options ---",0,NULL,0,0,0,NULL},
{"Screen size in GIF:",1,&(selected_config.Screen_size_in_GIF),0,1,0,Lookup_YesNo},
{"Clear palette:",1,&(selected_config.Clear_palette),0,1,0,Lookup_YesNo},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
};
const char * help_section[SETTING_PAGES] = {
"GUI",
"INPUT",
"EDITING",
"FILE SELECTOR",
"FILE FORMAT OPTIONS",
};
selected_config=Config;
Open_window(307,182,"Settings");
// Button Reload
Window_set_normal_button( 6,163, 51,14,"Reload" ,0,1,SDLK_LAST); // 1
// Button Auto-save
Window_set_normal_button( 73,163,107,14,"Auto-save: ",0,1,SDLK_LAST); // 2
// Button Save
Window_set_normal_button(183,163, 51,14,"Save" ,0,1,SDLK_LAST); // 3
// Button Close
Window_set_normal_button(250,163, 51,14,"Close" ,0,1,KEY_ESC); // 4
panel=Window_set_special_button(10, 21, 272,SETTING_PER_PAGE*SETTING_HEIGHT); // 5
Window_set_scroller_button(285,21,SETTING_PER_PAGE*SETTING_HEIGHT,SETTING_PAGES,1,current_page); // 6
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
if (need_redraw)
{
Hide_cursor();
Settings_display_config(setting+current_page*SETTING_PER_PAGE, &selected_config, panel);
if (need_redraw & 2)
{
// Including slider position
Window_scroller_button_list->Position=current_page;
Window_draw_slider(Window_scroller_button_list);
}
Display_cursor();
need_redraw=0;
}
clicked_button=Window_clicked_button();
switch(clicked_button)
{
case 1 : // Reload
Settings_load_config(&selected_config);
config_is_reloaded=1;
need_redraw=1;
break;
case 2 : // Auto-save
selected_config.Auto_save=!selected_config.Auto_save;
need_redraw=1;
break;
case 3 : // Save
Settings_save_config(&selected_config);
break;
// case 4: // Close
case 5: // Panel area
{
T_Setting item;
int num=(((short)Mouse_Y-Window_pos_Y)/Menu_factor_Y - panel->Pos_Y)/SETTING_HEIGHT;
if (num >= 0 && num < SETTING_PER_PAGE)
{
item=setting[current_page*SETTING_PER_PAGE+num];
if (item.Type!=0)
{
// Remember which button is clicked
byte old_mouse_k = Mouse_K;
if (Window_normal_button_onclick(panel->Pos_X, panel->Pos_Y+num*SETTING_HEIGHT, panel->Width, SETTING_HEIGHT+1, 5))
{
int value = Get_setting_value(&item);
if (item.Lookup)
{
// Enum: toggle it
if (old_mouse_k & LEFT_SIDE)
value = Lookup_next(value, item.Lookup);
else
value = Lookup_previous(value, item.Lookup);
Set_setting_value(&item, value);
}
else
{
// Numeric: edit it
char str[10];
str[0]='\0';
if (! (old_mouse_k & RIGHT_SIDE))
Num2str(value,str,item.Digits+1);
if (Readline(panel->Pos_X+3+176, panel->Pos_Y+num*SETTING_HEIGHT+(SETTING_HEIGHT-6)/2,str,item.Digits+1,INPUT_TYPE_INTEGER))
{
value=atoi(str);
if (valueitem.Max_value)
value = item.Max_value;
Set_setting_value(&item, value);
}
Key=0; // Need to discard keys used during editing
}
}
}
}
}
need_redraw=1;
break;
case 6: // Scroller
current_page = Window_attribute2;
need_redraw=1;
break;
}
if (Key == KEY_MOUSEWHEELDOWN)
{
if (current_page < (SETTING_PAGES-1))
{
current_page++;
need_redraw=2;
}
}
else if (Key == KEY_MOUSEWHEELUP)
{
if (current_page > 0)
{
current_page--;
need_redraw=2;
}
}
else if (Is_shortcut(Key,0x100+BUTTON_HELP))
Window_help(NB_BUTTONS+0, help_section[current_page]);
else if (Is_shortcut(Key,0x100+BUTTON_SETTINGS))
clicked_button=4;
}
while ( (clicked_button!=4) && (Key!=SDLK_RETURN) );
// Checks on change
if (Config.Show_hidden_directories!=selected_config.Show_hidden_directories
||Config.Show_hidden_files!=selected_config.Show_hidden_files)
{
// Reset fileselector offsets
// since different files are shown now
Main_fileselector_position=0;
Main_fileselector_offset=0;
Spare_fileselector_position=0;
Spare_fileselector_offset=0;
}
if(Config.Allow_multi_shortcuts && !selected_config.Allow_multi_shortcuts)
{
// User just disabled multi shortcuts: make them unique now.
Remove_duplicate_shortcuts();
}
// Copy all
Config=selected_config;
if (config_is_reloaded)
Compute_optimal_menu_colors(Main_palette);
Close_window();
Unselect_button(BUTTON_SETTINGS);
// Raffichage du menu pour que les inscriptions qui y figurent soient
// retraces avec la nouvelle fonte
Display_menu();
Display_cursor();
// On vrifie qu'on peut bien allouer le nombre de pages Undo.
Set_number_of_backups(Config.Max_undo_pages);
}
// Data for skin selector
T_Fileselector Skin_files_list;
// Data for font selector
T_Fileselector Font_files_list;
//
char * Format_font_filename(const char * fname)
{
static char result[12];
int c;
int length;
fname+=strlen(FONT_PREFIX); // Omit file prefix
length=strlen(fname) - 4; // assume .png extension
for (c=0;c<11 && c11)
result[10] = ELLIPSIS_CHARACTER;
return result;
}
// Add a skin to the list
void Add_font_or_skin(const char *name)
{
const char * fname;
int namelength;
// Cut the long name to keep only filename (no directory)
fname = Find_last_slash(name);
if (fname)
fname++;
else
fname = name;
namelength = strlen(fname);
if (namelength>=10 && fname[0]!='_' && !strncasecmp(fname, SKIN_PREFIX, strlen(SKIN_PREFIX))
&& (!strcasecmp(fname + namelength - 4,".png")
|| !strcasecmp(fname + namelength - 4,".gif")))
{
Add_element_to_list(&Skin_files_list, fname, Format_filename(fname, 19, 0), 0, ICON_NONE);
if (fname[0]=='\0')
return;
}
else if (namelength>=10 && !strncasecmp(fname, FONT_PREFIX, strlen(FONT_PREFIX))
&& (!strcasecmp(fname + namelength - 4, ".png")))
{
Add_element_to_list(&Font_files_list, fname, Format_font_filename(fname), 0, ICON_NONE);
if (fname[0]=='\0')
return;
}
}
// Callback to display a skin name in the list
void Draw_one_skin_name(word x, word y, word index, byte highlighted)
{
T_Fileselector_item * current_item;
if (Skin_files_list.Nb_elements)
{
current_item = Get_item_by_index(&Skin_files_list, index);
Print_in_window(x, y, current_item->Short_name, MC_Black,
(highlighted)?MC_Dark:MC_Light);
}
}
/// Skin selector window
void Button_Skins(void)
{
short clicked_button;
short temp;
char skinsdir[MAX_PATH_CHARACTERS];
T_Dropdown_button * font_dropdown;
T_Dropdown_button * cursor_dropdown;
T_List_button * skin_list;
T_Scroller_button * file_scroller;
int selected_font = 0;
int selected_cursor = Config.Cursor;
byte separatecolors = Config.Separate_colors;
byte showlimits = Config.Display_image_limits;
byte need_load=1;
int button;
word x, y, x_pos, offs_y;
char * cursors[] = { "Solid", "Transparent", "Thin" };
T_Gui_skin * gfx = NULL;
#define FILESEL_Y 34
// --- Read the contents of skins/ directory ------------------
// Here we use the same data container as the fileselectors.
// Reinitialize the list
Free_fileselector_list(&Skin_files_list);
Free_fileselector_list(&Font_files_list);
// Browse the "skins" directory
strcpy(skinsdir, Data_directory);
strcat(skinsdir, SKINS_SUBDIRECTORY);
// Add each found file to the list
For_each_file(skinsdir, Add_font_or_skin);
// Sort it
Sort_list_of_files(&Skin_files_list);
Sort_list_of_files(&Font_files_list);
selected_font = Find_file_in_fileselector(&Font_files_list, Config.Font_file);
// --------------------------------------------------------------
Open_window(290, 140, "Skins");
// Frames
Window_display_frame_in(6, FILESEL_Y - 2, 148, 84); // File selector
// Texts
Print_in_window( 172, 33,"Font:" ,MC_Black,MC_Light);
Print_in_window( 172, 59,"Cursor:" ,MC_Black,MC_Light);
// Ok button
Window_set_normal_button(6, 120, 51, 14, "OK", 0, 1, SDLK_RETURN); // 1
// List of skins
skin_list = Window_set_list_button(
// Fileselector
Window_set_special_button(8, FILESEL_Y + 1, 144, 80), // 2
// Scroller for the fileselector
(file_scroller = Window_set_scroller_button(155, FILESEL_Y - 1, 82,
Skin_files_list.Nb_elements, 10, 0)), // 3
Draw_one_skin_name, 2); // 4
skin_list->Cursor_position = Find_file_in_fileselector(&Skin_files_list, Config.Skin_file);
// Buttons to choose a font
font_dropdown = Window_set_dropdown_button(172, 43, 104, 11, 0, Get_item_by_index(&Font_files_list,selected_font)->Short_name,1,0,1,RIGHT_SIDE|LEFT_SIDE,0); // 5
for (temp=0; tempShort_name);
// Cancel
Window_set_normal_button(61, 120, 51,14,"Cancel",0,1,SDLK_ESCAPE); // 6
// Dropdown list to choose cursor type
cursor_dropdown = Window_set_dropdown_button(172, 69, 104, 11, 0,
cursors[selected_cursor], 1, 0, 1, RIGHT_SIDE|LEFT_SIDE,0); // 7
for (temp = 0; temp<3; temp++)
Window_dropdown_add_item(cursor_dropdown, temp, cursors[temp]);
Window_set_normal_button(172, 87, 14, 14,
(Config.Display_image_limits)?"X":" ", -1, 1, SDLK_LAST); // 8
Print_in_window( 190, 85,"Draw picture", MC_Dark, MC_Light);
Print_in_window( 190, 94,"limits", MC_Dark, MC_Light);
Window_set_normal_button(172, 111, 14, 14,
(Config.Separate_colors)?"X":" ", -1, 1, SDLK_LAST); // 9
Print_in_window( 190, 109,"Separate", MC_Dark, MC_Light);
Print_in_window( 190, 118,"colors", MC_Dark, MC_Light);
Window_redraw_list(skin_list);
for (y = 14, offs_y = 0; offs_y < 16; offs_y++, y++)
for (x = 6, x_pos = 0; x_pos<173; x_pos++, x++)
Pixel_in_window(x, y, Gfx->Preview[offs_y][x_pos]);
Update_window_area(0, 0, Window_width, Window_height);
Display_cursor();
do
{
if (need_load)
{
need_load=0;
Hide_cursor();
// (Re-)load GUI graphics from selected skins
strcpy(skinsdir, Get_item_by_index(&Skin_files_list,
skin_list->List_start + skin_list->Cursor_position)->Full_name);
gfx = Load_graphics(skinsdir, NULL);
if (gfx == NULL) // Error
{
Display_cursor();
Verbose_message("Error!", Gui_loading_error_message);
Hide_cursor();
// Update preview
Window_rectangle(6, 14, 173, 16, MC_Light);
}
else
{
// Update preview
// Display the bitmap according to its own color indices
for (y = 14, offs_y = 0; offs_y < 16; offs_y++, y++)
for (x = 6, x_pos = 0; x_pos<173; x_pos++, x++)
{
if (gfx->Preview[offs_y][x_pos] == gfx->Color[0])
Pixel_in_window(x, y, MC_Black);
else if (gfx->Preview[offs_y][x_pos] == gfx->Color[1])
Pixel_in_window(x, y, MC_Dark);
else if (gfx->Preview[offs_y][x_pos] == gfx->Color[3])
Pixel_in_window(x, y, MC_White);
else if (gfx->Preview[offs_y][x_pos] == gfx->Color[2])
Pixel_in_window(x, y, MC_Light);
}
// Actualize current screen according to preferred GUI colors
// Note this only updates onscreen colors
Set_color(
MC_Black,
gfx->Default_palette[gfx->Color[0]].R,
gfx->Default_palette[gfx->Color[0]].G,
gfx->Default_palette[gfx->Color[0]].B);
Set_color(
MC_Dark,
gfx->Default_palette[gfx->Color[1]].R,
gfx->Default_palette[gfx->Color[1]].G,
gfx->Default_palette[gfx->Color[1]].B);
Set_color(
MC_Light,
gfx->Default_palette[gfx->Color[2]].R,
gfx->Default_palette[gfx->Color[2]].G,
gfx->Default_palette[gfx->Color[2]].B);
Set_color(
MC_White,
gfx->Default_palette[gfx->Color[3]].R,
gfx->Default_palette[gfx->Color[3]].G,
gfx->Default_palette[gfx->Color[3]].B);
}
Update_window_area(6, 14, 173, 16);
Display_cursor();
}
clicked_button=Window_clicked_button();
if (Is_shortcut(Key,0x100+BUTTON_HELP))
Window_help(BUTTON_SETTINGS, "SKINS");
switch(clicked_button)
{
case 1 : // OK
break;
case 2 : // double-click file: do nothing
break;
case 3 : // doesn't happen
break;
case 4 : // a file is selected
need_load=1;
break;
case 5 : // Font dropdown
selected_font = Window_attribute2; // Get the index of the chosen font.
break;
// 6: Cancel
case 7 : // Cursor
selected_cursor = Window_attribute2;
break;
case 8: // Display limits
showlimits = !showlimits;
Hide_cursor();
Print_in_window(175, 90, (showlimits)?"X":" ", MC_Black, MC_Light);
Display_cursor();
break;
case 9: // Separate colors
separatecolors = !separatecolors;
Hide_cursor();
Print_in_window(175, 114, (separatecolors)?"X":" ", MC_Black, MC_Light);
Display_cursor();
break;
}
}
while ( (clicked_button!=1) && (clicked_button !=6) && (Key != SDLK_ESCAPE));
if(clicked_button == 1)
{
byte * new_font;
if (gfx != NULL)
{
Set_current_skin(skinsdir, gfx);
}
// (Re-)load the selected font
new_font = Load_font(Get_item_by_index(&Font_files_list,selected_font)->Full_name);
if (new_font)
{
const char * fname;
free(Menu_font);
Menu_font = new_font;
fname = Get_item_by_index(&Font_files_list,selected_font)->Full_name;
free(Config.Font_file);
Config.Font_file = (char *)strdup(fname);
}
// Confirm the change of cursor shape
Config.Cursor = selected_cursor;
Config.Display_image_limits = showlimits;
Config.Separate_colors = separatecolors;
// Now find the best colors for the new skin in the current palette
// and remap the skin
Compute_optimal_menu_colors(Main_palette);
}
// We don't want to keep the skin's palette, as this would corrupt the current picture's one.
Set_palette(Main_palette);
Close_window();
Unselect_button(BUTTON_SETTINGS);
// Raffichage du menu pour que les inscriptions qui y figurent soient retraces avec la nouvelle fonte
Display_menu();
// Redraw all buttons, to ensure all specific sprites are in place.
// This is necessary for multi-state buttons, for example Freehand.
for (button=0; buttonPages->Nb_layers; i++)
{
if (i == Spare_current_layer)
{
// Copy the current layer
memcpy(Spare_backups->Pages->Image[i],Main_backups->Pages->Image[Main_current_layer],Main_image_width*Main_image_height);
}
else
{
// Resize the original layer
Copy_part_of_image_to_another(
Spare_backups->Pages->Next->Image[i],0,0,Min(old_width,Spare_image_width),
Min(old_height,Spare_image_height),old_width,
Spare_backups->Pages->Image[i],0,0,Spare_image_width);
}
}
// Copie des dimensions de l'image
/*
C'est inutile, le "Backuper et redimensionner brouillon" a dj modifi
ces valeurs pour qu'elles soient correctes.
*/
/*
Spare_image_width=Main_image_width;
Spare_image_height=Main_image_height;
*/
Copy_view_to_spare();
// Update the visible buffer of the spare.
// It's a bit complex because at the moment, to save memory,
// the spare doesn't have a full visible_buffer + depth_buffer,
// so I can't use exactly the same technique as for Main page.
// (It's the same reason that the "Page" function gets complex,
// it needs to rebuild a depth buffer only, trusting the
// depth buffer that was already available in Spare_.)
Update_spare_buffers(Spare_image_width,Spare_image_height);
Redraw_spare_image();
}
else
Message_out_of_memory();
}
void Copy_some_colors(void)
{
short index;
byte confirmation=0;
static byte mask_color_to_copy[256]; // static to use less stack
memset(mask_color_to_copy,1,256);
Menu_tag_colors("Tag colors to copy",mask_color_to_copy,&confirmation,0, NULL, 0xFFFF);
if (confirmation)
{
// Make a backup with the same pixel data as previous history steps
Backup_the_spare(0);
for (index=0; index<256; index++)
{
if (mask_color_to_copy[index])
memcpy(Spare_palette+index,Main_palette+index,
sizeof(T_Components));
}
}
}
void Button_Copy_page(void)
{
short clicked_button;
Open_window(168,137,"Copy to spare page");
Window_set_normal_button(10, 20,148,14,"Pixels + palette" , 0,1,SDLK_RETURN); // 1
Window_set_normal_button(10, 37,148,14,"Pixels only" , 3,1,SDLK_x); // 2
Window_set_normal_button(10, 54,148,14,"Palette only" , 1,1,SDLK_p); // 3
Window_set_normal_button(10, 71,148,14,"Some colors only" , 6,1,SDLK_c); // 4
Window_set_normal_button(10, 88,148,14,"Palette and remap",13,1,SDLK_r); // 5
Window_set_normal_button(44,114, 80,14,"Cancel" , 0,1,KEY_ESC); // 6
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
clicked_button=Window_clicked_button();
if (Is_shortcut(Key,0x100+BUTTON_HELP))
Window_help(BUTTON_PAGE, NULL);
else if (Is_shortcut(Key,0x200+BUTTON_PAGE))
clicked_button=6;
}
while (clicked_button<=0);
Close_window();
Display_cursor();
switch (clicked_button)
{
case 1: // Pixels+palette
Backup_the_spare(-1);
Copy_image_only();
// copie de la palette
memcpy(Spare_palette,Main_palette,sizeof(T_Palette));
// Equivalent of 'end_of_modifications' for spare.
Update_spare_buffers(Spare_image_width,Spare_image_height);
Redraw_spare_image();
Spare_image_is_modified=1;
break;
case 2: // Pixels only
Backup_the_spare(-1);
Copy_image_only();
// Equivalent of 'end_of_modifications' for spare.
Update_spare_buffers(Spare_image_width,Spare_image_height);
Redraw_spare_image();
Spare_image_is_modified=1;
break;
case 3: // Palette only
Backup_the_spare(0);
// Copy palette
memcpy(Spare_palette,Main_palette,sizeof(T_Palette));
// Equivalent of 'end_of_modifications' for spare.
Update_spare_buffers(Spare_image_width,Spare_image_height);
Redraw_spare_image();
Spare_image_is_modified=1;
break;
case 4: // Some colors
// Will backup if needed
Copy_some_colors();
break;
case 5: // Palette and remap
Backup_the_spare(-1);
Remap_spare();
// Copy palette
memcpy(Spare_palette,Main_palette,sizeof(T_Palette));
// Equivalent of 'end_of_modifications' for spare.
Update_spare_buffers(Spare_image_width,Spare_image_height);
Redraw_spare_image();
Spare_image_is_modified=1;
break;
}
Hide_cursor();
Unselect_button(BUTTON_PAGE);
Display_cursor();
}
// -- Suppression d'une page -------------------------------------------------
void Button_Kill(void)
{
if ( (Main_backups->List_size==1)
|| (!Confirmation_box("Delete the current page?")) )
{
if (Main_backups->List_size==1)
Warning_message("You can't delete the last page.");
Hide_cursor();
Unselect_button(BUTTON_KILL);
Display_cursor();
}
else
{
Hide_cursor();
Free_current_page();
Set_palette(Main_palette);
Compute_optimal_menu_colors(Main_palette);
Display_all_screen();
Unselect_button(BUTTON_KILL);
Draw_menu_button(BUTTON_MAGNIFIER,Main_magnifier_mode);
Display_menu();
Display_cursor();
}
}
//------------------------- Dimensions Image/Screen ---------------------------
void Check_mode_button(short x_pos, short y_pos, byte state)
{
byte color;
switch (state & 0x7F)
{
case 0 : color=MC_White; break;
case 1 : color=MC_Light; break;
case 2 : color=MC_Dark; break;
default: color=MC_Black;
}
Block(Window_pos_X+Menu_factor_X*x_pos,Window_pos_Y+Menu_factor_Y*y_pos,
Menu_factor_X*9,Menu_factor_Y*3,color);
Update_rect(Window_pos_X+Menu_factor_X*x_pos,Window_pos_Y+Menu_factor_Y*y_pos,
Menu_factor_X*9,Menu_factor_Y*3);
}
/// Number of video modes to display in the resolution menu
#define MODELIST_LINES 10
void Display_modes_list(short list_start, short cursor_position)
{
short index,current_mode;
short y_pos;
byte text_color,background_color;
char str[29];
char *ratio;
for (current_mode=list_start,index=0; indexPosition!=list_start)
{
Window_scroller_button_list->Position=list_start;
Window_draw_slider(Window_scroller_button_list);
}
Display_modes_list(list_start,cursor_position);
Display_cursor();
}
void Button_Resolution(void)
{
short clicked_button;
int selected_mode;
word chosen_width;
word chosen_height;
byte chosen_pixel;
short list_start;
short cursor_position;
short temp;
char str[5];
T_Special_button * input_width_button, * input_button_height;
T_Dropdown_button * pixel_button;
static const char *pixel_ratio_labels[PIXEL_MAX] ={
"Normal (1x1)",
"Wide (2x1)",
"Tall (1x2)",
"Double (2x2)",
"Triple (3x3)",
"Wide2 (4x2)",
"Tall2 (2x4)",
"Quadruple (4x4)"};
Open_window(299,190,"Picture & screen sizes");
Print_in_window( 12, 21,"Picture size:" ,MC_Dark,MC_Light);
Window_display_frame ( 8,17,195, 33);
Window_set_normal_button(223, 18,67,14,"OK" ,0,1,SDLK_RETURN); // 1
Window_set_normal_button(223, 35,67,14,"Cancel" ,0,1,KEY_ESC); // 2
Print_in_window( 12, 37,"Width:" ,MC_Dark,MC_Light);
input_width_button=Window_set_input_button( 60, 35,4); // 3
Print_in_window(108, 37,"Height:" ,MC_Dark,MC_Light);
input_button_height=Window_set_input_button(164, 35,4); // 4
Window_display_frame ( 8,72,283,110);
Window_display_frame_in (37,84,228,84);
Window_rectangle (38,85,226,82,MC_Black);
Print_in_window( 16, 76,"OK" ,MC_Dark,MC_Light);
Print_in_window( 55, 76,"X Y" ,MC_Dark,MC_Light);
Print_in_window(120, 76,"Win / Full" ,MC_Dark,MC_Light);
Print_in_window(219, 76,"Ratio" ,MC_Dark,MC_Light);
Print_in_window( 30,170,"\03" ,MC_Dark,MC_Light);
Print_in_window( 62,170,"OK" ,MC_Dark,MC_Light);
Print_in_window(102,170,"Imperfect" ,MC_Dark,MC_Light);
Print_in_window(196,170,"Unsupported" ,MC_Dark,MC_Light);
Window_set_special_button(38,86,225,80); // 5
selected_mode=Current_resolution;
if (selected_mode>=MODELIST_LINES/2 && Nb_video_modes > MODELIST_LINES)
{
if (selected_mode>3;
if (temp0)
cursor_position--;
else
if (list_start>0)
list_start--;
Scroll_list_of_modes(list_start,cursor_position,&selected_mode);
Key=0;
break;
case SDLK_DOWN : // Bas
if (cursor_position<(MODELIST_LINES-1) && cursor_position<(Nb_video_modes-1))
cursor_position++;
else
if (list_start0)
cursor_position=0;
else
{
if (list_start>(MODELIST_LINES-1))
list_start-=(MODELIST_LINES-1);
else
list_start=0;
}
Scroll_list_of_modes(list_start,cursor_position,&selected_mode);
Key=0;
break;
case SDLK_PAGEDOWN : // PageDown
if (Nb_video_modesOPERATION_FILLED_CONTOUR)
Selected_freehand_mode=OPERATION_CONTINUOUS_DRAW;
Hide_cursor();
switch(Selected_freehand_mode)
{
default:
case OPERATION_CONTINUOUS_DRAW:
icon=-1;
break;
case OPERATION_DISCONTINUOUS_DRAW:
icon=MENU_SPRITE_DISCONTINUOUS_DRAW;
break;
case OPERATION_POINT_DRAW:
icon=MENU_SPRITE_POINT_DRAW;
break;
case OPERATION_FILLED_CONTOUR:
icon=MENU_SPRITE_CONTOUR_DRAW;
break;
}
Display_sprite_in_menu(BUTTON_DRAW,icon);
Draw_menu_button(BUTTON_DRAW,BUTTON_PRESSED);
Start_operation_stack(Selected_freehand_mode);
Display_cursor();
/* NOUVEAU CODE AVEC POPUP (EN COURS DE TEST) ***
short clicked_button;
Open_popup(16,Menu_Y/Menu_factor_X-32,18,50);
Window_set_normal_button(1,1,16,16,"A",0,1,KEY_ESC); // 1
Display_cursor();
Update_rect(16*Menu_factor_X,Menu_Y-32*Menu_factor_X,18*Menu_factor_X,50*Menu_factor_X);
do
{
while(!Get_input())Wait_VBL();
clicked_button = Window_get_clicked_button();
switch(clicked_button)
{
case 1:
Selected_freehand_mode++;
if (Selected_freehand_mode>OPERATION_FILLED_CONTOUR)
Selected_freehand_mode=OPERATION_CONTINUOUS_DRAW;
break;
}
}
while (Mouse_K);
Close_popup();
//Display_sprite_in_menu(BUTTON_DRAW,Selected_freehand_mode+2);
Start_operation_stack(Selected_freehand_mode);
Display_cursor();
*/
}
// -- Gestion des boutons de rectangle vide et plein ------------------------
void Button_Empty_rectangle(void)
{
Hide_cursor();
Start_operation_stack(OPERATION_EMPTY_RECTANGLE);
Display_cursor();
}
void Button_Filled_rectangle(void)
{
Hide_cursor();
Start_operation_stack(OPERATION_FILLED_RECTANGLE);
Display_cursor();
}
// -- Gestion des boutons de cercle (ellipse) vide et plein(e) --------------
void Button_Empty_circle(void)
{
Hide_cursor();
Start_operation_stack(OPERATION_EMPTY_CIRCLE);
Display_cursor();
}
void Button_Empty_ellipse(void)
{
Hide_cursor();
Start_operation_stack(OPERATION_EMPTY_ELLIPSE);
Display_cursor();
}
void Button_Filled_circle(void)
{
Hide_cursor();
Start_operation_stack(OPERATION_FILLED_CIRCLE);
Display_cursor();
}
void Button_Filled_ellipse(void)
{
Hide_cursor();
Start_operation_stack(OPERATION_FILLED_ELLIPSE);
Display_cursor();
}
// -- Gestion du menu des dgrads ------------------------------------------
void Draw_button_gradient_style(short x_pos,short y_pos,int technique)
{
short line;
// On commence par afficher les 2 cts qui constituent le dgrad de base:
// Ct gauche (noir)
Block(Window_pos_X+((x_pos+2)*Menu_factor_X),
Window_pos_Y+((y_pos+2)*Menu_factor_Y),
Menu_factor_X*6,
Menu_factor_Y*10,MC_Black);
// Ct droit (blanc)
Block(Window_pos_X+((x_pos+8)*Menu_factor_X),
Window_pos_Y+((y_pos+2)*Menu_factor_Y),
Menu_factor_X*5,
Menu_factor_Y*10,MC_White);
switch(technique)
{
case 1 : // Dgrad de trames simples
// Au centre, on place 10 lignes trames simplement
for (line=2;line<2+10;line++)
if (line&1)
{
// Lignes impaires
Pixel_in_window(x_pos+ 5,y_pos+line,MC_White);
Pixel_in_window(x_pos+ 7,y_pos+line,MC_White);
Pixel_in_window(x_pos+ 8,y_pos+line,MC_Black);
}
else
{
// Lignes paires
Pixel_in_window(x_pos+ 6,y_pos+line,MC_White);
Pixel_in_window(x_pos+ 9,y_pos+line,MC_Black);
}
break;
case 2 : // Dgrad de trames tendues
// Au centre, on place 10 lignes trames de faon complique
for (line=2;line<2+10;line++)
if (line&1)
{
// Lignes impaires
Pixel_in_window(x_pos+ 7,y_pos+line,MC_White);
Pixel_in_window(x_pos+ 8,y_pos+line,MC_Black);
Pixel_in_window(x_pos+10,y_pos+line,MC_Black);
}
else
{
// Lignes paires
Pixel_in_window(x_pos+ 4,y_pos+line,MC_White);
Pixel_in_window(x_pos+ 6,y_pos+line,MC_White);
}
}
Update_rect(Window_pos_X+((x_pos+2)*Menu_factor_X),Window_pos_Y+((y_pos+2)*Menu_factor_Y),
Menu_factor_X*10,Menu_factor_Y*10);
}
void Load_gradient_data(int index)
{
if (Main_backups->Pages->Gradients->Range[index].Start>Main_backups->Pages->Gradients->Range[index].End)
Error(0);
Gradient_lower_bound =Main_backups->Pages->Gradients->Range[index].Start;
Gradient_upper_bound =Main_backups->Pages->Gradients->Range[index].End;
Gradient_is_inverted =Main_backups->Pages->Gradients->Range[index].Inverse;
Gradient_random_factor=Main_backups->Pages->Gradients->Range[index].Mix+1;
Gradient_bounds_range=(Gradient_lower_boundPages->Gradients->Range[index].Technique)
{
case 0 : // Degrad de base
Gradient_function=Gradient_basic;
break;
case 1 : // Dgrad de trames simples
Gradient_function=Gradient_dithered;
break;
case 2 : // Dgrad de trames tendues
Gradient_function=Gradient_extra_dithered;
}
}
void Draw_gradient_preview(short start_x,short start_y,short width,short height,int index)
{
short x_pos; // Variables de balayage du block en bas de l'cran.
short y_pos;
short end_x;
short end_y;
Load_gradient_data(index);
start_x=Window_pos_X+(start_x*Menu_factor_X);
start_y=Window_pos_Y+(start_y*Menu_factor_Y);
Gradient_total_range=width*Menu_factor_X;
end_x=start_x+Gradient_total_range;
end_y=start_y+(height*Menu_factor_Y);
for (y_pos=start_y;y_posPages->Gradients,sizeof(T_Gradient_array));
Open_window(235,146,"Gradation menu");
Window_set_palette_button(48,19); // 1
// Slider for gradient selection
gradient_scroller=Window_set_scroller_button(218,20,75,16,1,Current_gradient); // 2
// Slider for mix
mix_scroller = Window_set_scroller_button(31,20,84,256,1,
Main_backups->Pages->Gradients->Range[Current_gradient].Mix); // 3
// Direction
Window_set_normal_button(8,20,15,14,
(Main_backups->Pages->Gradients->Range[Current_gradient].Inverse)?"\033":"\032",0,1,SDLK_TAB); // 4
// Technique
Window_set_normal_button(8,90,15,14,"",0,1,SDLK_TAB|MOD_SHIFT); // 5
Draw_button_gradient_style(8,90,Main_backups->Pages->Gradients->Range[Current_gradient].Technique);
Window_set_normal_button(178,128,51,14,"OK",0,1,SDLK_RETURN); // 6
Window_set_normal_button(123,128,51,14,"Cancel",0,1,KEY_ESC); // 7
// Scrolling speed
speed_scroller = Window_set_horizontal_scroller_button(99,111,130,106,1,Main_backups->Pages->Gradients->Range[Current_gradient].Speed); // 8
Num2str(Main_backups->Pages->Gradients->Range[Current_gradient].Speed,str,3);
Print_in_window(73,113,str,MC_Black,MC_Light);
Print_in_window(5,58,"MIX",MC_Dark,MC_Light);
// Cycling mode on/off
Window_set_normal_button(8,109,62,14,"",0,1,KEY_NONE); // 9
Print_in_window(11,112,"Cycling",cycling_mode?MC_Black:MC_Dark,MC_Light);
// On tagge les couleurs qui vont avec
Tag_color_range(Main_backups->Pages->Gradients->Range[Current_gradient].Start,Main_backups->Pages->Gradients->Range[Current_gradient].End);
Num2str(Current_gradient+1,str,2);
Print_in_window(215,100,str,MC_Black,MC_Light);
// On affiche le cadre autour de la prview
Window_display_frame_in(7,127,110,16);
// On affiche la preview
Draw_gradient_preview(8,128,108,14,Current_gradient);
first_color=last_color=(Main_backups->Pages->Gradients->Range[Current_gradient].Inverse)?Main_backups->Pages->Gradients->Range[Current_gradient].End:Main_backups->Pages->Gradients->Range[Current_gradient].Start;
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
old_mouse_x=Mouse_X;
old_mouse_y=Mouse_Y;
old_mouse_k=Mouse_K;
if (changed_gradient_index)
{
// User has changed which gradient (0-15) he's watching
changed_gradient_index=0;
Hide_cursor();
// On affiche la valeur sous la jauge
Num2str(Current_gradient+1,str,2);
Print_in_window(215,100,str,MC_Black,MC_Light);
// On tagge les couleurs qui vont avec
Tag_color_range(Main_backups->Pages->Gradients->Range[Current_gradient].Start,Main_backups->Pages->Gradients->Range[Current_gradient].End);
// On affiche le sens qui va avec
Print_in_window(12,23,(Main_backups->Pages->Gradients->Range[Current_gradient].Inverse)?"\033":"\032",MC_Black,MC_Light);
// On raffiche le mlange (jauge) qui va avec
mix_scroller->Position=Main_backups->Pages->Gradients->Range[Current_gradient].Mix;
Window_draw_slider(mix_scroller);
// Update speed
speed_scroller->Position=Main_backups->Pages->Gradients->Range[Current_gradient].Speed;
Window_draw_slider(speed_scroller);
Num2str(Main_backups->Pages->Gradients->Range[Current_gradient].Speed,str,3);
Print_in_window(73,113,str,MC_Black,MC_Light);
// Gradient #
gradient_scroller->Position=Current_gradient;
Window_draw_slider(gradient_scroller);
// Technique (flat, dithered, very dithered)
Draw_button_gradient_style(8,90,Main_backups->Pages->Gradients->Range[Current_gradient].Technique);
// Rectangular gradient preview
Draw_gradient_preview(8,128,108,14,Current_gradient);
Display_cursor();
}
clicked_button=Window_clicked_button();
if (Input_sticky_control!=8 || !Mouse_K)
{
Allow_colorcycling=0;
// Restore palette
Set_palette(Main_palette);
}
switch(clicked_button)
{
case -1 :
case 1 : // Palette
if ( (Mouse_X!=old_mouse_x) || (Mouse_Y!=old_mouse_y) || (Mouse_K!=old_mouse_k) )
{
Hide_cursor();
temp_color=(clicked_button==1) ? Window_attribute2 : Read_pixel(Mouse_X,Mouse_Y);
if (!old_mouse_k)
{
// On vient de clicker
// On met jour l'intervalle du dgrad
first_color=last_color=Main_backups->Pages->Gradients->Range[Current_gradient].Start=Main_backups->Pages->Gradients->Range[Current_gradient].End=temp_color;
// On tagge le bloc
Tag_color_range(Main_backups->Pages->Gradients->Range[Current_gradient].Start,Main_backups->Pages->Gradients->Range[Current_gradient].End);
// Trac de la preview:
Draw_gradient_preview(8,128,108,14,Current_gradient);
}
else
{
// On maintient le click, on va donc tester si le curseur bouge
if (temp_color!=last_color)
{
// On commence par ordonner la 1re et dernire couleur du bloc
if (first_colorPages->Gradients->Range[Current_gradient].Start=first_color;
Main_backups->Pages->Gradients->Range[Current_gradient].End =temp_color;
}
else if (first_color>temp_color)
{
Main_backups->Pages->Gradients->Range[Current_gradient].Start=temp_color;
Main_backups->Pages->Gradients->Range[Current_gradient].End =first_color;
}
else
Main_backups->Pages->Gradients->Range[Current_gradient].Start=Main_backups->Pages->Gradients->Range[Current_gradient].End=first_color;
// On tagge le bloc
Tag_color_range(Main_backups->Pages->Gradients->Range[Current_gradient].Start,Main_backups->Pages->Gradients->Range[Current_gradient].End);
// Trac de la preview:
Draw_gradient_preview(8,128,108,14,Current_gradient);
last_color=temp_color;
}
}
Display_cursor();
}
break;
case 2 : // Nouvel indice de dgrad
// Nouvel indice dans Window_attribute2
Current_gradient=Window_attribute2;
changed_gradient_index=1;
break;
case 3 : // Nouveau mlange de dgrad
Hide_cursor();
// Nouvel mlange dans Window_attribute2
Main_backups->Pages->Gradients->Range[Current_gradient].Mix=Window_attribute2;
// On affiche la nouvelle preview
Draw_gradient_preview(8,128,108,14,Current_gradient);
Display_cursor();
break;
case 4 : // Changement de sens
Hide_cursor();
// On inverse le sens (par un XOR de 1)
Main_backups->Pages->Gradients->Range[Current_gradient].Inverse^=1;
Print_in_window(12,23,(Main_backups->Pages->Gradients->Range[Current_gradient].Inverse)?"\033":"\032",MC_Black,MC_Light);
// On affiche la nouvelle preview
Draw_gradient_preview(8,128,108,14,Current_gradient);
Display_cursor();
break;
case 5 : // Changement de technique
Hide_cursor();
// On change la technique par (+1)%3
Main_backups->Pages->Gradients->Range[Current_gradient].Technique=(Main_backups->Pages->Gradients->Range[Current_gradient].Technique+1)%3;
Draw_button_gradient_style(8,90,Main_backups->Pages->Gradients->Range[Current_gradient].Technique);
// On affiche la nouvelle preview
Draw_gradient_preview(8,128,108,14,Current_gradient);
Display_cursor();
case 8 : // Speed
Main_backups->Pages->Gradients->Range[Current_gradient].Speed=Window_attribute2;
Num2str(Main_backups->Pages->Gradients->Range[Current_gradient].Speed,str,3);
Hide_cursor();
Print_in_window(73,113,str,MC_Black,MC_Light);
Display_cursor();
Allow_colorcycling=1;
break;
case 9: // Cycling on/off
cycling_mode = !cycling_mode;
Hide_cursor();
Print_in_window(11,112,"Cycling",cycling_mode?MC_Black:MC_Dark,MC_Light);
Display_cursor();
break;
}
if (!Mouse_K)
switch (Key)
{
case SDLK_BACKQUOTE : // Rcupration d'une couleur derrire le menu
case SDLK_COMMA :
Get_color_behind_window(&color,&click);
if (click)
{
Hide_cursor();
temp_color=color;
// On met jour l'intervalle du dgrad
first_color=last_color=Main_backups->Pages->Gradients->Range[Current_gradient].Start=Main_backups->Pages->Gradients->Range[Current_gradient].End=temp_color;
// On tagge le bloc
Tag_color_range(Main_backups->Pages->Gradients->Range[Current_gradient].Start,Main_backups->Pages->Gradients->Range[Current_gradient].End);
// Trac de la preview:
Draw_gradient_preview(8,128,108,14,Current_gradient);
Display_cursor();
Wait_end_of_click();
}
Key=0;
break;
case KEY_MOUSEWHEELUP:
if (Current_gradient>0)
{
Current_gradient--;
changed_gradient_index=1;
}
break;
case KEY_MOUSEWHEELDOWN:
if (Current_gradient<15)
{
Current_gradient++;
changed_gradient_index=1;
}
break;
default:
if (Is_shortcut(Key,0x100+BUTTON_HELP))
{
Window_help(BUTTON_GRADRECT, NULL);
Key=0;
break;
}
else if (Is_shortcut(Key,0x200+BUTTON_GRADRECT))
clicked_button=6;
else if (Is_shortcut(Key,SPECIAL_CYCLE_MODE))
{
// Cycling on/off
cycling_mode = !cycling_mode;
Hide_cursor();
Print_in_window(11,112,"Cycling",cycling_mode?MC_Black:MC_Dark,MC_Light);
Display_cursor();
}
}
}
while (clicked_button!=6 && clicked_button!=7);
Close_window();
// The Grad rect operation uses the same button as Grad menu.
if (Current_operation != OPERATION_GRAD_RECTANGLE)
Unselect_button(BUTTON_GRADRECT);
Display_cursor();
Gradient_pixel=Display_pixel;
Cycling_mode=cycling_mode;
if (clicked_button==7) // Cancel
{
Current_gradient=old_current_gradient;
memcpy(Main_backups->Pages->Gradients,&backup_gradients,sizeof(T_Gradient_array));
}
}
// -- Gestion des boutons de cercle / ellipse / rectangle dgrads --------------------
void Button_Grad_circle(void)
{
Hide_cursor();
Start_operation_stack(OPERATION_GRAD_CIRCLE);
Display_cursor();
}
void Button_Grad_ellipse(void)
{
Hide_cursor();
Start_operation_stack(OPERATION_GRAD_ELLIPSE);
Display_cursor();
}
void Button_Grad_rectangle(void)
{
Hide_cursor();
Start_operation_stack(OPERATION_GRAD_RECTANGLE);
Display_cursor();
}
// -- Gestion du bouton de remplissage ---------------------------------------
void Button_Fill(void)
{
if (Current_operation!=OPERATION_FILL)
{
Hide_cursor();
if (Current_operation!=OPERATION_REPLACE)
{
Paintbrush_shape_before_fill=Paintbrush_shape;
Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
}
else
if ( (Mouse_Y=Main_X_zoom) ) )
Print_in_menu("X: Y: ",0);
Start_operation_stack(OPERATION_FILL);
Display_cursor();
}
}
void Button_Replace(void)
{
if (Current_operation!=OPERATION_REPLACE)
{
Hide_cursor();
if (Current_operation!=OPERATION_FILL)
{
Paintbrush_shape_before_fill=Paintbrush_shape;
Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
}
if ( (Mouse_Y=Main_X_zoom) ) )
Print_in_menu("X: Y: ( )",0);
Start_operation_stack(OPERATION_REPLACE);
Display_cursor();
}
}
void Button_Unselect_fill(void)
{
Paintbrush_shape=Paintbrush_shape_before_fill;
if (Current_operation==OPERATION_REPLACE)
if ( (Mouse_Y=Main_X_zoom) ) )
Print_in_menu("X: Y: ",0);
}
//---------------------------- Menu des pinceaux -----------------------------
/// Checks if the current brush is identical to a preset one.
byte Same_paintbrush(byte index)
{
if (Paintbrush_shape!=Paintbrush[index].Shape ||
Paintbrush_width!=Paintbrush[index].Width ||
Paintbrush_height!=Paintbrush[index].Height)
return 0;
if (Paintbrush_shape==PAINTBRUSH_SHAPE_MISC)
{
// Check all pixels
int x,y;
for(y=0;y=(NB_PAINTBRUSH_SPRITES+3))
{
index = clicked_button-NB_PAINTBRUSH_SPRITES-3;
if (Window_attribute2==1) // Set
{
// Store
x_pos=13+((index+NB_PAINTBRUSH_SPRITES)%12)*24;
y_pos=27+((index+NB_PAINTBRUSH_SPRITES)/12)*25;
Store_brush(index);
Hide_cursor();
Display_stored_brush_in_window(x_pos+2, y_pos+2, index);
Display_cursor();
}
else
{
// Restore and exit
if (Restore_brush(index))
{
Close_window();
break;
}
}
}
else if (clicked_button>=3)
// Standard paintbrushes
{
if (Window_attribute2!=1)
{
// Select paintbrush
Close_window();
Select_paintbrush(clicked_button-3);
break;
}
else if (Window_attribute2==1)
{
// Store current
index=clicked_button-3;
if (!Store_paintbrush(index))
{
// Redraw
Hide_cursor();
x_pos=13+(index%12)*24;
y_pos=27+(index/12)*25;
Window_rectangle(x_pos,y_pos,20,20,MC_White);
Display_paintbrush_in_window(x_pos+2,y_pos+2,index);
Display_cursor();
}
}
}
else if (clicked_button==1 || Is_shortcut(Key,0x100+BUTTON_PAINTBRUSHES))
{
Close_window();
break;
}
else if (clicked_button==2)
{
int size;
// Pick a standard shape
Paintbrush_shape=Window_attribute2;
// Assign a reasonable size
size=Max(Paintbrush_width,Paintbrush_height);
if (size==1)
size=3;
switch (Paintbrush_shape)
{
case PAINTBRUSH_SHAPE_HORIZONTAL_BAR:
Set_paintbrush_size(size, 1);
break;
case PAINTBRUSH_SHAPE_VERTICAL_BAR:
Set_paintbrush_size(1, size);
break;
case PAINTBRUSH_SHAPE_CROSS:
case PAINTBRUSH_SHAPE_PLUS:
case PAINTBRUSH_SHAPE_DIAMOND:
Set_paintbrush_size(size|1,size|1);
break;
default:
Set_paintbrush_size(size,size);
break;
}
Close_window();
Change_paintbrush_shape(Paintbrush_shape);
break;
}
}
while (1);
Unselect_button(BUTTON_PAINTBRUSHES);
Display_cursor();
}
void Button_Brush_monochrome(void)
{
Hide_cursor();
// On passe en brosse monochrome:
Change_paintbrush_shape(PAINTBRUSH_SHAPE_MONO_BRUSH);
Unselect_button(BUTTON_PAINTBRUSHES);
Display_cursor();
}
// -- Fonction renvoyant le mode vido le plus adapt l'image charge -----
#define TOLERANCE_X 8
#define TOLERANCE_Y 4
int Best_video_mode(void)
{
short best_width,best_height;
int best_mode;
short temp_x,temp_y;
int mode;
// Si mode fentre, on reste dans ce mode.
if (Current_resolution == 0)
return 0;
// On commence par borner les dimensions, ou du moins les rendre cohrentes
if ((Original_screen_X<=0) || (Config.Set_resolution_according_to==2))
Original_screen_X=Main_image_width;
else
if (Original_screen_X<320)
Original_screen_X=320;
if ((Original_screen_Y<=0) || (Config.Set_resolution_according_to==2))
Original_screen_Y=Main_image_height;
else
if (Original_screen_Y<200)
Original_screen_Y=200;
if ((Original_screen_X>1024) || (Original_screen_Y>768))
{
Original_screen_X=1024;
Original_screen_Y=768;
}
// Maintenant on peut chercher le mode qui correspond le mieux
best_mode=Current_resolution;
best_width=0;
best_height=0;
for (mode=1; mode On charge/sauve une image
// Image=0 => On charge/sauve une brosse
{
byte confirm;
byte old_cursor_shape;
int new_mode;
T_IO_Context context;
static char filename [MAX_PATH_CHARACTERS];
static char directory[MAX_PATH_CHARACTERS];
if (image)
{
strcpy(filename, Main_backups->Pages->Filename);
strcpy(directory, Main_backups->Pages->File_directory);
Init_context_layered_image(&context, filename, directory);
}
else
{
strcpy(filename, Brush_filename);
strcpy(directory, Main_current_directory);
Init_context_brush(&context, Brush_filename, Main_current_directory);
}
confirm=Button_Load_or_Save(1, &context);
if (confirm)
{
if (image)
{
if (Main_image_is_modified)
confirm=Confirmation_box("Discard unsaved changes?");
}
}
// confirm is modified inside the first if, that's why we check it
// again here
if (confirm)
{
old_cursor_shape=Cursor_shape;
Hide_cursor();
Cursor_shape=CURSOR_SHAPE_HOURGLASS;
Display_cursor();
if (image)
{
Original_screen_X=0;
Original_screen_Y=0;
}
Load_image(&context);
if (!image)
{
if (File_error==3) // Memory allocation error when loading brush
{
// Nothing to do here.
// Previous versions of Grafx2 would have damaged the Brush,
// and need reset it here, but now the loading is done in separate
// memory buffers.
}
Tiling_offset_X=0;
Tiling_offset_Y=0;
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
Select_button(BUTTON_DRAW,LEFT_SIDE);
if (Config.Auto_discontinuous)
{
// On se place en mode Dessin discontinu la main
while (Current_operation!=OPERATION_DISCONTINUOUS_DRAW)
Select_button(BUTTON_DRAW,RIGHT_SIDE);
}
Hide_cursor();
// On passe en brosse couleur:
Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
}
else
{
Hide_cursor();
Cursor_shape=old_cursor_shape;
}
if ( (File_error==1) || (Get_fileformat(Main_fileformat)->Palette_only) )
{
if (File_error!=1)
Compute_optimal_menu_colors(Main_palette);
}
else
{
if (image)
{
if (Main_magnifier_mode)
{
Pixel_preview=Pixel_preview_normal;
Main_magnifier_mode=0;
Draw_menu_button(BUTTON_MAGNIFIER,Main_magnifier_mode);
}
new_mode=Best_video_mode();
if ((Config.Auto_set_res) && (new_mode!=Current_resolution))
{
Init_mode_video(
Video_mode[new_mode].Width,
Video_mode[new_mode].Height,
Video_mode[new_mode].Fullscreen,
Pixel_ratio);
Display_menu();
}
// In window mode, activate wide or tall pixels if the image says so.
else if (!Video_mode[Current_resolution].Fullscreen &&
((context.Ratio == PIXEL_WIDE &&
Pixel_ratio != PIXEL_WIDE && Pixel_ratio != PIXEL_WIDE2) ||
(context.Ratio == PIXEL_TALL &&
Pixel_ratio != PIXEL_TALL && Pixel_ratio != PIXEL_TALL2)))
{
Init_mode_video(
Video_mode[Current_resolution].Width,
Video_mode[Current_resolution].Height,
Video_mode[Current_resolution].Fullscreen,
context.Ratio);
Display_menu();
}
else
{
Main_offset_X=0;
Main_offset_Y=0;
Compute_limits();
Compute_paintbrush_coordinates();
}
}
Compute_optimal_menu_colors(Main_palette);
Redraw_layered_image();
End_of_modification();
Display_all_screen();
if (image)
Main_image_is_modified=0;
}
Destroy_context(&context);
Display_menu();
Display_cursor();
}
//if (!image)
// Swap_data_of_image_and_brush();
Hide_cursor();
Print_filename();
Display_cursor();
Set_palette(Main_palette);
}
void Button_Load(void)
{
// On sauve l'tat actuel des paramtres de l'image pour pouvoir les
// restituer en cas d'erreur n'affectant pas l'image
Upload_infos_page_main(Main_backups->Pages);
Load_picture(1);
}
void Button_Reload(void)
{
byte old_cursor_shape;
int new_mode;
// On sauve l'tat actuel des paramtres de l'image pour pouvoir les
// restituer en cas d'erreur n'affectant pas l'image
Upload_infos_page_main(Main_backups->Pages);
if ( (!Main_image_is_modified) || Confirmation_box("Discard unsaved changes ?") )
{
T_IO_Context context;
Hide_cursor();
old_cursor_shape=Cursor_shape;
Cursor_shape=CURSOR_SHAPE_HOURGLASS;
Display_cursor();
Original_screen_X=0;
Original_screen_Y=0;
Init_context_layered_image(&context, Main_backups->Pages->Filename, Main_backups->Pages->File_directory);
Load_image(&context);
Hide_cursor();
Cursor_shape=old_cursor_shape;
if (File_error!=1)
{
if (Main_magnifier_mode)
{
Pixel_preview=Pixel_preview_normal;
Main_magnifier_mode=0;
Draw_menu_button(BUTTON_MAGNIFIER,Main_magnifier_mode);
}
new_mode=Best_video_mode();
if ( ((Config.Auto_set_res) && (new_mode!=Current_resolution)) &&
(!Resolution_in_command_line) )
{
Init_mode_video(
Video_mode[new_mode].Width,
Video_mode[new_mode].Height,
Video_mode[new_mode].Fullscreen,
Pixel_ratio);
Display_menu();
}
// In window mode, activate wide or tall pixels if the image says so.
else if (!Video_mode[Current_resolution].Fullscreen &&
((context.Ratio == PIXEL_WIDE &&
Pixel_ratio != PIXEL_WIDE && Pixel_ratio != PIXEL_WIDE2) ||
(context.Ratio == PIXEL_TALL &&
Pixel_ratio != PIXEL_TALL && Pixel_ratio != PIXEL_TALL2)))
{
Init_mode_video(
Video_mode[Current_resolution].Width,
Video_mode[Current_resolution].Height,
Video_mode[Current_resolution].Fullscreen,
context.Ratio);
Display_menu();
}
else
{
Main_offset_X=0;
Main_offset_Y=0;
Compute_limits();
Compute_paintbrush_coordinates();
}
Redraw_layered_image();
End_of_modification();
Display_all_screen();
Main_image_is_modified=0;
}
Destroy_context(&context);
}
else
Hide_cursor();
Compute_optimal_menu_colors(Main_palette);
Display_menu();
if (Config.Display_image_limits)
Display_image_limits();
Unselect_button(BUTTON_LOAD);
Display_cursor();
}
void Backup_filename(char * fname, char * backup_name)
{
short i;
strcpy(backup_name,fname);
for (i=strlen(fname)-strlen(Main_backups->Pages->Filename); backup_name[i]!='.'; i++);
backup_name[i+1]='\0';
strcat(backup_name,"BAK");
}
void Backup_existing_file(void)
{
char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
char new_filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier backup
Get_full_filename(filename, Main_backups->Pages->Filename, Main_backups->Pages->File_directory);
// Calcul du nom complet du fichier backup
Backup_filename(filename,new_filename);
File_error=0;
// On fait un backup si le nom du fichier n'est pas celui qu'on a choisi
// pour nommer les backups (c'est vident!).
if (strcmp(new_filename,filename))
{
// S'il y avait dj un fichier Backup, on l'efface
if ((File_exists(new_filename))
&& (remove(new_filename)!=0))
File_error=1;
if ((!File_error)
&& (rename(filename,new_filename)!=0))
File_error=1;
}
}
void Save_picture(byte image)
// image=1 => On charge/sauve une image
// image=0 => On charge/sauve une brosse
{
byte confirm;
byte old_cursor_shape;
T_IO_Context save_context;
static char filename [MAX_PATH_CHARACTERS];
static char directory[MAX_PATH_CHARACTERS];
if (image)
{
strcpy(filename, Main_backups->Pages->Filename);
strcpy(directory, Main_backups->Pages->File_directory);
Init_context_layered_image(&save_context, filename, directory);
save_context.Format = Main_fileformat;
}
else
{
strcpy(filename, Brush_filename);
strcpy(directory, Brush_file_directory);
Init_context_brush(&save_context, filename, directory);
save_context.Format = Main_fileformat;
}
//if (!image)
// Swap_data_of_image_and_brush();
confirm=Button_Load_or_Save(0, &save_context);
if (confirm && File_exists(save_context.File_name))
{
confirm=Confirmation_box("Erase old file ?");
if (confirm && (Config.Backup))
{
Backup_existing_file();
if (File_error)
{
confirm=0;
Error(0);
}
}
}
if (confirm)
{
old_cursor_shape=Cursor_shape;
Hide_cursor();
Cursor_shape=CURSOR_SHAPE_HOURGLASS;
Display_cursor();
Save_image(&save_context);
if (!File_error && image && !Get_fileformat(save_context.Format)->Palette_only)
{
Main_image_is_modified=0;
strcpy(Main_backups->Pages->Filename, save_context.File_name);
strcpy(Main_backups->Pages->File_directory, save_context.File_directory);
}
Hide_cursor();
Cursor_shape=old_cursor_shape;
Display_cursor();
}
Destroy_context(&save_context);
Print_filename();
Set_palette(Main_palette);
}
void Button_Save(void)
{
Save_picture(1);
}
void Button_Autosave(void)
{
byte old_cursor_shape;
static char filename[MAX_PATH_CHARACTERS];
byte file_already_exists;
Get_full_filename(filename, Main_backups->Pages->Filename, Main_backups->Pages->File_directory);
file_already_exists=File_exists(filename);
if ( (!file_already_exists) || Confirmation_box("Erase old file ?") )
{
if ((file_already_exists) && (Config.Backup))
Backup_existing_file();
else
File_error=0;
Hide_cursor();
if (!File_error)
{
T_IO_Context save_context;
old_cursor_shape=Cursor_shape;
Cursor_shape=CURSOR_SHAPE_HOURGLASS;
Display_cursor();
Init_context_layered_image(&save_context, Main_backups->Pages->Filename, Main_backups->Pages->File_directory);
Save_image(&save_context);
if (!File_error)
{
Main_image_is_modified=0;
}
Destroy_context(&save_context);
Hide_cursor();
Cursor_shape=old_cursor_shape;
}
else
Error(0);
}
else
Hide_cursor();
Unselect_button(BUTTON_SAVE);
Display_cursor();
}
// -- Gestion des boutons de ligne ------------------------------------------
void Button_Lines(void)
{
Hide_cursor();
Start_operation_stack(Selected_line_mode);
Display_cursor();
}
void Button_Lines_switch_mode(void)
{
char icon;
if (Selected_line_mode==OPERATION_LINE)
Selected_line_mode=OPERATION_K_LINE;
else
{
if (Selected_line_mode==OPERATION_K_LINE)
Selected_line_mode=OPERATION_CENTERED_LINES;
else
Selected_line_mode=OPERATION_LINE;
}
switch(Selected_line_mode)
{
default:
case OPERATION_LINE:
icon=-1;
break;
case OPERATION_K_LINE:
icon=MENU_SPRITE_K_LINE;
break;
case OPERATION_CENTERED_LINES:
icon=MENU_SPRITE_CENTERED_LINES;
break;
}
Hide_cursor();
Display_sprite_in_menu(BUTTON_LINES,icon);
Draw_menu_button(BUTTON_LINES,BUTTON_PRESSED);
Start_operation_stack(Selected_line_mode);
Display_cursor();
}
// -- Button de brosse ------------------------------------------------------
void Button_Brush(void)
{
Hide_cursor();
if (Current_operation!=OPERATION_GRAB_BRUSH)
Start_operation_stack(OPERATION_GRAB_BRUSH);
else
Unselect_button(BUTTON_BRUSH);
Display_cursor();
}
void Button_Unselect_brush(void)
{
// On fait de notre mieux pour restaurer l'ancienne opration:
Start_operation_stack(Operation_before_interrupt);
}
void Button_Restore_brush(void)
{
Hide_cursor();
// On passe en brosse couleur:
Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
Unselect_button(BUTTON_BRUSH);
Unselect_button(BUTTON_POLYBRUSH);
Display_cursor();
}
// -- Button de prise de brosse au lasso ------------------------------------
void Button_Lasso(void)
{
Hide_cursor();
if (Current_operation!=OPERATION_POLYBRUSH)
{
Paintbrush_shape_before_lasso=Paintbrush_shape;
Paintbrush_shape=PAINTBRUSH_SHAPE_POINT;
Start_operation_stack(OPERATION_POLYBRUSH);
}
else
Unselect_button(BUTTON_POLYBRUSH);
Display_cursor();
}
void Button_Unselect_lasso(void)
{
// On fait de notre mieux pour restaurer l'ancienne opration:
Start_operation_stack(Operation_before_interrupt);
Paintbrush_shape=Paintbrush_shape_before_lasso;
}
// -- Button de pipette -----------------------------------------------------
void Button_Colorpicker(void)
{
Hide_cursor();
if (Current_operation!=OPERATION_COLORPICK)
{
Colorpicker_color=-1;
Start_operation_stack(OPERATION_COLORPICK);
Paintbrush_shape_before_colorpicker=Paintbrush_shape;
Paintbrush_shape=PAINTBRUSH_SHAPE_NONE;
if (Operation_before_interrupt!=OPERATION_REPLACE)
if ( (Mouse_Y=Main_X_zoom) ) )
Print_in_menu("X: Y: ( )",0);
}
else
Unselect_button(BUTTON_COLORPICKER);
Display_cursor();
}
void Button_Unselect_colorpicker(void)
{
// Erase the color block which shows the picked color
if (Operation_before_interrupt!=OPERATION_REPLACE)
if ( (Mouse_Y=Main_X_zoom) ) )
Print_in_menu("X: Y: ",0);
// On fait de notre mieux pour restaurer l'ancienne opration:
if (Current_operation==OPERATION_COLORPICK)
{
Start_operation_stack(Operation_before_interrupt);
Paintbrush_shape=Paintbrush_shape_before_colorpicker;
}
}
// -- Inversion de la couleur Fore et de la couleur Back --
void Button_Invert_foreback(void)
{
byte temp_color;
temp_color=Fore_color;
Fore_color =Back_color;
Back_color =temp_color;
Hide_cursor();
Frame_menu_color(Back_color);
Frame_menu_color(Fore_color);
Reposition_palette();
Display_foreback();
Unselect_button(BUTTON_COLORPICKER);
Display_cursor();
}
// -- Gestion du bouton Loupe -----------------------------------------------
byte Coming_from_zoom_factor_menu=0;
void Button_Magnify(void)
{
Hide_cursor();
if ( (Current_operation==OPERATION_MAGNIFY) || (Main_magnifier_mode) )
{
Unselect_button(BUTTON_MAGNIFIER);
}
else
{
Compute_magnifier_data();
if ((!Config.Fast_zoom) || (Mouse_Y>=Menu_Y) || Coming_from_zoom_factor_menu)
{
Coming_from_zoom_factor_menu=0;
Start_operation_stack(OPERATION_MAGNIFY);
}
else
{ /* Ceci est de la duplication de code de presque toute l'opration de */
/* la loupe... Il serait peut-tre plus propre de faire une procdure */
/* qui s'en charge... */
// On passe en mode loupe
Main_magnifier_mode=1;
// La fonction d'affichage dans la partie image est dsormais un affichage
// spcial loupe.
Pixel_preview=Pixel_preview_magnifier;
// On calcule l'origine de la loupe
Main_magnifier_offset_X=Mouse_X-(Main_magnifier_width>>1);
Main_magnifier_offset_Y=Mouse_Y-(Main_magnifier_height>>1);
// Calcul des coordonnes absolues de ce coin DANS L'IMAGE
Main_magnifier_offset_X+=Main_offset_X;
Main_magnifier_offset_Y+=Main_offset_Y;
Clip_magnifier_offsets(&Main_magnifier_offset_X, &Main_magnifier_offset_Y);
// On calcule les bornes visibles dans l'cran
Position_screen_according_to_zoom();
Compute_limits();
Display_all_screen();
// Repositionner le curseur en fonction des coordonnes visibles
Compute_paintbrush_coordinates();
}
}
Display_cursor();
Update_rect(0,0,0,0);
}
void Button_Magnify_menu(void)
{
T_Dropdown_button dropdown;
T_Dropdown_choice *item;
int i;
const char text[NB_ZOOM_FACTORS][4] =
{"x2", "x3", "x4", "x5", "x6", "x8", "x10", "x12", "x14", "x16", "x18", "x20",
"x24", "x28", "x32"};
Hide_cursor();
dropdown.Pos_X =Buttons_Pool[BUTTON_MAGNIFIER].X_offset;
dropdown.Pos_Y =Buttons_Pool[BUTTON_MAGNIFIER].Y_offset;
dropdown.Height =Buttons_Pool[BUTTON_MAGNIFIER].Height;
dropdown.Dropdown_width=28;
dropdown.First_item =NULL;
dropdown.Bottom_up =1;
for(i = 0; i < NB_ZOOM_FACTORS; i++) {
Window_dropdown_add_item(&dropdown, i, text[i]);
}
item=Dropdown_activate(&dropdown,0,Menu_Y);
if (item)
{
Change_magnifier_factor(item->Number,0);
}
if ( (!item) && (!Main_magnifier_mode) && (Current_operation!=OPERATION_MAGNIFY) ) // Cancel
Unselect_button(BUTTON_MAGNIFIER);
Display_all_screen();
Display_cursor();
Update_rect(Main_separator_position,0,Screen_width-Main_separator_position,Menu_Y);
if ( (item) && (!Main_magnifier_mode) && (Current_operation!=OPERATION_MAGNIFY) ) // Passage en mode zoom
{
Coming_from_zoom_factor_menu=1;
Select_button(BUTTON_MAGNIFIER,LEFT_SIDE);
}
Window_dropdown_clear_items(&dropdown);
}
void Button_Unselect_magnifier(void)
{
if (Main_magnifier_mode)
{
// On sort du mode loupe
Main_magnifier_mode=0;
// --> Recalculer le dcalage de l'cran lorsqu'on sort de la loupe <--
// Centrage "brut" de lcran par rapport la loupe
Main_offset_X=Main_magnifier_offset_X-((Screen_width-Main_magnifier_width)>>1);
Main_offset_Y=Main_magnifier_offset_Y-((Menu_Y-Main_magnifier_height)>>1);
// Correction en cas de dbordement de l'image
if (Main_offset_X+Screen_width>Main_image_width)
Main_offset_X=Main_image_width-Screen_width;
if (Main_offset_X<0)
Main_offset_X=0;
if (Main_offset_Y+Menu_Y>Main_image_height)
Main_offset_Y=Main_image_height-Menu_Y;
if (Main_offset_Y<0)
Main_offset_Y=0;
// La fonction d'affichage dans l'image est dsormais un affichage normal.
Pixel_preview=Pixel_preview_normal;
// Calculer les bornes visibles dans l'cran
Compute_limits();
Display_all_screen(); // <=> Display_screen();
// Repositionner le curseur en fonction des coordonnes visibles
Compute_paintbrush_coordinates();
Old_MX = -1;
Old_MY = -1;
}
else // On fait de notre mieux pour restaurer l'ancienne opration:
Start_operation_stack(Operation_before_interrupt);
}
// ----------------------- Modifications de brosse ---------------------------
void Button_Brush_FX(void)
{
short clicked_button;
short index;
Open_window(310,162,"Brush effects");
Window_display_frame( 6,19,298,61);
Window_display_frame( 6,83,122,53);
Window_display_frame(137,83,167,53);
Window_set_normal_button(236,141, 67,14,"Cancel" ,0,1,KEY_ESC); // 1
Window_set_normal_button( 19, 46, 27,14,"X\035" ,0,1,Config_Key[SPECIAL_FLIP_X][0]); // 2
Window_set_normal_button( 19, 61, 27,14,"Y\022" ,0,1,Config_Key[SPECIAL_FLIP_Y][0]); // 3
Window_set_normal_button( 58, 46, 37,14,"90" ,0,1,Config_Key[SPECIAL_ROTATE_90][0]); // 4
Window_set_normal_button( 96, 46, 37,14,"180" ,0,1,Config_Key[SPECIAL_ROTATE_180][0]); // 5
Window_set_normal_button( 58, 61, 75,14,"any angle" ,0,1,Config_Key[SPECIAL_ROTATE_ANY_ANGLE][0]); // 6
Window_set_normal_button(145, 46, 67,14,"Stretch" ,0,1,Config_Key[SPECIAL_STRETCH][0]); // 7
Window_set_normal_button(145, 61, 67,14,"Distort" ,0,1,Config_Key[SPECIAL_DISTORT][0]); // 8
Window_set_normal_button(155, 99,131,14,"Recolorize" ,0,1,Config_Key[SPECIAL_RECOLORIZE_BRUSH][0]); // 9
Window_set_normal_button(155,117,131,14,"Get brush colors",0,1,Config_Key[SPECIAL_GET_BRUSH_COLORS][0]); // 10
// Boutons reprsentant les coins du brush handle: (HG,HD,C,BG,BD)
Window_set_normal_button( 75, 90,11,11,"",0,1,Config_Key[SPECIAL_TOP_LEFT_ATTACHMENT][0]); // 11
Window_set_normal_button(103, 90,11,11,"",0,1,Config_Key[SPECIAL_TOP_RIGHT_ATTACHMENT][0]); // 12
Window_set_normal_button( 89,104,11,11,"",0,1,Config_Key[SPECIAL_CENTER_ATTACHMENT][0]); // 13
Window_set_normal_button( 75,118,11,11,"",0,1,Config_Key[SPECIAL_BOTTOM_LEFT_ATTACHMENT][0]); // 14
Window_set_normal_button(103,118,11,11,"",0,1,Config_Key[SPECIAL_BOTTOM_RIGHT_ATTACHMENT][0]); // 15
Window_set_normal_button(224,46,67,14,"Outline",0,1,Config_Key[SPECIAL_OUTLINE][0]); // 16
Window_set_normal_button(224,61,67,14,"Nibble" ,0,1,Config_Key[SPECIAL_NIBBLE][0]); // 17
Window_set_normal_button( 7,141, 60,14,"Load",0,1,Config_Key[SPECIAL_LOAD_BRUSH][0]); // 18
Window_set_normal_button( 70,141, 60,14,"Save",0,1,Config_Key[SPECIAL_SAVE_BRUSH][0]); // 19
Print_in_window( 80, 24,"Shape modifications",MC_Dark,MC_Light);
Print_in_window( 10, 36,"Mirror",MC_Dark,MC_Light);
Print_in_window( 72, 36,"Rotate",MC_Dark,MC_Light);
Print_in_window(155, 36,"Deform",MC_Dark,MC_Light);
Print_in_window(230, 36,"Borders",MC_Dark,MC_Light);
Print_in_window(141, 88,"Colors modifications",MC_Dark,MC_Light);
Print_in_window( 20,102,"Brush",MC_Dark,MC_Light);
Print_in_window( 16,110,"handle",MC_Dark,MC_Light);
// Dessin des pointills pour le "brush handle"
for (index=0; index<13; index+=2)
{
Pixel_in_window( 88+index, 92,MC_Dark);
Pixel_in_window( 88+index,126,MC_Dark);
Pixel_in_window( 77,103+index,MC_Dark);
Pixel_in_window(111,103+index,MC_Dark);
}
// Dessin des coins et du centre pour les boutons du "brush handle"
// Coin HG
Block(Window_pos_X+(Menu_factor_X* 77),Window_pos_Y+(Menu_factor_Y* 92),Menu_factor_X*7,Menu_factor_Y,MC_Black);
Block(Window_pos_X+(Menu_factor_X* 77),Window_pos_Y+(Menu_factor_Y* 92),Menu_factor_X,Menu_factor_Y*7,MC_Black);
// Coin HD
Block(Window_pos_X+(Menu_factor_X*105),Window_pos_Y+(Menu_factor_Y* 92),Menu_factor_X*7,Menu_factor_Y,MC_Black);
Block(Window_pos_X+(Menu_factor_X*111),Window_pos_Y+(Menu_factor_Y* 92),Menu_factor_X,Menu_factor_Y*7,MC_Black);
// Centre
Block(Window_pos_X+(Menu_factor_X* 91),Window_pos_Y+(Menu_factor_Y*109),Menu_factor_X*7,Menu_factor_Y,MC_Black);
Block(Window_pos_X+(Menu_factor_X* 94),Window_pos_Y+(Menu_factor_Y*106),Menu_factor_X,Menu_factor_Y*7,MC_Black);
// Coin BG
Block(Window_pos_X+(Menu_factor_X* 77),Window_pos_Y+(Menu_factor_Y*126),Menu_factor_X*7,Menu_factor_Y,MC_Black);
Block(Window_pos_X+(Menu_factor_X* 77),Window_pos_Y+(Menu_factor_Y*120),Menu_factor_X,Menu_factor_Y*7,MC_Black);
// Coin BD
Block(Window_pos_X+(Menu_factor_X*105),Window_pos_Y+(Menu_factor_Y*126),Menu_factor_X*7,Menu_factor_Y,MC_Black);
Block(Window_pos_X+(Menu_factor_X*111),Window_pos_Y+(Menu_factor_Y*120),Menu_factor_X,Menu_factor_Y*7,MC_Black);
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
clicked_button=Window_clicked_button();
if (Is_shortcut(Key,0x100+BUTTON_HELP))
{
Key=0;
Window_help(BUTTON_BRUSH_EFFECTS, NULL);
}
else if (Is_shortcut(Key,0x100+BUTTON_BRUSH_EFFECTS))
{
clicked_button=1;
}
}
while (clicked_button<=0);
Close_window();
Unselect_button(BUTTON_BRUSH_EFFECTS);
// Gestion du bouton click
switch (clicked_button)
{
case 2 : // Flip X
Flip_X_lowlevel(Brush_original_pixels, Brush_width, Brush_height);
// Remap according to the last used remap table
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
break;
case 3 : // Flip Y
Flip_Y_lowlevel(Brush_original_pixels, Brush_width, Brush_height);
// Remap according to the last used remap table
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
break;
case 4 : // 90 Rotation
Rotate_90_deg();
break;
case 5 : // 180 Rotation
Rotate_180_deg_lowlevel(Brush, Brush_width, Brush_height);
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
break;
case 6 : // Any angle rotation
Start_operation_stack(OPERATION_ROTATE_BRUSH);
break;
case 7 : // Stretch
Start_operation_stack(OPERATION_STRETCH_BRUSH);
break;
case 8 : // Distort
Start_operation_stack(OPERATION_DISTORT_BRUSH);
break;
case 9 : // Recolorize
Remap_brush();
break;
case 10 : // Get brush colors
Display_cursor();
Get_colors_from_brush();
Hide_cursor();
break;
case 11 : // Brush Attachment: Top-Left
Brush_offset_X=0;
Brush_offset_Y=0;
break;
case 12 : // Brush Attachment: Top-Right
Brush_offset_X=(Brush_width-1);
Brush_offset_Y=0;
break;
case 13 : // Brush Attachment: Center
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
break;
case 14 : // Brush Attachment: Bottom-Left
Brush_offset_X=0;
Brush_offset_Y=(Brush_height-1);
break;
case 15 : // Brush Attachment: Bottom-Right
Brush_offset_X=(Brush_width-1);
Brush_offset_Y=(Brush_height-1);
break;
case 16 : // Outline
Outline_brush();
break;
case 17 : // Nibble
Nibble_brush();
break;
case 18 : // Load
Display_cursor();
Load_picture(0);
Hide_cursor();
break;
case 19 : // Save
Display_cursor();
Save_picture(0);
Hide_cursor();
break;
}
Display_cursor();
}
//---------------------------- Courbes de Bzier ----------------------------
void Button_Curves(void)
{
Hide_cursor();
Start_operation_stack(Selected_curve_mode);
Display_cursor();
}
void Button_Curves_switch_mode(void)
{
if (Selected_curve_mode==OPERATION_4_POINTS_CURVE)
Selected_curve_mode=OPERATION_3_POINTS_CURVE;
else
Selected_curve_mode=OPERATION_4_POINTS_CURVE;
Hide_cursor();
Display_sprite_in_menu(BUTTON_CURVES,Selected_curve_mode==OPERATION_4_POINTS_CURVE?MENU_SPRITE_4_POINTS_CURVE:-1);
Draw_menu_button(BUTTON_CURVES,BUTTON_PRESSED);
Start_operation_stack(Selected_curve_mode);
Display_cursor();
}
//--------------------------------- Spray -----------------------------------
void Button_Airbrush(void)
{
Hide_cursor();
Start_operation_stack(OPERATION_AIRBRUSH);
Display_cursor();
}
void Refresh_airbrush_settings(byte selected_color, byte update_slider)
{
char str[3];
if (update_slider)
{
Window_scroller_button_list->Position=49-Airbrush_multi_flow[selected_color];
Window_draw_slider(Window_scroller_button_list);
}
Num2str(Airbrush_multi_flow[selected_color],str,2);
Print_in_window(196,130,str,MC_Black,MC_Light);
Update_rect(Window_pos_X+(Menu_factor_X*(Window_palette_button_list->Pos_X+4+(selected_color >> 4)*10)),
Window_pos_Y+(Menu_factor_Y*(Window_palette_button_list->Pos_Y+3+(selected_color & 15)* 5)),
Menu_factor_X<<1,Menu_factor_Y*5);
}
void Button_Airbrush_menu(void)
{
static byte spray_init=1;
short clicked_button;
char str[4];
word index;
byte selected_color=Fore_color;
byte old_airbrush_mode =Airbrush_mode;
short old_airbrush_size =Airbrush_size;
byte old_airbrush_delay =Airbrush_delay;
byte old_airbrush_mono_flow=Airbrush_mono_flow;
byte old_airbrush_multi_flow[256];
T_Special_button * input_size_button;
T_Special_button * input_delay_button;
T_Special_button * input_flow_button;
T_Special_button * input_init_button;
word old_mouse_x;
word old_mouse_y;
byte old_mouse_k;
byte color;
byte click;
memcpy(old_airbrush_multi_flow,Airbrush_multi_flow,256);
Open_window(226,170,"Spray");
Window_set_normal_button(110,148,51,14,"Cancel" ,0,1,KEY_ESC); // 1
Window_set_normal_button(166,148,51,14,"OK" ,0,1,SDLK_RETURN); // 2
Window_set_scroller_button(178,62,74,50,1,49-Airbrush_multi_flow[selected_color]); // 3
Window_set_palette_button(7,56); // 4
Window_set_normal_button( 8,148,83,14,"Mode: ",0,1,SDLK_TAB); // 5
if (Airbrush_mode)
Print_in_window(50,151," Mono",MC_Black,MC_Light);
else
Print_in_window(50,151,"Multi",MC_Black,MC_Light);
Window_set_normal_button(194, 62,19,14,"+1" ,0,1,SDLK_KP_PLUS); // 6
Window_set_normal_button(194, 79,19,14,"-1" ,0,1,SDLK_KP_MINUS); // 7
Window_set_normal_button(194, 96,19,14,"x2" ,0,1,SDLK_KP_MULTIPLY); // 8
Window_set_normal_button(194,113,19,14,"2" ,0,1,SDLK_KP_ENTER); // 9
Window_set_normal_button( 8, 37,43,14,"Clear" ,1,1,SDLK_c); // 10
Print_in_window(142,25,"Size:" ,MC_Dark,MC_Light);
input_size_button = Window_set_input_button(186,23,3); // 11
Num2str(Airbrush_size,str,3);
Window_input_content(input_size_button,str);
Print_in_window(142,39,"Delay:" ,MC_Dark,MC_Light);
input_delay_button = Window_set_input_button(194,37,2); // 12
Num2str(Airbrush_delay,str,2);
Window_input_content(input_delay_button,str);
Print_in_window( 27,24,"Mono-Flow:",MC_Dark,MC_Light);
input_flow_button = Window_set_input_button(111,22,2); // 13
Num2str(Airbrush_mono_flow,str,2);
Window_input_content(input_flow_button,str);
Print_in_window( 67,40,"Init:",MC_Dark,MC_Light);
input_init_button = Window_set_input_button(111,38,2); // 14
Num2str(spray_init,str,2);
Window_input_content(input_init_button,str);
Window_display_frame(173,56,45,86);
Window_display_frame(137,19,81,33);
// On tagge toutes les couleurs utilises
for (index=0; index<256; index++)
if (Airbrush_multi_flow[index])
Stencil_tag_color(index,MC_Black);
// Et enfin, on tagge la couleur slectionne
Stencil_tag_color(selected_color,MC_White);
Refresh_airbrush_settings(selected_color,0);
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
Stencil_update_color(selected_color);
do
{
old_mouse_x=Mouse_X;
old_mouse_y=Mouse_Y;
old_mouse_k=Mouse_K;
clicked_button=Window_clicked_button();
switch (clicked_button)
{
case 0 :
case 2 : // OK
break;
case 1 : // Cancel
Airbrush_mode =old_airbrush_mode;
Airbrush_size =old_airbrush_size;
Airbrush_delay =old_airbrush_delay;
Airbrush_mono_flow=old_airbrush_mono_flow;
memcpy(Airbrush_multi_flow,old_airbrush_multi_flow,256);
break;
case 3 : // Scroller
Hide_cursor();
Airbrush_multi_flow[selected_color]=49-Window_attribute2;
Refresh_airbrush_settings(selected_color,0);
Display_cursor();
break;
case -1 :
case 4 : // Palette
if ( (Mouse_X!=old_mouse_x) || (Mouse_Y!=old_mouse_y) || (Mouse_K!=old_mouse_k) )
{
Hide_cursor();
Stencil_tag_color(selected_color,(Airbrush_multi_flow[selected_color])?MC_Black:MC_Light);
Stencil_update_color(selected_color);
// Mettre la couleur slectionne jour suivant le click
selected_color=(clicked_button==4) ? Window_attribute2 : Read_pixel(Mouse_X,Mouse_Y);
if (Mouse_K==2)
Airbrush_multi_flow[selected_color]=0;
else
if (Airbrush_multi_flow[selected_color]==0)
Airbrush_multi_flow[selected_color]=spray_init;
// Tagger la couleur slectionne en blanc
Stencil_tag_color(selected_color,MC_White);
Refresh_airbrush_settings(selected_color,1);
Display_cursor();
Stencil_update_color(selected_color);
}
break;
case 5 : // Toggle Mode
Airbrush_mode=(Airbrush_mode+1)&1;
Hide_cursor();
if (Airbrush_mode)
Print_in_window(50,151," Mono",MC_Black,MC_Light);
else
Print_in_window(50,151,"Multi",MC_Black,MC_Light);
Update_rect(Window_pos_X+50*Menu_factor_X,Window_pos_Y+151*Menu_factor_Y,5*8*Menu_factor_X,8*Menu_factor_Y);
Display_cursor();
break;
case 6 : // +1
for (index=0; index<256; index++)
{
if ( (Airbrush_multi_flow[index]) && (Airbrush_multi_flow[index]<49) )
Airbrush_multi_flow[index]++;
}
Hide_cursor();
Refresh_airbrush_settings(selected_color,1);
Display_cursor();
break;
case 7 : // -1
for (index=0; index<256; index++)
{
if (Airbrush_multi_flow[index]>1)
Airbrush_multi_flow[index]--;
}
Hide_cursor();
Refresh_airbrush_settings(selected_color,1);
Display_cursor();
break;
case 8 : // x2
for (index=0; index<256; index++)
{
if (Airbrush_multi_flow[index])
{
Airbrush_multi_flow[index]<<=1;
if (Airbrush_multi_flow[index]>49)
Airbrush_multi_flow[index]=49;
}
}
Hide_cursor();
Refresh_airbrush_settings(selected_color,1);
Display_cursor();
break;
case 9 : // 2
for (index=0; index<256; index++)
{
if (Airbrush_multi_flow[index]>1)
Airbrush_multi_flow[index]>>=1;
}
Hide_cursor();
Refresh_airbrush_settings(selected_color,1);
Display_cursor();
break;
case 10 : // Clear
memset(Airbrush_multi_flow,0,256);
// On raffiche les infos de la couleur slectionne
Refresh_airbrush_settings(selected_color,1);
// On efface les anciens TAGs
Window_clear_tags();
// Tagger la couleur slectionne en blanc
Stencil_tag_color(selected_color,MC_White);
Stencil_update_color(selected_color);
break;
case 11 : // Size
Num2str(Airbrush_size,str,3);
Readline(188,25,str,3,INPUT_TYPE_INTEGER);
Airbrush_size=atoi(str);
// On corrige les dimensions
if (Airbrush_size>256)
{
Airbrush_size=256;
Num2str(Airbrush_size,str,3);
Window_input_content(input_size_button,str);
}
else if (!Airbrush_size)
{
Airbrush_size=1;
Num2str(Airbrush_size,str,3);
Window_input_content(input_size_button,str);
}
Display_cursor();
break;
case 12 : // Delay
Num2str(Airbrush_delay,str,2);
Readline(196,39,str,2,INPUT_TYPE_INTEGER);
Airbrush_delay=atoi(str);
// On corrige le delai
if (Airbrush_delay>99)
{
Airbrush_delay=99;
Num2str(Airbrush_delay,str,2);
Window_input_content(input_delay_button,str);
}
Display_cursor();
break;
case 13 : // Mono-Flow
Num2str(Airbrush_mono_flow,str,2);
Readline(113,24,str,2,INPUT_TYPE_INTEGER);
Airbrush_mono_flow=atoi(str);
// On corrige le flux
if (!Airbrush_mono_flow)
{
Airbrush_mono_flow=1;
Num2str(Airbrush_mono_flow,str,2);
Window_input_content(input_flow_button,str);
}
Display_cursor();
break;
case 14 : // Init
Num2str(spray_init,str,2);
Readline(113,40,str,2,INPUT_TYPE_INTEGER);
spray_init=atoi(str);
// On corrige la valeur
if (spray_init>=50)
{
spray_init=49;
Num2str(spray_init,str,2);
Window_input_content(input_init_button,str);
}
else if (spray_init<1)
{
spray_init=1;
Num2str(spray_init,str,2);
Window_input_content(input_init_button,str);
}
Display_cursor();
break;
}
if (!Mouse_K)
switch (Key)
{
case SDLK_BACKQUOTE : // Rcupration d'une couleur derrire le menu
case SDLK_COMMA :
Get_color_behind_window(&color,&click);
if (click)
{
Hide_cursor();
Stencil_tag_color(selected_color,(Airbrush_multi_flow[selected_color])?MC_Black:MC_Light);
Stencil_update_color(selected_color);
// Mettre la couleur slectionne jour suivant le click
selected_color=color;
if (click==2)
Airbrush_multi_flow[selected_color]=0;
else
if (Airbrush_multi_flow[selected_color]==0)
Airbrush_multi_flow[selected_color]=spray_init;
// Tagger la couleur slectionne en blanc
Stencil_tag_color(selected_color,MC_White);
Refresh_airbrush_settings(selected_color,1);
Display_cursor();
Stencil_update_color(selected_color);
Wait_end_of_click();
}
Key=0;
break;
default:
if (Is_shortcut(Key,0x100+BUTTON_HELP))
{
Window_help(BUTTON_AIRBRUSH, NULL);
Key=0;
break;
}
if (Is_shortcut(Key,0x200+BUTTON_AIRBRUSH))
{
clicked_button=2;
break;
}
}
}
while ( (clicked_button!=1) && (clicked_button!=2) );
Close_window();
/*
// Tant que l'on aura pas rsolu le problme du dsenclenchement du mode
// de dessin prcedent, il faudra laisser a en remarque et donc passer en
// spray mme si on a click sur Cancel (idem pour OK (un peu plus bas)).
if (clicked_button==1) // Cancel
{
if (Current_operation!=OPERATION_AIRBRUSH)
Unselect_button(BUTTON_AIRBRUSH);
}
*/
Display_cursor();
/*
if (clicked_button==2) // OK
*/
if (Current_operation!=OPERATION_AIRBRUSH)
Select_button(BUTTON_AIRBRUSH,LEFT_SIDE);
}
// -- Gestion des boutons de polygone vide et plein -------------------------
void Button_polygon(void)
{
Hide_cursor();
Start_operation_stack(OPERATION_POLYGON);
Display_cursor();
}
void Button_Polyform(void)
{
Hide_cursor();
Start_operation_stack(OPERATION_POLYFORM);
Display_cursor();
}
void Button_Polyfill(void)
{
Hide_cursor();
Start_operation_stack(OPERATION_POLYFILL);
Display_cursor();
}
void Button_Filled_polyform(void)
{
Hide_cursor();
Start_operation_stack(OPERATION_FILLED_POLYFORM);
Display_cursor();
}
// -- Boutons d'ajustement de l'image ---------------------------------------
void Button_Adjust(void)
{
Hide_cursor();
Start_operation_stack(OPERATION_SCROLL);
Display_cursor();
}
// -- Menu des effets (Shade, Stencil, etc...) ------------------------------
void Display_effect_sprite(short sprite_number, short start_x, short start_y)
{
short x,y,x_pos,y_pos;
for (y=0,y_pos=start_y;yEffect_sprite[sprite_number][y][x]);
Update_rect(ToWinX(start_x),ToWinY(start_y),EFFECT_SPRITE_WIDTH*Menu_factor_X,EFFECT_SPRITE_HEIGHT*Menu_factor_Y);
}
void Display_effect_state(short x, short y, char * label, byte state)
{
Block(Window_pos_X+(x*Menu_factor_X),Window_pos_Y+(y*Menu_factor_Y),
12*Menu_factor_X,Menu_factor_Y<<3,MC_Light);
Print_in_window(x,y,label,(state)?MC_White:MC_Black,MC_Light);
if (state)
Print_in_window(x+56,y,":ON ",MC_White,MC_Light);
else
Print_in_window(x+56,y,":OFF",MC_Black,MC_Light);
}
void Display_effect_states(void)
{
Display_effect_state( 30, 24,"Shade" ,Shade_mode);
Display_effect_state( 30, 43,"Q-shade",Quick_shade_mode);
Display_effect_state( 30, 62,"Transp.",Colorize_mode);
Display_effect_state( 30, 81,"Smooth" ,Smooth_mode);
Display_effect_state( 30,100,"Smear" ,Smear_mode);
Display_effect_state(176, 24,"Stencil",Stencil_mode);
Display_effect_state(176, 43,"Mask" ,Mask_mode);
Display_effect_state(176, 62,"Sieve" ,Sieve_mode);
Display_effect_state(176, 81,"Grid" ,Snap_mode);
Display_effect_state(176,100,"Tiling" ,Tiling_mode);
}
void Display_feedback_state(void)
{
Print_in_window(159,134,(Config.FX_Feedback)?"YES":" NO",MC_Black,MC_Light);
}
void Button_Effects(void)
{
short clicked_button;
byte exit_by_close_button=0;
Open_window(270,152,"Drawing modes (effects)");
Window_set_normal_button( 7, 19, 16,16,"",0,1,Config_Key[SPECIAL_SHADE_MODE][0]); // 1
Window_set_normal_button( 7, 38, 16,16,"",0,1,Config_Key[SPECIAL_QUICK_SHADE_MODE][0]); // 2
Window_set_normal_button( 7, 57, 16,16,"",0,1,Config_Key[SPECIAL_COLORIZE_MODE][0]); // 3
Window_set_normal_button( 7, 76, 16,16,"",0,1,Config_Key[SPECIAL_SMOOTH_MODE][0]); // 4
Window_set_normal_button( 7, 95, 16,16,"",0,1,Config_Key[SPECIAL_SMEAR_MODE][0]); // 5
Window_set_normal_button(153, 19, 16,16,"",0,1,Config_Key[SPECIAL_STENCIL_MODE][0]); // 6
Window_set_normal_button(153, 38, 16,16,"",0,1,Config_Key[SPECIAL_MASK_MODE][0]); // 7
Window_set_normal_button(153, 57, 16,16,"",0,1,Config_Key[SPECIAL_SIEVE_MODE][0]); // 8
Window_set_normal_button(153, 76, 16,16,"",0,1,Config_Key[SPECIAL_GRID_MODE][0]); // 9
Window_set_normal_button(153, 95, 16,16,"",0,1,Config_Key[SPECIAL_TILING_MODE][0]); // 10
Window_set_normal_button(195,131, 68,14,"Close",0,1,SDLK_RETURN); // 11
Window_set_normal_button( 7,131, 68,14,"All off",0,1,SDLK_DELETE); // 12
Window_set_normal_button( 83,131,104,14,"Feedback: ",1,1,SDLK_f); // 13
Display_feedback_state();
Display_effect_sprite(0, 8,20);
Display_effect_sprite(0, 8,39);
Display_effect_sprite(1, 8,58);
Display_effect_sprite(2, 8,77);
Display_effect_sprite(8, 8,96);
Display_effect_sprite(4,154,20);
Display_effect_sprite(7,154,39);
Display_effect_sprite(5,154,58);
Display_effect_sprite(6,154,77);
Display_effect_sprite(3,154,96);
Display_effect_states();
Print_in_window(12,117,"click: Left:Switch / Right:Edit",MC_Dark,MC_Light);
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
clicked_button=Window_clicked_button();
if (Key==KEY_ESC || Is_shortcut(Key,0x100+BUTTON_EFFECTS))
{
clicked_button=11;
Key=0;
}
else if (Is_shortcut(Key,0x100+BUTTON_HELP))
{
// Aide contextuelle
switch(Window_get_clicked_button())
{
case 1:
Window_help(BUTTON_EFFECTS, "SHADE");
break;
case 2:
Window_help(BUTTON_EFFECTS, "QUICK SHADE");
break;
case 3:
Window_help(BUTTON_EFFECTS, "TRANSPARENCY");
break;
case 4:
Window_help(BUTTON_EFFECTS, "SMOOTH");
break;
case 5:
Window_help(BUTTON_EFFECTS, "SMEAR");
break;
case 6:
Window_help(BUTTON_EFFECTS, "STENCIL");
break;
case 7:
Window_help(BUTTON_EFFECTS, "MASK");
break;
case 8:
Window_help(BUTTON_EFFECTS, "SIEVE");
break;
case 9:
Window_help(BUTTON_EFFECTS, "GRID");
break;
case 10:
Window_help(BUTTON_EFFECTS, "TILING");
break;
default:
Window_help(BUTTON_EFFECTS, NULL);
}
// Hack because we have used Window_get_clicked_button()
Input_sticky_control=0;
//
}
switch (clicked_button)
{
case 1 : // Shade
if (Window_attribute1==LEFT_SIDE)
{
Button_Shade_mode();
Hide_cursor();
Display_effect_states();
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Shade_menu();
clicked_button=11;
}
break;
case 2 : // Quick-shade
if (Window_attribute1==LEFT_SIDE)
{
Button_Quick_shade_mode();
Hide_cursor();
Display_effect_states();
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Quick_shade_menu();
clicked_button=11;
}
break;
case 3 : // Colorize / Transparency
if (Window_attribute1==LEFT_SIDE)
{
Button_Colorize_mode();
Hide_cursor();
Display_effect_states();
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Colorize_menu();
clicked_button=11;
}
break;
case 4 : // Smooth
if (Window_attribute1==LEFT_SIDE)
{
Button_Smooth_mode();
Hide_cursor();
Display_effect_states();
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Smooth_menu();
clicked_button=11;
}
break;
case 5 : // Smear
Button_Smear_mode();
Hide_cursor();
Display_effect_states();
Display_cursor();
break;
case 6 : // Stencil
if (Window_attribute1==LEFT_SIDE)
{
Button_Stencil_mode();
Hide_cursor();
Display_effect_state(176,24,"Stencil",Stencil_mode);
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Stencil_menu();
clicked_button=11;
}
break;
case 7 : // Mask
if (Window_attribute1==LEFT_SIDE)
{
Button_Mask_mode();
Hide_cursor();
Display_effect_state(176,43,"Mask",Mask_mode);
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Mask_menu();
clicked_button=11;
}
break;
case 8 : // Sieve
if (Window_attribute1==LEFT_SIDE)
{
Button_Sieve_mode();
Hide_cursor();
Display_effect_state(176,62,"Sieve",Sieve_mode);
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Sieve_menu();
clicked_button=11;
}
break;
case 9 : // Grid
if (Window_attribute1==LEFT_SIDE)
{
Button_Snap_mode();
Hide_cursor();
Display_effect_state(176,81,"Grid",Snap_mode);
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Grid_menu();
clicked_button=11;
}
break;
case 10 : // Tiling
if (Window_attribute1==LEFT_SIDE)
{
Button_Tiling_mode();
Hide_cursor();
Display_effect_states();
Display_cursor();
}
else
{
Close_window();
Display_cursor();
Button_Tiling_menu();
clicked_button=11;
}
break;
case 11 : // Close
exit_by_close_button=1;
break;
case 12 : // All off
Effects_off();
Hide_cursor();
Display_effect_states();
Display_cursor();
break;
case 13 : // Feedback (pour Colorize et Shade)
Config.FX_Feedback = !Config.FX_Feedback;
Update_FX_feedback(Config.FX_Feedback);
Hide_cursor();
Display_feedback_state();
Display_cursor();
break;
}
}
while (clicked_button!=11);
if (exit_by_close_button)
Close_window();
else
Hide_cursor();
if (!(Shade_mode||Quick_shade_mode||Colorize_mode||Smooth_mode||Tiling_mode||Smear_mode||Stencil_mode||Mask_mode||Sieve_mode||Snap_mode))
Unselect_button(BUTTON_EFFECTS);
Display_cursor();
}
// Callback to display a font name in the list
void Draw_one_font_name(word x, word y, word index, byte highlighted)
{
Print_in_window(x,y,Font_label(index), MC_Black, (highlighted)?MC_Dark:MC_Light);
}
void Button_Text(void)
{
static char str[256]="";
static int font_size=32;
static int antialias=1;
static short list_start=0; // index de le premiere fonte dans le selector
static short cursor_position=0; // index de la ligne active dans le selector
static short selected_font_index=0;
static short is_bold=0;
static short is_italic=0;
byte * new_brush=NULL;
T_Palette text_palette;
int new_width;
int new_height;
int clicked_button;
const int NB_FONTS=8;
char size_buffer[4];
T_Special_button * input_size_button;
T_Special_button * input_text_button;
T_Special_button * preview_button;
T_Special_button * font_list_button;
T_Scroller_button * font_scroller;
T_List_button * font_list;
byte redraw_is_needed=1;
byte preview_is_needed=1;
Open_window(288,180,"Text");
// Texte saisi
Print_in_window(6,20,"Text:",MC_Dark,MC_Light);
input_text_button = Window_set_input_button(48,18,29); // 1
// TrueType options
Window_display_frame_in(182,34,100,68);
Print_in_window(199,31,"TrueType", MC_Dark, MC_Light);
// AA
Window_set_normal_button(188,58,13,11,antialias?"X":" ",0,1,SDLK_a); // 2
Print_in_window(206,60,"AntiAlias", MC_Dark, MC_Light);
// Bold
Window_set_normal_button(188,72,13,11,is_bold?"X":" ",0,1,SDLK_b); // 3
Print_in_window(206,75,"Bold", MC_Dark, MC_Light);
// Italic
Window_set_normal_button(188,86,13,11,is_italic?"X":" ",0,1,SDLK_i); // 4
Print_in_window(206,89,"Italic", MC_Dark, MC_Light);
// Scroller des fontes
font_scroller = Window_set_scroller_button(165,35,NB_FONTS*8,Nb_fonts,NB_FONTS,list_start); // 5
// Liste des fontes disponibles
font_list_button = Window_set_special_button(8,35,152,NB_FONTS*8); // 6
Window_display_frame_in(7, 33, 154, NB_FONTS*8+4);
// Taille texte
input_size_button = Window_set_input_button(220,43,3); // 7
Window_set_repeatable_button(202,43,13,11,"-",0,1,SDLK_LAST); // 8
Window_set_repeatable_button(251,43,13,11,"+",0,1,SDLK_LAST); // 9
// Preview
preview_button = Window_set_special_button(8,106,273,50); // 10
Window_display_frame_in(7, 105, 275, 52);
Window_set_normal_button(8,160,40,14,"OK",0,1,SDLK_RETURN); // 11
Window_set_normal_button(54,160,60,14,"Cancel",0,1,KEY_ESC); // 12
// List of fonts
font_list = Window_set_list_button(font_list_button, font_scroller, Draw_one_font_name, 2); // 13
// Restore its settings from last passage in screen
font_list->List_start = list_start;
font_list->Cursor_position = cursor_position;
Window_redraw_list(font_list);
Update_window_area(0,0,Window_width, Window_height);
// str texte
Window_input_content(input_text_button,str);
// Taille police
redraw_is_needed=1;
// --
while (1)
{
if (redraw_is_needed)
{
// Taille
Num2str(font_size,size_buffer,3);
Window_input_content(input_size_button,size_buffer);
}
if (preview_is_needed)
{
const char * preview_string = "AaBbCcDdEeFf012345";
byte is_truetype;
if (str[0])
preview_string=str;
is_truetype=TrueType_font(selected_font_index);
free(new_brush);
new_brush = Render_text(preview_string, selected_font_index, font_size, antialias, is_bold, is_italic, &new_width, &new_height, text_palette);
// Background:
if (antialias&&is_truetype)
// Solid
Window_rectangle(8, 106, 273, 50,MC_Black);
else if (is_truetype)
{
long l = text_palette[Fore_color].R+text_palette[Fore_color].G+text_palette[Fore_color].B;
Window_rectangle(8, 106, 273, 50,l>128*3? MC_Black:MC_Light);
}
else
{
long l = text_palette[Back_color].R+text_palette[Back_color].G+text_palette[Back_color].B;
Window_rectangle(8, 106, 273, 50,l>128*3? MC_Light:MC_Black);
}
if (new_brush)
{
if (!is_truetype || (is_truetype&&antialias))
{
// Display brush in remapped form.
byte *remapped_brush;
remapped_brush=(byte *)malloc(new_width*new_height);
if (remapped_brush)
{
// This code is mostly copied from Remap_brush()
short x_pos;
short y_pos;
int color;
byte colmap[256];
for (color=0;color<=255;color++)
colmap[color]=0;
for (y_pos=0;y_posPos_X*Menu_factor_X,
Window_pos_Y+preview_button->Pos_Y*Menu_factor_Y,
0,
0,
Min(preview_button->Width*Menu_factor_X, new_width),
Min(preview_button->Height*Menu_factor_Y, new_height),
Back_color,
new_width);
free(remapped_brush);
}
}
else
{
// Solid
Display_brush(
new_brush,
Window_pos_X+preview_button->Pos_X*Menu_factor_X,
Window_pos_Y+preview_button->Pos_Y*Menu_factor_Y,
0,
0,
Min(preview_button->Width*Menu_factor_X, new_width),
Min(preview_button->Height*Menu_factor_Y, new_height),
Back_color,
new_width);
}
}
Update_rect(
Window_pos_X+preview_button->Pos_X*Menu_factor_X,
Window_pos_Y+preview_button->Pos_Y*Menu_factor_Y,
preview_button->Width*Menu_factor_X,
preview_button->Height*Menu_factor_Y);
}
if (redraw_is_needed || preview_is_needed)
{
redraw_is_needed=0;
preview_is_needed=0;
Display_cursor();
}
clicked_button=Window_clicked_button();
if (clicked_button==0)
{
if (Is_shortcut(Key,0x100+BUTTON_HELP))
Window_help(BUTTON_TEXT, NULL);
else if (Is_shortcut(Key,0x100+BUTTON_TEXT))
clicked_button=12;
}
switch(clicked_button)
{
case 1: // Texte saisi
Readline_ex(50,20,str,29,250,INPUT_TYPE_STRING,0);
preview_is_needed=1;
break;
case 2: // AA
antialias = (antialias==0);
Hide_cursor();
Print_in_window(191,60,antialias?"X":" ", MC_Black, MC_Light);
preview_is_needed=1;
break;
case 3: // Bold
is_bold = (is_bold==0);
Hide_cursor();
Print_in_window(191,74,is_bold?"X":" ", MC_Black, MC_Light);
preview_is_needed=1;
break;
case 4: // Italic
is_italic = (is_italic==0);
Hide_cursor();
Print_in_window(191,88,is_italic?"X":" ", MC_Black, MC_Light);
preview_is_needed=1;
break;
case 5: // Scroller des fontes
/* Cannot happen, event is catched by the list control */
break;
case 13: // Font selection
selected_font_index = Window_attribute2;
Hide_cursor();
preview_is_needed=1;
break;
case 7: // Taille du texte (nombre)
Readline(222,45,size_buffer,3,INPUT_TYPE_INTEGER);
font_size=atoi(size_buffer);
// On corrige les dimensions
if (font_size < 1)
{
font_size = 1;
}
else if (font_size>500)
{
font_size = 500;
}
redraw_is_needed=1;
preview_is_needed=1;
break;
case 8: // Taille -
if (font_size > 1)
{
font_size--;
Hide_cursor();
redraw_is_needed=1;
preview_is_needed=1;
}
break;
case 9: // Taille +
if (font_size < 255)
{
font_size++;
Hide_cursor();
redraw_is_needed=1;
preview_is_needed=1;
}
break;
case 6: // Double-click font selector
case 11: // OK
// Save the selector settings
list_start = font_list->List_start;
cursor_position = font_list->Cursor_position;
if (!new_brush)
{
// Si echec de rendu
Close_window();
Unselect_button(BUTTON_TEXT);
Display_cursor();
Error(0);
return;
}
if (Realloc_brush(new_width, new_height, new_brush, NULL))
{
free(new_brush);
Close_window();
Unselect_button(BUTTON_TEXT);
Display_cursor();
Error(0);
}
// Grab palette
memcpy(Brush_original_palette, text_palette,sizeof(T_Palette));
// Remap to image's palette
Remap_brush();
Brush_offset_X=Brush_width>>1;
Brush_offset_Y=Brush_height>>1;
// Fermeture
Close_window();
Unselect_button(BUTTON_TEXT);
// On passe en brosse:
Display_cursor();
if (antialias || !TrueType_font(selected_font_index))
Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
else
Change_paintbrush_shape(PAINTBRUSH_SHAPE_MONO_BRUSH);
// Activate alpha mode
if (antialias && TrueType_font(selected_font_index))
{
Shade_mode=0;
Quick_shade_mode=0;
Smooth_mode=0;
Tiling_mode=0;
Smear_mode=0;
Colorize_mode=1;
Colorize_current_mode=3;
Effect_function=Effect_alpha_colorize;
Draw_menu_button(BUTTON_EFFECTS,BUTTON_PRESSED);
}
Select_button(BUTTON_DRAW,LEFT_SIDE);
if (Config.Auto_discontinuous)
{
// On se place en mode Dessin discontinu la main
while (Current_operation!=OPERATION_DISCONTINUOUS_DRAW)
Select_button(BUTTON_DRAW,RIGHT_SIDE);
}
//Display_cursor();
return;
case 12: // Cancel
// Save the selector settings
list_start = font_list->List_start;
cursor_position = font_list->Cursor_position;
free(new_brush);
new_brush = NULL;
Close_window();
Unselect_button(BUTTON_TEXT);
Display_cursor();
return;
}
}
}
void Display_stored_brush_in_window(word x_pos,word y_pos,int index)
{
if (Brush_container[index].Paintbrush_shape < PAINTBRUSH_SHAPE_MAX)
{
int x,y;
int offset_x=0, offset_y=0;
//int brush_offset_x=0, brush_offset_y=0;
// Determine draw offset (small brushes are stacked on corner of their preview)
if (Brush_container[index].WidthBRUSH_CONTAINER_PREVIEW_WIDTH)
brush_offset_x = (Paintbrush_width-BRUSH_CONTAINER_PREVIEW_WIDTH)/2;
if (Paintbrush_height>BRUSH_CONTAINER_PREVIEW_HEIGHT)
brush_offset_y = (Paintbrush_height-BRUSH_CONTAINER_PREVIEW_HEIGHT)/2;
for (y=0; yBRUSH_CONTAINER_PREVIEW_WIDTH ||
Brush_height>BRUSH_CONTAINER_PREVIEW_HEIGHT)
{
// Scale
Rescale(Brush_original_pixels, Brush_width, Brush_height, (byte *)(Brush_container[index].Thumbnail), BRUSH_CONTAINER_PREVIEW_WIDTH, BRUSH_CONTAINER_PREVIEW_HEIGHT, 0, 0);
}
else
{
// Direct copy
Copy_part_of_image_to_another(Brush_original_pixels, 0,0,Brush_width, Brush_height,Brush_width,(byte *)(Brush_container[index].Thumbnail),0,0,BRUSH_CONTAINER_PREVIEW_WIDTH);
}
}
else
{
Error(0);
}
}
}
/// Retrieve a normal paintbrush
void Select_paintbrush(int index)
{
int x_pos,y_pos;
Paintbrush_shape=Paintbrush[index].Shape;
if (Paintbrush[index].Width<=PAINTBRUSH_WIDTH &&
Paintbrush[index].Height<=PAINTBRUSH_HEIGHT)
{
Paintbrush_width=Paintbrush[index].Width;
Paintbrush_height=Paintbrush[index].Height;
Paintbrush_offset_X=Paintbrush[index].Offset_X;
Paintbrush_offset_Y=Paintbrush[index].Offset_Y;
for (y_pos=0; y_posPAINTBRUSH_WIDTH)
x_off=(Paintbrush_width-PAINTBRUSH_WIDTH)/2;
if (Paintbrush_height>PAINTBRUSH_HEIGHT)
y_off=(Paintbrush_height-PAINTBRUSH_HEIGHT)/2;
for (y_pos=0; y_pos>1;
Paintbrush_offset_Y=Paintbrush_height>>1;
}
else
{
// Recreate the brush pixels from its shape and dimensions
Set_paintbrush_size(Paintbrush_width,Paintbrush_height);
}
}
// Color brushes
if (shape == PAINTBRUSH_SHAPE_COLOR_BRUSH ||
shape == PAINTBRUSH_SHAPE_MONO_BRUSH)
{
Paintbrush_shape=shape;
if (!Realloc_brush(Brush_container[index].Width,Brush_container[index].Height,NULL,NULL))
{
// Recover pixels
memcpy(Brush_original_pixels, Brush_container[index].Brush, (long)Brush_height*Brush_width);
// Grab palette
memcpy(Brush_original_palette, Brush_container[index].Palette, sizeof(T_Palette));
// Recover colormap
memcpy(Brush_colormap, Brush_container[index].Colormap, 256);
// Remap using current colormap
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
Brush_offset_X=Brush_width>>1;
Brush_offset_Y=Brush_height>>1;
}
}
Change_paintbrush_shape(shape);
return 1;
}
void Button_Brush_container(void)
{
short clicked_button;
short x_pos,y_pos;
byte index;
Open_window(BRUSH_CONTAINER_COLUMNS*(BRUSH_CONTAINER_PREVIEW_WIDTH+8)+8,
BRUSH_CONTAINER_ROWS*(BRUSH_CONTAINER_PREVIEW_HEIGHT+8)+40,
"Brushes");
Window_set_normal_button(
(BRUSH_CONTAINER_COLUMNS*(BRUSH_CONTAINER_PREVIEW_WIDTH+8)-59)/2,
(BRUSH_CONTAINER_ROWS)*(BRUSH_CONTAINER_PREVIEW_HEIGHT+8)+18,
67,14,"Cancel",0,1,KEY_ESC); // 1
index=0;
for (index=0; index < BRUSH_CONTAINER_ROWS*BRUSH_CONTAINER_COLUMNS; index++)
{
x_pos = (index % BRUSH_CONTAINER_COLUMNS)*(BRUSH_CONTAINER_PREVIEW_WIDTH+8)+7;
y_pos = (index / BRUSH_CONTAINER_COLUMNS)*(BRUSH_CONTAINER_PREVIEW_HEIGHT+8)+18;
Window_set_normal_button(
x_pos,
y_pos,
BRUSH_CONTAINER_PREVIEW_WIDTH+2,
BRUSH_CONTAINER_PREVIEW_HEIGHT+2,
"",0,1,SDLK_LAST);
Display_stored_brush_in_window(x_pos+1, y_pos+1, index);
}
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
clicked_button=Window_clicked_button();
//if (Is_shortcut(Key,0x100+BUTTON_HELP))
// Window_help(BUTTON_PAINTBRUSHES, NULL);
if (clicked_button == 1)
break;
if (clicked_button>1)
{
index = clicked_button-2;
if (Window_attribute1==RIGHT_SIDE)
{
// Store
x_pos = (index % BRUSH_CONTAINER_COLUMNS)*(BRUSH_CONTAINER_PREVIEW_WIDTH+8)+7;
y_pos = (index / BRUSH_CONTAINER_COLUMNS)*(BRUSH_CONTAINER_PREVIEW_HEIGHT+8)+18;
Store_brush(index);
Hide_cursor();
Display_stored_brush_in_window(x_pos+1, y_pos+1, index);
Display_cursor();
}
else
{
// Restore and exit
if (Restore_brush(index))
break;
}
}
}
while (1);
Close_window();
//Unselect_button(BUTTON_PAINTBRUSHES);
Display_cursor();
}
grafx2/src/buttons_effects.c 0000644 0000764 0001040 00000106657 11521112356 016576 0 ustar vig Administrator /* 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
*/
////////////////////////////////////////////////////////////////////////////
///@file buttons_effects.c
/// Handles all the effects buttons and setup windows in the effects menu.
////////////////////////////////////////////////////////////////////////////
#include
#include
#include
#include "buttons.h"
#include "engine.h"
#include "global.h"
#include "graph.h"
#include "help.h"
#include "input.h"
#include "misc.h"
#include "readline.h"
#include "sdlscreen.h"
#include "struct.h"
#include "windows.h"
#include "brush.h"
//---------- Menu dans lequel on tagge des couleurs (genre Stencil) ----------
void Menu_tag_colors(char * window_title, byte * table, byte * mode, byte can_cancel, const char *help_section, word close_shortcut)
{
short clicked_button;
byte backup_table[256];
word index;
word old_mouse_x;
word old_mouse_y;
byte old_mouse_k;
byte tagged_color;
byte color;
byte click;
Open_window(176,150,window_title);
Window_set_palette_button(6,38); // 1
Window_set_normal_button( 7, 19,78,14,"Clear" ,1,1,SDLK_c); // 2
Window_set_normal_button(91, 19,78,14,"Invert",1,1,SDLK_i); // 3
if (can_cancel)
{
Window_set_normal_button(91,129,78,14,"OK" ,0,1,SDLK_RETURN); // 4
Window_set_normal_button( 7,129,78,14,"Cancel",0,1,KEY_ESC); // 5
// On enregistre la table dans un backup au cas o on ferait Cancel
memcpy(backup_table,table,256);
}
else
Window_set_normal_button(49,129,78,14,"OK" ,0,1,SDLK_RETURN); // 4
// On affiche l'tat actuel de la table
for (index=0; index<=255; index++)
Stencil_tag_color(index, (table[index])?MC_Black:MC_Light);
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
old_mouse_x=Mouse_X;
old_mouse_y=Mouse_Y;
old_mouse_k=Mouse_K;
clicked_button=Window_clicked_button();
switch (clicked_button)
{
case 0 :
break;
case -1 :
case 1 : // Palette
if ( (Mouse_X!=old_mouse_x) || (Mouse_Y!=old_mouse_y) || (Mouse_K!=old_mouse_k) )
{
Hide_cursor();
tagged_color=(clicked_button==1) ? Window_attribute2 : Read_pixel(Mouse_X,Mouse_Y);
table[tagged_color]=(Mouse_K==LEFT_SIDE);
Stencil_tag_color(tagged_color,(Mouse_K==LEFT_SIDE)?MC_Black:MC_Light);
Display_cursor();
Stencil_update_color(tagged_color);
}
break;
case 2 : // Clear
memset(table,0,256);
Hide_cursor();
for (index=0; index<=255; index++)
Stencil_tag_color(index,MC_Light);
Display_cursor();
Update_window_area(0,0,Window_width, Window_height);
break;
case 3 : // Invert
Hide_cursor();
for (index=0; index<=255; index++)
Stencil_tag_color(index,(table[index]^=1)?MC_Black:MC_Light);
Display_cursor();
Update_window_area(0,0,Window_width, Window_height);
}
if (!Mouse_K)
switch (Key)
{
case SDLK_BACKQUOTE : // Rcupration d'une couleur derrire le menu
case SDLK_COMMA :
Get_color_behind_window(&color,&click);
if (click)
{
Hide_cursor();
tagged_color=color;
table[tagged_color]=(click==LEFT_SIDE);
Stencil_tag_color(tagged_color,(click==LEFT_SIDE)?MC_Black:MC_Light);
Stencil_update_color(tagged_color);
Display_cursor();
Wait_end_of_click();
}
Key=0;
break;
default:
if (Is_shortcut(Key,0x100+BUTTON_HELP))
{
Window_help(BUTTON_EFFECTS, help_section);
Key=0;
break;
}
else if (Is_shortcut(Key,close_shortcut))
{
clicked_button=4;
}
}
}
while (clicked_button<4);
Close_window();
if (clicked_button==5) // Cancel
memcpy(table,backup_table,256);
else // OK
*mode=1;
Display_cursor();
}
//--------------------------------- Stencil ----------------------------------
void Button_Stencil_mode(void)
{
Stencil_mode=!Stencil_mode;
}
void Stencil_tag_color(byte color, byte tag_color)
{
Block(Window_pos_X+(Menu_factor_X*(Window_palette_button_list->Pos_X+4+(color >> 4)*10)),
Window_pos_Y+(Menu_factor_Y*(Window_palette_button_list->Pos_Y+3+(color & 15)* 5)),
Menu_factor_X<<1,Menu_factor_Y*5,tag_color);
}
void Stencil_update_color(byte color)
{
Update_rect(Window_pos_X+(Menu_factor_X*(Window_palette_button_list->Pos_X+4+(color >> 4)*10)),
Window_pos_Y+(Menu_factor_Y*(Window_palette_button_list->Pos_Y+3+(color & 15)* 5)),
Menu_factor_X<<1,Menu_factor_Y*5);
}
void Button_Stencil_menu(void)
{
Menu_tag_colors("Stencil",Stencil,&Stencil_mode,1, "STENCIL", SPECIAL_STENCIL_MENU);
}
//--------------------------------- Masque -----------------------------------
void Button_Mask_mode(void)
{
Mask_mode=!Mask_mode;
}
void Button_Mask_menu(void)
{
Menu_tag_colors("Mask",Mask_table,&Mask_mode,1, "MASK", SPECIAL_MASK_MENU);
}
// -------------------------------- Grille -----------------------------------
void Button_Snap_mode(void)
{
Hide_cursor();
Snap_mode=!Snap_mode;
Compute_paintbrush_coordinates();
Display_cursor();
}
void Button_Grid_menu(void)
{
short clicked_button;
word chosen_X =Snap_width;
word chosen_Y =Snap_height;
short dx_selected=Snap_offset_X;
short dy_selected=Snap_offset_Y;
char showgrid = Show_grid;
// if grid is shown check if we snap
// if not snap by default (so the window work like before we introduced the "show" option)
char snapgrid = Show_grid?Snap_mode:1;
T_Special_button * input_x_button;
T_Special_button * input_y_button;
T_Special_button * input_dx_button;
T_Special_button * input_dy_button;
char str[3];
Open_window(133,118,"Grid");
Window_set_normal_button(12,92,51,14,"Cancel",0,1,KEY_ESC); // 1
Window_set_normal_button(70,92,51,14,"OK" ,0,1,SDLK_RETURN); // 2
Print_in_window(19,26, "X:",MC_Dark,MC_Light);
input_x_button = Window_set_input_button(37,24,2); // 3
Num2str(chosen_X,str,2);
Window_input_content(input_x_button,str);
Print_in_window(19,47, "Y:",MC_Dark,MC_Light);
input_y_button = Window_set_input_button(37,45,2); // 4
Num2str(chosen_Y,str,2);
Window_input_content(input_y_button,str);
Print_in_window(69,26,"dX:",MC_Dark,MC_Light);
input_dx_button = Window_set_input_button(95,24,2); // 5
Num2str(dx_selected,str,2);
Window_input_content(input_dx_button,str);
Print_in_window(69,47,"dY:",MC_Dark,MC_Light);
input_dy_button = Window_set_input_button(95,45,2); // 6
Num2str(dy_selected,str,2);
Window_set_normal_button(12, 62, 14, 14, " ", 0, 1, 0); // 7
Window_set_normal_button(70, 62, 14, 14, " ", 0, 1, 0); // 8
if (snapgrid)
Print_in_window(16, 65, "X", MC_Black, MC_Light);
if (Show_grid)
Print_in_window(74, 65, "X", MC_Black, MC_Light);
Print_in_window(32, 65,"Snap",MC_Dark,MC_Light);
Print_in_window(90, 65,"Show",MC_Dark,MC_Light);
Window_input_content(input_dy_button,str);
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
clicked_button=Window_clicked_button();
switch (clicked_button)
{
case 3 :
Num2str(chosen_X,str,2);
Readline(39,26,str,2,INPUT_TYPE_INTEGER);
chosen_X=atoi(str);
// On corrige les dimensions
if ((!chosen_X) || (chosen_X>80))
{
if (!chosen_X)
chosen_X=1;
else
chosen_X=80;
Num2str(chosen_X,str,2);
Window_input_content(input_x_button,str);
}
if (dx_selected>=chosen_X)
{
dx_selected=chosen_X-1;
Num2str(dx_selected,str,2);
Window_input_content(input_dx_button,str);
}
Display_cursor();
break;
case 4 :
Num2str(chosen_Y,str,2);
Readline(39,47,str,2,INPUT_TYPE_INTEGER);
chosen_Y=atoi(str);
// On corrige les dimensions
if ((!chosen_Y) || (chosen_Y>80))
{
if (!chosen_Y)
chosen_Y=1;
else
chosen_Y=80;
Num2str(chosen_Y,str,2);
Window_input_content(input_y_button,str);
}
if (dy_selected>=chosen_Y)
{
dy_selected=chosen_Y-1;
Num2str(dy_selected,str,2);
Window_input_content(input_dy_button,str);
}
Display_cursor();
break;
case 5 :
Num2str(dx_selected,str,2);
Readline(97,26,str,2,INPUT_TYPE_INTEGER);
dx_selected=atoi(str);
// On corrige les dimensions
if (dx_selected>79)
dx_selected=79;
if (dx_selected>=chosen_X)
dx_selected=chosen_X-1;
Num2str(dx_selected,str,2);
Window_input_content(input_dx_button,str);
Display_cursor();
break;
case 6 :
Num2str(dy_selected,str,2);
Readline(97,47,str,2,INPUT_TYPE_INTEGER);
dy_selected=atoi(str);
// On corrige les dimensions
if (dy_selected>79)
dy_selected=79;
if (dy_selected>=chosen_Y)
dy_selected=chosen_Y-1;
Num2str(dy_selected,str,2);
Window_input_content(input_dy_button,str);
Display_cursor();
case 7:
snapgrid = !snapgrid;
Hide_cursor();
Print_in_window(16, 65, snapgrid?"X":" ", MC_Black, MC_Light);
Display_cursor();
break;
case 8:
showgrid = !showgrid;
Hide_cursor();
Print_in_window(74, 65, showgrid?"X":" ", MC_Black, MC_Light);
Display_cursor();
break;
}
if (Is_shortcut(Key,0x100+BUTTON_HELP))
Window_help(BUTTON_EFFECTS, "GRID");
}
while ( (clicked_button!=1) && (clicked_button!=2) );
if (clicked_button==2) // OK
{
Snap_width=chosen_X;
Snap_height=chosen_Y;
Snap_offset_X=dx_selected;
Snap_offset_Y=dy_selected;
Snap_mode=snapgrid;
Show_grid=showgrid;
}
Close_window();
Display_cursor();
}
void Button_Show_grid(void)
{
Show_grid = !Show_grid;
Hide_cursor();
Display_all_screen();
Display_cursor();
}
// -- Mode Smooth -----------------------------------------------------------
void Button_Smooth_mode(void)
{
if (Smooth_mode)
Effect_function=No_effect;
else
{
Effect_function=Effect_smooth;
Shade_mode=0;
Quick_shade_mode=0;
Colorize_mode=0;
Tiling_mode=0;
Smear_mode=0;
}
Smooth_mode=!Smooth_mode;
}
byte Smooth_default_matrices[4][3][3]=
{
{ {1,2,1}, {2,4,2}, {1,2,1} },
{ {1,3,1}, {3,9,3}, {1,3,1} },
{ {0,1,0}, {1,2,1}, {0,1,0} },
{ {2,3,2}, {3,1,3}, {2,3,2} }
};
void Button_Smooth_menu(void)
{
short clicked_button;
word x,y,i,j;
byte chosen_matrix[3][3];
T_Special_button * matrix_input[3][3];
char str[3];
Open_window(142,109,"Smooth");
Window_set_normal_button(82,59,53,14,"Cancel",0,1,KEY_ESC); // 1
Window_set_normal_button(82,88,53,14,"OK" ,0,1,SDLK_RETURN); // 2
Window_display_frame(6,17,130,37);
for (x=11,y=0; y<4; x+=31,y++)
{
Window_set_normal_button(x,22,27,27,"",0,1,SDLK_LAST); // 3,4,5,6
for (j=0; j<3; j++)
for (i=0; i<3; i++)
Print_char_in_window(x+2+(i<<3),24+(j<<3),'0'+Smooth_default_matrices[y][i][j],MC_Black,MC_Light);
}
Window_display_frame(6,58, 69,45);
for (j=0; j<3; j++)
for (i=0; i<3; i++)
{
matrix_input[i][j]=Window_set_input_button(10+(i*21),62+(j*13),2); // 7..15
chosen_matrix[i][j] = Smooth_matrix[i][j] ;
Num2str(chosen_matrix[i][j], str, 2);
Window_input_content(matrix_input[i][j],str);
}
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
clicked_button=Window_clicked_button();
if (clicked_button>2)
{
if (clicked_button<=6)
{
memcpy(chosen_matrix,Smooth_default_matrices[clicked_button-3],sizeof(chosen_matrix));
Hide_cursor();
for (j=0; j<3; j++)
for (i=0; i<3; i++)
{
Num2str(chosen_matrix[i][j],str,2);
Window_input_content(matrix_input[i][j],str);
}
Display_cursor();
}
else
{
i=clicked_button-7; x=i%3; y=i/3;
Num2str(chosen_matrix[x][y],str,2);
Readline(matrix_input[x][y]->Pos_X+2,
matrix_input[x][y]->Pos_Y+2,
str,2,INPUT_TYPE_INTEGER);
chosen_matrix[x][y]=atoi(str);
Display_cursor();
}
}
if (Is_shortcut(Key,0x100+BUTTON_HELP))
Window_help(BUTTON_EFFECTS, "SMOOTH");
else if (Is_shortcut(Key,SPECIAL_SMOOTH_MENU))
clicked_button=2;
}
while ((clicked_button!=1) && (clicked_button!=2));
Close_window();
if (clicked_button==2) // OK
{
memcpy(Smooth_matrix,chosen_matrix,sizeof(Smooth_matrix));
Smooth_mode=0; // On le met 0 car la fonct suivante va le passer 1
Button_Smooth_mode();
}
Display_cursor();
}
// -- Mode Smear ------------------------------------------------------------
void Button_Smear_mode(void)
{
if (!Smear_mode)
{
if (!Colorize_mode)
Effect_function=No_effect;
Shade_mode=0;
Quick_shade_mode=0;
Smooth_mode=0;
Tiling_mode=0;
}
Smear_mode=!Smear_mode;
}
// -- Mode Colorize ---------------------------------------------------------
void Compute_colorize_table(void)
{
word index;
word factor_a;
word factor_b;
factor_a=256*(100-Colorize_opacity)/100;
factor_b=256*( Colorize_opacity)/100;
for (index=0;index<256;index++)
{
Factors_table[index]=index*factor_a;
Factors_inv_table[index]=index*factor_b;
}
}
void Button_Colorize_mode(void)
{
if (Colorize_mode)
Effect_function=No_effect;
else
{
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=!Colorize_mode;
}
void Button_Colorize_display_selection(int mode)
{
short y_pos=0; // Ligne o afficher les flches de slection
// On commence par effacer les anciennes slections:
// Partie gauche
Print_in_window(4,37," ",MC_Black,MC_Light);
Print_in_window(4,57," ",MC_Black,MC_Light);
Print_in_window(4,74," ",MC_Black,MC_Light);
Print_in_window(4,91," ",MC_Black,MC_Light);
// Partie droite
Print_in_window(129,37," ",MC_Black,MC_Light);
Print_in_window(129,57," ",MC_Black,MC_Light);
Print_in_window(129,74," ",MC_Black,MC_Light);
Print_in_window(129,91," ",MC_Black,MC_Light);
// Ensuite, on affiche la flche l o il le faut:
switch(mode)
{
case 0 : // Mthode interpole
y_pos=37;
break;
case 1 : // Mthode additive
y_pos=57;
break;
case 2 : // Mthode soustractive
y_pos=74;
break;
case 3 : // Mthode alpha
y_pos=91;
}
Print_in_window(4,y_pos,"\020",MC_Black,MC_Light);
Print_in_window(129,y_pos,"\021",MC_Black,MC_Light);
}
void Button_Colorize_menu(void)
{
short chosen_opacity;
short selected_mode;
short clicked_button;
char str[4];
Open_window(140,135,"Transparency");
Print_in_window(16,23,"Opacity:",MC_Dark,MC_Light);
Window_set_input_button(87,21,3); // 1
Print_in_window(117,23,"%",MC_Dark,MC_Light);
Window_set_normal_button(16,34,108,14,"Interpolate",1,1,SDLK_i); // 2
Window_display_frame(12,18,116,34);
Window_set_normal_button(16,54,108,14,"Additive" ,2,1,SDLK_d); // 3
Window_set_normal_button(16,71,108,14,"Subtractive",1,1,SDLK_s); // 4
Window_set_normal_button(16,88,108,14,"Alpha",1,1,SDLK_a); // 4
Window_set_normal_button(16,111, 51,14,"Cancel" ,0,1,KEY_ESC); // 5
Window_set_normal_button(73,111, 51,14,"OK" ,0,1,SDLK_RETURN); // 6
Num2str(Colorize_opacity,str,3);
Window_input_content(Window_special_button_list,str);
Button_Colorize_display_selection(Colorize_current_mode);
chosen_opacity=Colorize_opacity;
selected_mode =Colorize_current_mode;
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
clicked_button=Window_clicked_button();
switch(clicked_button)
{
case 1: // Zone de saisie de l'opacit
Num2str(chosen_opacity,str,3);
Readline(89,23,str,3,INPUT_TYPE_INTEGER);
chosen_opacity=atoi(str);
// On corrige le pourcentage
if (chosen_opacity>100)
{
chosen_opacity=100;
Num2str(chosen_opacity,str,3);
Window_input_content(Window_special_button_list,str);
}
Display_cursor();
break;
case 2: // Interpolated method
case 3: // Additive method
case 4: // Substractive method
case 5: // Alpha method
selected_mode=clicked_button-2;
Hide_cursor();
Button_Colorize_display_selection(selected_mode);
Display_cursor();
}
if (Is_shortcut(Key,0x100+BUTTON_HELP))
Window_help(BUTTON_EFFECTS, "TRANSPARENCY");
else if (Is_shortcut(Key,SPECIAL_COLORIZE_MENU))
clicked_button=7;
}
while (clicked_button<6);
Close_window();
if (clicked_button==7) // OK
{
Colorize_opacity =chosen_opacity;
Colorize_current_mode=selected_mode;
Compute_colorize_table();
Colorize_mode=0; // On le met 0 car la fonct suivante va le passer 1
Button_Colorize_mode();
}
Display_cursor();
}
// -- Mode Tiling -----------------------------------------------------------
void Button_Tiling_mode(void)
{
if (Tiling_mode)
Effect_function=No_effect;
else
{
Effect_function=Effect_tiling;
Shade_mode=0;
Quick_shade_mode=0;
Colorize_mode=0;
Smooth_mode=0;
Smear_mode=0;
}
Tiling_mode=!Tiling_mode;
}
void Button_Tiling_menu(void)
{
short clicked_button;
short chosen_offset_x=Tiling_offset_X;
short chosen_offset_y=Tiling_offset_Y;
char str[5];
T_Special_button * input_offset_x_button;
T_Special_button * input_offset_y_button;
Open_window(138,79,"Tiling");
Window_set_normal_button(13,55,51,14,"Cancel",0,1,KEY_ESC); // 1
Window_set_normal_button(74,55,51,14,"OK" ,0,1,SDLK_RETURN); // 2
input_offset_x_button = Window_set_input_button(91,21,4); // 3
input_offset_y_button = Window_set_input_button(91,35,4); // 4
Print_in_window(12,23,"Offset X:",MC_Dark,MC_Light);
Print_in_window(12,37,"Offset Y:",MC_Dark,MC_Light);
Num2str(Tiling_offset_X,str,4);
Window_input_content(input_offset_x_button,str);
Num2str(Tiling_offset_Y,str,4);
Window_input_content(input_offset_y_button,str);
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
clicked_button=Window_clicked_button();
if (clicked_button==3) // Zone de saisie du dcalage X
{
Num2str(chosen_offset_x,str,4);
Readline(93,23,str,4,INPUT_TYPE_INTEGER);
chosen_offset_x=atoi(str);
// On corrige le dcalage en X
if (chosen_offset_x>=Brush_width)
{
chosen_offset_x=Brush_width-1;
Num2str(chosen_offset_x,str,4);
Window_input_content(input_offset_x_button,str);
}
Display_cursor();
}
else
if (clicked_button==4) // Zone de saisie du dcalage Y
{
Num2str(chosen_offset_y,str,4);
Readline(93,37,str,4,INPUT_TYPE_INTEGER);
chosen_offset_y=atoi(str);
// On corrige le dcalage en Y
if (chosen_offset_y>=Brush_height)
{
chosen_offset_y=Brush_height-1;
Num2str(chosen_offset_y,str,4);
Window_input_content(input_offset_y_button,str);
}
Display_cursor();
}
if (Is_shortcut(Key,0x100+BUTTON_HELP))
Window_help(BUTTON_EFFECTS, "TILING");
}
while ( (clicked_button!=1) && (clicked_button!=2) );
Close_window();
if (clicked_button==2) // OK
{
Tiling_offset_X=chosen_offset_x;
Tiling_offset_Y=chosen_offset_y;
if (!Tiling_mode)
Button_Tiling_mode();
}
Display_cursor();
}
// -- All modes off ---------------------------------------------------------
void Effects_off(void)
{
Effect_function=No_effect;
Shade_mode=0;
Quick_shade_mode=0;
Colorize_mode=0;
Smooth_mode=0;
Tiling_mode=0;
Smear_mode=0;
Stencil_mode=0;
Mask_mode=0;
Sieve_mode=0;
Snap_mode=0;
}
// -- Mode Sieve (Sieve) ----------------------------------------------------
void Button_Sieve_mode(void)
{
Sieve_mode=!Sieve_mode;
}
void Draw_sieve_scaled(short origin_x, short origin_y)
{
short x_pos;
short y_pos;
short x_size;
short y_size;
short start_x=Window_pos_X+(Menu_factor_X*230);
short start_y=Window_pos_Y+(Menu_factor_Y*78);
x_size=Menu_factor_X*5; // |_ Taille d'une case
y_size=Menu_factor_Y*5; // | de la trame zoome
// On efface de contenu prcdent
Block(origin_x,origin_y,
Menu_factor_X*Window_special_button_list->Width,
Menu_factor_Y*Window_special_button_list->Height,MC_Light);
for (y_pos=0; y_posSieve_pattern[index][j&0xF]>>(15-(i&0xF)))&1)?MC_White:MC_Black);
Update_rect(ToWinX(10),ToWinY(22),ToWinL(12*23+16),ToWinH(16));
}
void Copy_preset_sieve(byte index)
{
short i,j;
for (j=0; j<16; j++)
for (i=0; i<16; i++)
Sieve[i][j]=(Gfx->Sieve_pattern[index][j]>>(15-i))&1;
Sieve_width=16;
Sieve_height=16;
}
void Invert_trame(void)
{
byte x_pos,y_pos;
for (y_pos=0; y_pos plus grande
short preview_y_end; // | rapidit.
memcpy(old_sieve,Sieve,256);
Open_window(290,179,"Sieve");
preview_x_start=Window_pos_X+(Menu_factor_X*230);
preview_y_start=Window_pos_Y+(Menu_factor_Y*78);
preview_x_end=preview_x_start+(Menu_factor_X*51);
preview_y_end=preview_y_start+(Menu_factor_Y*71);
Window_display_frame ( 7, 65,130,43);
Window_display_frame ( 7,110,130,43);
Window_display_frame_in(142, 68, 82,82);
Window_display_frame_in(229, 77, 53,73);
Print_in_window(228, 68,"Preview",MC_Dark,MC_Light);
Print_in_window( 27, 83,"Scroll" ,MC_Dark,MC_Light);
Print_in_window( 23,120,"Width:" ,MC_Dark,MC_Light);
Print_in_window( 15,136,"Height:",MC_Dark,MC_Light);
Window_set_special_button(143,69,80,80); // 1
Window_set_normal_button(175,157,51,14,"Cancel",0,1,KEY_ESC); // 2
Window_set_normal_button(230,157,51,14,"OK" ,0,1,SDLK_RETURN); // 3
Window_set_normal_button( 8,157,51,14,"Clear" ,1,1,SDLK_c); // 4
Window_set_normal_button( 63,157,51,14,"Invert",1,1,SDLK_i); // 5
Window_set_normal_button( 8,46,131,14,"Get from brush" ,1,1,SDLK_g); // 6
Window_set_normal_button(142,46,139,14,"Transfer to brush",1,1,SDLK_t); // 7
Window_set_normal_button(109,114,11,11,"\030",0,1,SDLK_UP|MOD_SHIFT); // 8
Window_set_normal_button(109,138,11,11,"\031",0,1,SDLK_DOWN|MOD_SHIFT); // 9
Window_set_normal_button( 97,126,11,11,"\033",0,1,SDLK_LEFT|MOD_SHIFT); // 10
Window_set_normal_button(121,126,11,11,"\032",0,1,SDLK_RIGHT|MOD_SHIFT); // 11
button_bg_color = Window_set_normal_button(109,126,11,11,"" ,0,1,SDLK_INSERT); // 12
Block(Window_pos_X+(Menu_factor_X*(button_bg_color->Pos_X+2)),
Window_pos_Y+(Menu_factor_Y*(button_bg_color->Pos_Y+2)),
Menu_factor_X*7, Menu_factor_Y*7, (default_bg_color)?MC_White:MC_Black);
Window_set_repeatable_button(109, 69,11,11,"\030",0,1,SDLK_UP); // 13
Window_set_repeatable_button(109, 93,11,11,"\031",0,1,SDLK_DOWN); // 14
Window_set_repeatable_button( 97, 81,11,11,"\033",0,1,SDLK_LEFT); // 15
Window_set_repeatable_button(121, 81,11,11,"\032",0,1,SDLK_RIGHT); // 16
for (index=0; index<12; index++)
Window_set_normal_button((index*23)+8,20,20,20,"",0,1,SDLK_F1+index); // 17 -> 28
Draw_preset_sieve_patterns();
origin_x=Window_pos_X+(Menu_factor_X*Window_special_button_list->Pos_X);
origin_y=Window_pos_Y+(Menu_factor_Y*Window_special_button_list->Pos_Y);
Num2str(Sieve_width,str,2);
Print_in_window(71,120,str,MC_Black,MC_Light);
Num2str(Sieve_height,str,2);
Print_in_window(71,136,str,MC_Black,MC_Light);
Draw_sieve_scaled(origin_x,origin_y);
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
clicked_button=Window_clicked_button();
origin_x=Window_pos_X+(Menu_factor_X*Window_special_button_list->Pos_X);
origin_y=Window_pos_Y+(Menu_factor_Y*Window_special_button_list->Pos_Y);
switch (clicked_button)
{
case -1 :
case 0 :
break;
case 1 : // Zone de dessin de la trame
/* // Version qui n'accepte pas les clicks sur la grille
x_pos=(Mouse_X-origin_x)/Menu_factor_X;
y_pos=(Mouse_Y-origin_y)/Menu_factor_Y;
if ( (x_pos%5<4) && (y_pos%5<4) )
{
x_pos/=5;
y_pos/=5;
if ( (x_pos16)?16:Brush_width;
Sieve_height=(Brush_height>16)?16:Brush_height;
for (y_pos=0; y_pos>1);
Brush_offset_Y=(Brush_height>>1);
Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
break;
case 8 : // Rduire hauteur
if (Sieve_height>1)
{
Hide_cursor();
Sieve_height--;
Num2str(Sieve_height,str,2);
Print_in_window(71,136,str,MC_Black,MC_Light);
Draw_sieve_scaled(origin_x,origin_y);
Display_cursor();
Update_sieve_area(origin_x, origin_y);
}
break;
case 9 : // Agrandir hauteur
if (Sieve_height<16)
{
Hide_cursor();
for (index=0; index1)
{
Hide_cursor();
Sieve_width--;
Num2str(Sieve_width,str,2);
Print_in_window(71,120,str,MC_Black,MC_Light);
Draw_sieve_scaled(origin_x,origin_y);
Display_cursor();
Update_sieve_area(origin_x, origin_y);
}
break;
case 11 : // Agrandir largeur
if (Sieve_width<16)
{
Hide_cursor();
for (index=0; indexPos_X+2)),
Window_pos_Y+(Menu_factor_Y*(button_bg_color->Pos_Y+2)),
Menu_factor_X*7, Menu_factor_Y*7, (default_bg_color)?MC_White:MC_Black);
Display_cursor();
Update_rect(
Window_pos_X+(Menu_factor_X*(button_bg_color->Pos_X+2)),
Window_pos_Y+(Menu_factor_Y*(button_bg_color->Pos_Y+2)),
Menu_factor_X*7,
Menu_factor_Y*7);
break;
case 13 : // Scroll vers le haut
Hide_cursor();
for (x_pos=0; x_pos0; y_pos--)
Sieve[x_pos][y_pos]=Sieve[x_pos][y_pos-1];
Sieve[x_pos][0]=temp;
}
Draw_sieve_scaled(origin_x,origin_y);
Display_cursor();
Update_sieve_area(origin_x, origin_y);
break;
case 15 : // Scroll vers la gauche
Hide_cursor();
for (y_pos=0; y_pos0; x_pos--)
Sieve[x_pos][y_pos]=Sieve[x_pos-1][y_pos];
Sieve[0][y_pos]=temp;
}
Draw_sieve_scaled(origin_x,origin_y);
Display_cursor();
Update_sieve_area(origin_x, origin_y);
break;
default : // Boutons de trames prdfinies
Hide_cursor();
Copy_preset_sieve(clicked_button-17);
Draw_sieve_scaled(origin_x,origin_y);
Num2str(Sieve_width,str,2);
Print_in_window(71,120,str,MC_Black,MC_Light);
Num2str(Sieve_height,str,2);
Print_in_window(71,136,str,MC_Black,MC_Light);
Draw_sieve_scaled(origin_x,origin_y);
Display_cursor();
Update_sieve_area(origin_x, origin_y);
}
if (Is_shortcut(Key,0x100+BUTTON_HELP))
{
Key=0;
Window_help(BUTTON_EFFECTS, "SIEVE");
}
}
while ( (clicked_button!=2) && (clicked_button!=3) );
Close_window();
if (clicked_button==2) // Cancel
{
Sieve_width=old_sieve_width;
Sieve_height=old_sieve_height;
memcpy(Sieve,old_sieve,256);
}
if ( (clicked_button==3) && (!Sieve_mode) ) // OK
Button_Sieve_mode();
Display_cursor();
}
grafx2/src/engine.c 0000644 0000764 0001040 00000335254 11545652460 014656 0 ustar vig Administrator /* 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
*/
/// @file engine.c: Window engine and interface management
#include
#include
#include
#include "const.h"
#include "struct.h"
#include "global.h"
#include "graph.h"
#include "misc.h"
#include "special.h"
#include "buttons.h"
#include "operatio.h"
#include "shade.h"
#include "errors.h"
#include "sdlscreen.h"
#include "windows.h"
#include "brush.h"
#include "input.h"
#include "engine.h"
#include "pages.h"
#include "layers.h"
#include "factory.h"
#include "loadsave.h"
#include "io.h"
// we need this as global
short Old_MX = -1;
short Old_MY = -1;
//---------- Annuler les effets des modes de dessin (sauf la grille) ---------
// Variables mmorisants les anciens effets
byte Shade_mode_before_cancel;
byte Quick_shade_mode_before_cancel;
byte Stencil_mode_before_cancel;
byte Sieve_mode_before_cancel;
byte Colorize_mode_before_cancel;
byte Smooth_mode_before_cancel;
byte Tiling_mode_before_cancel;
Func_effect Effect_function_before_cancel;
///This table holds pointers to the saved window backgrounds. We can have up to 8 windows open at a time.
byte* Window_background[8];
///Table of tooltip texts for menu buttons
char * Menu_tooltip[NB_BUTTONS]=
{
"Hide toolbars / Select ",
"Layers manager ",
"Get/Set transparent col.",
"Merge layer ",
"Add layer ",
"Drop layer ",
"Raise layer ",
"Lower layer ",
"Layer select / toggle ",
"Paintbrush choice ",
"Adjust / Transform menu ",
"Freehand draw. / Toggle ",
"Splines / Toggle ",
"Lines / Toggle ",
"Spray / Menu ",
"Floodfill / Replace col.",
"Polylines / Polyforms ",
"Polyfill / Filled Pforms",
"Empty rectangles ",
"Filled rectangles ",
"Empty circles / ellipses",
"Filled circles / ellips.",
"Grad. rect / Grad. menu ",
"Grad. spheres / ellipses",
"Brush grab. / Restore ",
"Lasso / Restore brush ",
#ifdef __ENABLE_LUA__
"Brush effects / factory ",
#else
"Brush effects ",
#endif
"Drawing modes (effects) ",
"Text ",
"Magnify mode / Menu ",
"Pipette / Invert colors ",
"Screen size / Safe. res.",
"Go / Copy to other page ",
"Save as / Save ",
"Load / Re-load ",
"Settings / Skins ",
"Clear / with backcolor ",
"Help / Statistics ",
"Undo / Redo ",
"Kill current page ",
"Quit ",
"Palette editor / setup ",
"Scroll pal. bkwd / Fast ",
"Scroll pal. fwd / Fast ",
"Color #" ,
};
///Save a screen block (usually before erasing it with a new window or a dropdown menu)
void Save_background(byte **buffer, int x_pos, int y_pos, int width, int height)
{
int index;
if(*buffer != NULL) DEBUG("WARNING : buffer already allocated !!!",0);
*buffer=(byte *) malloc(width*Menu_factor_X*height*Menu_factor_Y*Pixel_width);
if(*buffer==NULL) Error(0);
for (index=0; index<(height*Menu_factor_Y); index++)
Read_line(x_pos,y_pos+index,width*Menu_factor_X,(*buffer)+((int)index*width*Menu_factor_X*Pixel_width));
}
///Restores a screen block
void Restore_background(byte *buffer, int x_pos, int y_pos, int width, int height)
{
int index;
for (index=0; index= Menu_Y+Menu_factor_Y*(Menu_bars[current_menu].Top) &&
Mouse_Y < Menu_Y+Menu_factor_Y*(Menu_bars[current_menu].Top + Menu_bars[current_menu].Height))
break;
}
}
if (current_menu==MENUBAR_COUNT)
return -1;
y_pos=(Mouse_Y - Menu_Y)/Menu_factor_Y - Menu_bars[current_menu].Top;
if (current_menu == 0) first_button = 0;
else first_button = Menu_bars[current_menu - 1].Last_button_index + 1;
for (btn_number=first_button;btn_number<=Menu_bars[current_menu].Last_button_index;btn_number++)
{
switch(Buttons_Pool[btn_number].Shape)
{
case BUTTON_SHAPE_NO_FRAME :
case BUTTON_SHAPE_RECTANGLE :
if ((x_pos>=Buttons_Pool[btn_number].X_offset) &&
(y_pos>=Buttons_Pool[btn_number].Y_offset) &&
(x_pos<=Buttons_Pool[btn_number].X_offset+Buttons_Pool[btn_number].Width) &&
(y_pos<=Buttons_Pool[btn_number].Y_offset+Buttons_Pool[btn_number].Height))
return btn_number;
break;
case BUTTON_SHAPE_TRIANGLE_TOP_LEFT:
if ((x_pos>=Buttons_Pool[btn_number].X_offset) &&
(y_pos>=Buttons_Pool[btn_number].Y_offset) &&
(x_pos+y_pos-(short)Buttons_Pool[btn_number].Y_offset-(short)Buttons_Pool[btn_number].X_offset<=Buttons_Pool[btn_number].Width))
return btn_number;
break;
case BUTTON_SHAPE_TRIANGLE_BOTTOM_RIGHT:
if ((x_pos<=Buttons_Pool[btn_number].X_offset+Buttons_Pool[btn_number].Width) &&
(y_pos<=Buttons_Pool[btn_number].Y_offset+Buttons_Pool[btn_number].Height) &&
(x_pos+y_pos-(short)Buttons_Pool[btn_number].Y_offset-(short)Buttons_Pool[btn_number].X_offset>=Buttons_Pool[btn_number].Width))
return btn_number;
break;
}
}
return -1;
}
///Draw a menu button, selected or not
void Draw_menu_button(byte btn_number,byte pressed)
{
word start_x;
word start_y;
word width;
word height;
byte * bitmap;
word bitmap_width;
word x_pos;
word y_pos;
byte current_menu;
byte color;
signed char icon;
// Find in which menu the button is
for (current_menu = 0; current_menu < MENUBAR_COUNT; current_menu++)
{
// We found the right bar !
if (Menu_bars[current_menu].Last_button_index >= btn_number &&
(current_menu==0 || Menu_bars[current_menu -1].Last_button_index < btn_number))
{
break;
}
}
start_x = Buttons_Pool[btn_number].X_offset;
start_y = Buttons_Pool[btn_number].Y_offset;
width = Buttons_Pool[btn_number].Width+1;
height = Buttons_Pool[btn_number].Height+1;
icon = Buttons_Pool[btn_number].Icon;
if (icon==-1)
{
// Standard button
bitmap_width = Menu_bars[current_menu].Skin_width;
bitmap=&(Menu_bars[current_menu].Skin[pressed][start_y*Menu_bars[current_menu].Skin_width+start_x]);
}
else
{
// From Menu_buttons
bitmap_width = MENU_SPRITE_WIDTH;
bitmap=Gfx->Menu_sprite[pressed][(byte)icon][0];
// For bottom right: offset +1,+1
if (Buttons_Pool[btn_number].Shape==BUTTON_SHAPE_TRIANGLE_BOTTOM_RIGHT)
bitmap += MENU_SPRITE_WIDTH+1;
}
switch(Buttons_Pool[btn_number].Shape)
{
case BUTTON_SHAPE_NO_FRAME :
break;
case BUTTON_SHAPE_RECTANGLE :
for (y_pos=0;y_posPages);
flimit = Find_last_slash(Drop_file_name);
*(flimit++) = '\0';
Hide_cursor();
old_cursor_shape=Cursor_shape;
Cursor_shape=CURSOR_SHAPE_HOURGLASS;
Display_cursor();
Init_context_layered_image(&context, flimit, Drop_file_name);
Load_image(&context);
if (File_error!=1)
{
Compute_limits();
Compute_paintbrush_coordinates();
Redraw_layered_image();
End_of_modification();
Display_all_screen();
Main_image_is_modified=0;
}
Destroy_context(&context);
Compute_optimal_menu_colors(Main_palette);
Display_menu();
if (Config.Display_image_limits)
Display_image_limits();
Hide_cursor();
Cursor_shape=old_cursor_shape;
Display_all_screen();
Display_cursor();
}
free(Drop_file_name);
Drop_file_name=NULL;
}
if(Get_input(0))
{
action = 0;
// Inhibit all keys if a drawing operation is in progress.
// We make an exception for the freehand operations, but these will
// only accept a very limited number of shortcuts.
if (Operation_stack_size!=0 && !Allow_color_change_during_operation)
Key=0;
// Evenement de fermeture
if (Quit_is_required)
{
Quit_is_required=0;
Button_Quit();
}
if (Key)
{
effect_modified = 0;
for (key_index=SPECIAL_CLICK_RIGHT+1;key_index>2));
else
Scroll_screen(0,-(Screen_height>>3));
action++;
break;
case SPECIAL_SCROLL_DOWN : // Scroll down
if (Main_magnifier_mode)
Scroll_magnifier(0,(Main_magnifier_height>>2));
else
Scroll_screen(0,(Screen_height>>3));
action++;
break;
case SPECIAL_SCROLL_LEFT : // Scroll left
if (Main_magnifier_mode)
Scroll_magnifier(-(Main_magnifier_width>>2),0);
else
Scroll_screen(-(Screen_width>>3),0);
action++;
break;
case SPECIAL_SCROLL_RIGHT : // Scroll right
if (Main_magnifier_mode)
Scroll_magnifier((Main_magnifier_width>>2),0);
else
Scroll_screen((Screen_width>>3),0);
action++;
break;
case SPECIAL_SCROLL_UP_FAST : // Scroll up faster
if (Main_magnifier_mode)
Scroll_magnifier(0,-(Main_magnifier_height>>1));
else
Scroll_screen(0,-(Screen_height>>2));
action++;
break;
case SPECIAL_SCROLL_DOWN_FAST : // Scroll down faster
if (Main_magnifier_mode)
Scroll_magnifier(0,(Main_magnifier_height>>1));
else
Scroll_screen(0,(Screen_height>>2));
action++;
break;
case SPECIAL_SCROLL_LEFT_FAST : // Scroll left faster
if (Main_magnifier_mode)
Scroll_magnifier(-(Main_magnifier_width>>1),0);
else
Scroll_screen(-(Screen_width>>2),0);
action++;
break;
case SPECIAL_SCROLL_RIGHT_FAST : // Scroll right faster
if (Main_magnifier_mode)
Scroll_magnifier((Main_magnifier_width>>1),0);
else
Scroll_screen((Screen_width>>2),0);
action++;
break;
case SPECIAL_SCROLL_UP_SLOW : // Scroll up slower
if (Main_magnifier_mode)
Scroll_magnifier(0,-1);
else
Scroll_screen(0,-1);
action++;
break;
case SPECIAL_SCROLL_DOWN_SLOW : // Scroll down slower
if (Main_magnifier_mode)
Scroll_magnifier(0,1);
else
Scroll_screen(0,1);
action++;
break;
case SPECIAL_SCROLL_LEFT_SLOW : // Scroll left slower
if (Main_magnifier_mode)
Scroll_magnifier(-1,0);
else
Scroll_screen(-1,0);
action++;
break;
case SPECIAL_SCROLL_RIGHT_SLOW : // Scroll right slower
if (Main_magnifier_mode)
Scroll_magnifier(1,0);
else
Scroll_screen(1,0);
action++;
break;
case SPECIAL_SHOW_HIDE_CURSOR : // Show / Hide cursor
Hide_cursor();
Cursor_hidden=!Cursor_hidden;
Display_cursor();
action++;
break;
case SPECIAL_DOT_PAINTBRUSH : // Paintbrush = "."
Hide_cursor();
Paintbrush_shape=PAINTBRUSH_SHAPE_ROUND;
Set_paintbrush_size(1,1);
Change_paintbrush_shape(PAINTBRUSH_SHAPE_ROUND);
Display_cursor();
action++;
break;
case SPECIAL_CONTINUOUS_DRAW : // Continuous freehand drawing
Select_button(BUTTON_DRAW,LEFT_SIDE);
// ATTENTION CE TRUC EST MOCHE ET VA MERDER SI ON SE MET A UTILISER DES BOUTONS POPUPS
while (Current_operation!=OPERATION_CONTINUOUS_DRAW)
Select_button(BUTTON_DRAW,RIGHT_SIDE);
action++;
break;
case SPECIAL_FLIP_X : // Flip X
Hide_cursor();
Flip_X_lowlevel(Brush_original_pixels, Brush_width, Brush_height);
// Remap according to the last used remap table
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
Display_cursor();
action++;
break;
case SPECIAL_FLIP_Y : // Flip Y
Hide_cursor();
Flip_Y_lowlevel(Brush_original_pixels, Brush_width, Brush_height);
// Remap according to the last used remap table
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
Display_cursor();
action++;
break;
case SPECIAL_ROTATE_90 : // 90 brush rotation
Hide_cursor();
Rotate_90_deg();
Display_cursor();
action++;
break;
case SPECIAL_ROTATE_180 : // 180 brush rotation
Hide_cursor();
Rotate_180_deg_lowlevel(Brush, Brush_width, Brush_height);
// Remap according to the last used remap table
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
Display_cursor();
action++;
break;
case SPECIAL_STRETCH : // Stretch brush
Hide_cursor();
Start_operation_stack(OPERATION_STRETCH_BRUSH);
Display_cursor();
action++;
break;
case SPECIAL_DISTORT : // Distort brush
Hide_cursor();
Start_operation_stack(OPERATION_DISTORT_BRUSH);
Display_cursor();
action++;
break;
case SPECIAL_ROTATE_ANY_ANGLE : // Rotate brush by any angle
Hide_cursor();
Start_operation_stack(OPERATION_ROTATE_BRUSH);
Display_cursor();
action++;
break;
case SPECIAL_BRUSH_DOUBLE:
if (Paintbrush_shape==PAINTBRUSH_SHAPE_COLOR_BRUSH
|| Paintbrush_shape==PAINTBRUSH_SHAPE_MONO_BRUSH)
{
Hide_cursor();
Stretch_brush(1,1,Brush_width*2,Brush_height*2);
Display_cursor();
}
action++;
break;
case SPECIAL_BRUSH_DOUBLE_WIDTH:
if (Paintbrush_shape==PAINTBRUSH_SHAPE_COLOR_BRUSH
|| Paintbrush_shape==PAINTBRUSH_SHAPE_MONO_BRUSH)
{
Hide_cursor();
Stretch_brush(1,1,Brush_width*2,Brush_height);
Display_cursor();
}
action++;
break;
case SPECIAL_BRUSH_DOUBLE_HEIGHT:
if (Paintbrush_shape==PAINTBRUSH_SHAPE_COLOR_BRUSH
|| Paintbrush_shape==PAINTBRUSH_SHAPE_MONO_BRUSH)
{
Hide_cursor();
Stretch_brush(1,1,Brush_width,Brush_height*2);
Display_cursor();
}
action++;
break;
case SPECIAL_BRUSH_HALVE:
if (Paintbrush_shape==PAINTBRUSH_SHAPE_COLOR_BRUSH
|| Paintbrush_shape==PAINTBRUSH_SHAPE_MONO_BRUSH)
{
Hide_cursor();
Stretch_brush(1,1,Brush_width/2,Brush_height/2);
Display_cursor();
}
action++;
break;
case SPECIAL_OUTLINE : // Outline brush
Hide_cursor();
Outline_brush();
Display_cursor();
action++;
break;
case SPECIAL_NIBBLE : // Nibble brush
Hide_cursor();
Nibble_brush();
Display_cursor();
action++;
break;
case SPECIAL_GET_BRUSH_COLORS : // Get colors from brush
Get_colors_from_brush();
action++;
break;
case SPECIAL_RECOLORIZE_BRUSH : // Recolorize brush
Hide_cursor();
Remap_brush();
Display_cursor();
action++;
break;
case SPECIAL_LOAD_BRUSH :
Load_picture(0);
action++;
break;
case SPECIAL_SAVE_BRUSH :
Save_picture(0);
action++;
break;
case SPECIAL_ZOOM_IN : // Zoom in
Zoom(+1);
action++;
break;
case SPECIAL_ZOOM_OUT : // Zoom out
Zoom(-1);
action++;
break;
case SPECIAL_CENTER_ATTACHMENT : // Center brush attachment
Hide_cursor();
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
Display_cursor();
action++;
break;
case SPECIAL_TOP_LEFT_ATTACHMENT : // Top-left brush attachment
Hide_cursor();
Brush_offset_X=0;
Brush_offset_Y=0;
Display_cursor();
action++;
break;
case SPECIAL_TOP_RIGHT_ATTACHMENT : // Top-right brush attachment
Hide_cursor();
Brush_offset_X=(Brush_width-1);
Brush_offset_Y=0;
Display_cursor();
action++;
break;
case SPECIAL_BOTTOM_LEFT_ATTACHMENT : // Bottom-left brush attachment
Hide_cursor();
Brush_offset_X=0;
Brush_offset_Y=(Brush_height-1);
Display_cursor();
action++;
break;
case SPECIAL_BOTTOM_RIGHT_ATTACHMENT : // Bottom right brush attachment
Hide_cursor();
Brush_offset_X=(Brush_width-1);
Brush_offset_Y=(Brush_height-1);
Display_cursor();
action++;
break;
case SPECIAL_EXCLUDE_COLORS_MENU : // Exclude colors menu
Menu_tag_colors("Tag colors to exclude",Exclude_color,&temp,1, NULL, SPECIAL_EXCLUDE_COLORS_MENU);
action++;
break;
case SPECIAL_INVERT_SIEVE :
Invert_trame();
action++;
break;
case SPECIAL_SHADE_MODE :
Button_Shade_mode();
effect_modified = 1;
action++;
break;
case SPECIAL_SHADE_MENU :
Button_Shade_menu();
effect_modified = 1;
action++;
break;
case SPECIAL_QUICK_SHADE_MODE :
Button_Quick_shade_mode();
effect_modified = 1;
action++;
break;
case SPECIAL_QUICK_SHADE_MENU :
Button_Quick_shade_menu();
effect_modified = 1;
action++;
break;
case SPECIAL_STENCIL_MODE :
Button_Stencil_mode();
effect_modified = 1;
action++;
break;
case SPECIAL_STENCIL_MENU :
Button_Stencil_menu();
effect_modified = 1;
action++;
break;
case SPECIAL_MASK_MODE :
Button_Mask_mode();
effect_modified = 1;
action++;
break;
case SPECIAL_MASK_MENU :
Button_Mask_menu();
effect_modified = 1;
action++;
break;
case SPECIAL_GRID_MODE :
Button_Snap_mode();
effect_modified = 1;
action++;
break;
case SPECIAL_GRID_MENU :
Button_Grid_menu();
effect_modified = 1;
action++;
break;
case SPECIAL_SHOW_GRID :
Button_Show_grid();
effect_modified = 1;
action++;
break;
case SPECIAL_SIEVE_MODE :
Button_Sieve_mode();
effect_modified = 1;
action++;
break;
case SPECIAL_SIEVE_MENU :
Button_Sieve_menu();
effect_modified = 1;
action++;
break;
case SPECIAL_COLORIZE_MODE :
Button_Colorize_mode();
effect_modified = 1;
action++;
break;
case SPECIAL_COLORIZE_MENU :
Button_Colorize_menu();
effect_modified = 1;
action++;
break;
case SPECIAL_SMOOTH_MODE :
Button_Smooth_mode();
effect_modified = 1;
action++;
break;
case SPECIAL_SMOOTH_MENU :
Button_Smooth_menu();
effect_modified = 1;
action++;
break;
case SPECIAL_SMEAR_MODE :
Button_Smear_mode();
effect_modified = 1;
action++;
break;
case SPECIAL_TILING_MODE :
Button_Tiling_mode();
effect_modified = 1;
action++;
break;
case SPECIAL_TILING_MENU :
effect_modified = 1;
Button_Tiling_menu();
action++;
break;
case SPECIAL_EFFECTS_OFF :
Effects_off();
effect_modified = 1;
action++;
break;
case SPECIAL_TRANSPARENCY_1 :
Transparency_set(1);
effect_modified = 1;
action++;
break;
case SPECIAL_TRANSPARENCY_2 :
Transparency_set(2);
effect_modified = 1;
action++;
break;
case SPECIAL_TRANSPARENCY_3 :
Transparency_set(3);
effect_modified = 1;
action++;
break;
case SPECIAL_TRANSPARENCY_4 :
Transparency_set(4);
effect_modified = 1;
action++;
break;
case SPECIAL_TRANSPARENCY_5 :
Transparency_set(5);
effect_modified = 1;
action++;
break;
case SPECIAL_TRANSPARENCY_6 :
Transparency_set(6);
effect_modified = 1;
action++;
break;
case SPECIAL_TRANSPARENCY_7 :
Transparency_set(7);
effect_modified = 1;
action++;
break;
case SPECIAL_TRANSPARENCY_8 :
Transparency_set(8);
effect_modified = 1;
action++;
break;
case SPECIAL_TRANSPARENCY_9 :
Transparency_set(9);
effect_modified = 1;
action++;
break;
case SPECIAL_TRANSPARENCY_0 :
Transparency_set(0);
effect_modified = 1;
action++;
break;
case SPECIAL_ZOOM_1 :
Zoom_set(-1);
action++;
break;
case SPECIAL_ZOOM_2 :
Zoom_set(0);
action++;
break;
case SPECIAL_ZOOM_3 :
Zoom_set(1);
action++;
break;
case SPECIAL_ZOOM_4 :
Zoom_set(2);
action++;
break;
case SPECIAL_ZOOM_5 :
Zoom_set(3);
action++;
break;
case SPECIAL_ZOOM_6 :
Zoom_set(4);
action++;
break;
case SPECIAL_ZOOM_8 :
Zoom_set(5);
action++;
break;
case SPECIAL_ZOOM_10 :
Zoom_set(6);
action++;
break;
case SPECIAL_ZOOM_12 :
Zoom_set(7);
action++;
break;
case SPECIAL_ZOOM_14 :
Zoom_set(8);
action++;
break;
case SPECIAL_ZOOM_16 :
Zoom_set(9);
action++;
break;
case SPECIAL_ZOOM_18 :
Zoom_set(10);
action++;
break;
case SPECIAL_ZOOM_20 :
Zoom_set(11);
action++;
break;
case SPECIAL_LAYER1_SELECT:
case SPECIAL_LAYER2_SELECT:
case SPECIAL_LAYER3_SELECT:
case SPECIAL_LAYER4_SELECT:
case SPECIAL_LAYER5_SELECT:
case SPECIAL_LAYER6_SELECT:
case SPECIAL_LAYER7_SELECT:
case SPECIAL_LAYER8_SELECT:
Layer_activate((key_index-SPECIAL_LAYER1_SELECT)/2, LEFT_SIDE);
action++;
break;
case SPECIAL_LAYER1_TOGGLE:
case SPECIAL_LAYER2_TOGGLE:
case SPECIAL_LAYER3_TOGGLE:
case SPECIAL_LAYER4_TOGGLE:
case SPECIAL_LAYER5_TOGGLE:
case SPECIAL_LAYER6_TOGGLE:
case SPECIAL_LAYER7_TOGGLE:
case SPECIAL_LAYER8_TOGGLE:
Layer_activate((key_index-SPECIAL_LAYER1_TOGGLE)/2, RIGHT_SIDE);
action++;
break;
case SPECIAL_REPEAT_SCRIPT:
#ifdef __ENABLE_LUA__
Repeat_script();
action++;
#endif
break;
case SPECIAL_RUN_SCRIPT_1:
case SPECIAL_RUN_SCRIPT_2:
case SPECIAL_RUN_SCRIPT_3:
case SPECIAL_RUN_SCRIPT_4:
case SPECIAL_RUN_SCRIPT_5:
case SPECIAL_RUN_SCRIPT_6:
case SPECIAL_RUN_SCRIPT_7:
case SPECIAL_RUN_SCRIPT_8:
case SPECIAL_RUN_SCRIPT_9:
case SPECIAL_RUN_SCRIPT_10:
#ifdef __ENABLE_LUA__
Run_numbered_script(key_index-SPECIAL_RUN_SCRIPT_1);
action++;
#endif
break;
case SPECIAL_CYCLE_MODE:
Cycling_mode= !Cycling_mode;
// Restore palette
if (!Cycling_mode)
Set_palette(Main_palette);
action++;
break;
}
}
} // End of special keys
// Shortcut for clicks of Menu buttons.
// Disable all of them when an operation is in progress
if (Operation_stack_size==0)
{
// Some functions open windows that clear the Key variable,
// so we need to use a temporary replacement.
key_pressed = Key;
for (button_index=0;button_index=Menu_Y) ||
( (Main_magnifier_mode) && (Mouse_X>=Main_separator_position) &&
(Mouse_XHover_effect && prev_button_number > -1 && !Buttons_Pool[prev_button_number].Pressed)
Draw_menu_button(prev_button_number, BUTTON_RELEASED);
*/
Block(18*Menu_factor_X,Menu_status_Y,192*Menu_factor_X,Menu_factor_Y<<3,MC_Light);
Update_rect(18*Menu_factor_X,Menu_status_Y,192*Menu_factor_X,Menu_factor_Y<<3);
Display_cursor();
}
}
else
{
if ( (prev_button_number!=BUTTON_CHOOSE_COL)
|| (temp_color!=First_color_in_palette)
|| (Old_MX!=Mouse_X) || (Old_MY!=Mouse_Y) )
{
// Le curseur est sur un nouveau bouton
if (button_index!=BUTTON_CHOOSE_COL)
{
Hide_cursor();
/*if (Gfx->Hover_effect && prev_button_number > -1 && !Buttons_Pool[prev_button_number].Pressed)
Draw_menu_button(prev_button_number, BUTTON_RELEASED);
*/
Print_in_menu(Menu_tooltip[button_index],0);
/*if (Gfx->Hover_effect && !Buttons_Pool[button_index].Pressed)
Draw_menu_button(button_index, BUTTON_HIGHLIGHTED);
*/
Display_cursor();
}
else
{ // Le curseur est-il sur une couleur de la palette?
int color;
if ((color=Pick_color_in_palette())!=-1)
{
Hide_cursor();
Status_print_palette_color(color);
Display_cursor();
}
else
{
if ( (Old_MX!=Mouse_X) || (Old_MY!=Mouse_Y) )
{
Hide_cursor();
Block(18*Menu_factor_X,Menu_status_Y,192*Menu_factor_X,Menu_factor_Y<<3,MC_Light);
Update_rect(18*Menu_factor_X,Menu_status_Y,192*Menu_factor_X,8*Menu_factor_Y);
Display_cursor();
}
}
}
}
}
}
prev_button_number=button_index;
// Gestion des clicks
if (Mouse_K)
{
if (Mouse_Y>=Menu_Y)
{
if (button_index>=0)
{
Select_button(button_index,Mouse_K);
prev_button_number=-1;
}
}
else
if (Main_magnifier_mode) Move_separator();
}
}
// we need to refresh that one as we may come from a sub window
Cursor_in_menu=(Mouse_Y>=Menu_Y) ||
( (Main_magnifier_mode) && (Mouse_X>=Main_separator_position) &&
(Mouse_XHover_effect && prev_button_number > -1 && !Buttons_Pool[prev_button_number].Pressed)
Draw_menu_button(prev_button_number, BUTTON_RELEASED);
*/
if ( (Current_operation!=OPERATION_COLORPICK) && (Current_operation!=OPERATION_REPLACE) )
{
Print_in_menu("X: Y: ",0);
}
else
{
Print_in_menu("X: Y: ( )",0);
}
Display_cursor();
Cursor_in_menu_previous = 0;
}
}
if(Cursor_in_menu)
{
Cursor_in_menu_previous = 1;
}
else
{
blink=Operation[Current_operation][Mouse_K_unique][Operation_stack_size].Hide_cursor;
if (blink) Hide_cursor();
Operation[Current_operation][Mouse_K_unique][Operation_stack_size].Action();
if (blink) Display_cursor();
}
Old_MX=Mouse_X;
Old_MY=Mouse_Y;
}
while (!Quitting);
}
//////////////////////////////////////////////////////////////////////////////
// diffrentes fonctions d'affichage utilises dans les fentres //
//////////////////////////////////////////////////////////////////////////////
//----------------------- Tracer une fentre d'options -----------------------
void Open_window(word width,word height, const char * title)
// Lors de l'appel cette procdure, la souris doit tre affiche.
// En sortie de cette procedure, la souris est efface.
{
//word i,j;
size_t title_length;
Hide_cursor();
/*if (Windows_open == 0 && Gfx->Hover_effect)
{
if (Cursor_in_menu)
{
int button_index=Button_under_mouse();
if (button_index > -1 && !Buttons_Pool[button_index].Pressed)
Draw_menu_button(button_index, BUTTON_RELEASED);
}
}*/
Windows_open++;
Window_width=width;
Window_height=height;
// Positionnement de la fentre
Window_pos_X=(Screen_width-(width*Menu_factor_X))>>1;
Window_pos_Y=(Screen_height-(height*Menu_factor_Y))>>1;
Window_draggable=1;
// Sauvegarde de ce que la fentre remplace
Save_background(&(Window_background[Windows_open-1]), Window_pos_X, Window_pos_Y, width, height);
// Fentre grise
Block(Window_pos_X+(Menu_factor_X<<1),Window_pos_Y+(Menu_factor_Y<<1),(width-4)*Menu_factor_X,(height-4)*Menu_factor_Y,MC_Window);
// -- Frame de la fentre ----- --- -- - -
// Frame noir puis en relief
Window_display_frame_mono(0,0,width,height,MC_Black);
Window_display_frame_out(1,1,width-2,height-2);
// Barre sous le titre
Block(Window_pos_X+(Menu_factor_X<<3),Window_pos_Y+(11*Menu_factor_Y),(width-16)*Menu_factor_X,Menu_factor_Y,MC_Dark);
Block(Window_pos_X+(Menu_factor_X<<3),Window_pos_Y+(12*Menu_factor_Y),(width-16)*Menu_factor_X,Menu_factor_Y,MC_White);
title_length = strlen(title);
if (title_length+2 > width/8)
title_length = width/8-2;
Print_in_window_limited((width-(title_length<<3))>>1,3,title,title_length,MC_Black,MC_Light);
if (Windows_open == 1)
{
Menu_is_visible_before_window=Menu_is_visible;
Menu_is_visible=0;
Menu_Y_before_window=Menu_Y;
Menu_Y=Screen_height;
Cursor_shape_before_window=Cursor_shape;
Cursor_shape=CURSOR_SHAPE_ARROW;
Paintbrush_hidden_before_window=Paintbrush_hidden;
Paintbrush_hidden=1;
if (Allow_colorcycling)
{
Allow_colorcycling=0;
// Restore palette
Set_palette(Main_palette);
}
Allow_drag_and_drop(0);
}
// Initialisation des listes de boutons de la fentre
Window_normal_button_list =NULL;
Window_palette_button_list =NULL;
Window_scroller_button_list=NULL;
Window_special_button_list =NULL;
Window_dropdown_button_list=NULL;
Window_nb_buttons =0;
}
//----------------------- Fermer une fentre d'options -----------------------
void Close_window(void)
// Lors de l'appel cette procedure, la souris doit tre affiche.
// En sortie de cette procedure, la souris est efface.
{
T_Normal_button * temp1;
T_Palette_button * temp2;
T_Scroller_button * temp3;
T_Special_button * temp4;
T_Dropdown_button * temp5;
T_List_button * temp6;
Hide_cursor();
while (Window_normal_button_list)
{
temp1=Window_normal_button_list->Next;
free(Window_normal_button_list);
Window_normal_button_list=temp1;
}
while (Window_palette_button_list)
{
temp2=Window_palette_button_list->Next;
free(Window_palette_button_list);
Window_palette_button_list=temp2;
}
while (Window_scroller_button_list)
{
temp3=Window_scroller_button_list->Next;
free(Window_scroller_button_list);
Window_scroller_button_list=temp3;
}
while (Window_special_button_list)
{
temp4=Window_special_button_list->Next;
free(Window_special_button_list);
Window_special_button_list=temp4;
}
while (Window_dropdown_button_list)
{
temp5=Window_dropdown_button_list->Next;
Window_dropdown_clear_items(Window_dropdown_button_list);
free(Window_dropdown_button_list);
Window_dropdown_button_list=temp5;
}
while (Window_list_button_list)
{
temp6=Window_list_button_list->Next;
free(Window_list_button_list);
Window_list_button_list=temp6;
}
if (Windows_open != 1)
{
// Restore de ce que la fentre cachait
Restore_background(Window_background[Windows_open-1], Window_pos_X, Window_pos_Y, Window_width, Window_height);
Window_background[Windows_open-1]=NULL;
Update_rect(Window_pos_X,Window_pos_Y,Window_width*Menu_factor_X,Window_height*Menu_factor_Y);
Windows_open--;
}
else
{
free(Window_background[Windows_open-1]);
Window_background[Windows_open-1]=NULL;
Windows_open--;
Paintbrush_hidden=Paintbrush_hidden_before_window;
Compute_paintbrush_coordinates();
Menu_Y=Menu_Y_before_window;
Menu_is_visible=Menu_is_visible_before_window;
Cursor_shape=Cursor_shape_before_window;
Display_all_screen();
Display_menu();
Allow_colorcycling=1;
Allow_drag_and_drop(1);
}
Key=0;
Mouse_K=0;
Old_MX = -1;
Old_MY = -1;
}
//---------------- Dessiner un bouton normal dans une fentre ----------------
void Window_draw_normal_bouton(word x_pos,word y_pos,word width,word height,
const char * title,byte undersc_letter,byte clickable)
{
byte title_color;
word text_x_pos,text_y_pos;
if (clickable)
{
Window_display_frame_out(x_pos,y_pos,width,height);
Window_display_frame_generic(x_pos-1,y_pos-1,width+2,height+2,MC_Black,MC_Black,MC_Dark,MC_Dark,MC_Dark);
title_color=MC_Black;
}
else
{
Window_display_frame_out(x_pos,y_pos,width,height);
Window_display_frame_mono(x_pos-1,y_pos-1,width+2,height+2,MC_Light);
title_color=MC_Dark;
}
text_x_pos=x_pos+( (width-(strlen(title)<<3)+1) >>1 );
text_y_pos=y_pos+((height-7)>>1);
Print_in_window(text_x_pos,text_y_pos,title,title_color,MC_Light);
if (undersc_letter)
Block(Window_pos_X+((text_x_pos+((undersc_letter-1)<<3))*Menu_factor_X),
Window_pos_Y+((text_y_pos+8)*Menu_factor_Y),
Menu_factor_X<<3,Menu_factor_Y,MC_Dark);
}
// -- Button normal enfonc dans la fentre --
void Window_select_normal_button(word x_pos,word y_pos,word width,word height)
{
Window_display_frame_generic(x_pos,y_pos,width,height,MC_Dark,MC_Black,MC_Dark,MC_Dark,MC_Black);
Update_rect(Window_pos_X+x_pos*Menu_factor_X, Window_pos_Y+y_pos*Menu_factor_Y, width*Menu_factor_X, height*Menu_factor_Y);
}
// -- Button normal dsenfonc dans la fentre --
void Window_unselect_normal_button(word x_pos,word y_pos,word width,word height)
{
Window_display_frame_out(x_pos,y_pos,width,height);
Update_rect(Window_pos_X+x_pos*Menu_factor_X, Window_pos_Y+y_pos*Menu_factor_Y, width*Menu_factor_X, height*Menu_factor_Y);
}
//--------------- Dessiner un bouton palette dans une fentre ----------------
void Window_draw_palette_bouton(word x_pos,word y_pos)
{
word color;
for (color=0; color<=255; color++)
Block( Window_pos_X+((((color >> 4)*10)+x_pos+6)*Menu_factor_X),Window_pos_Y+((((color & 15)*5)+y_pos+3)*Menu_factor_Y),Menu_factor_X*5,Menu_factor_Y*5,color);
Window_display_frame(x_pos,y_pos,164,86);
}
// -------------------- Effacer les TAGs sur les palette ---------------------
// Cette fonct ne sert plus que lorsqu'on efface les tags dans le menu Spray.
void Window_clear_tags(void)
{
word origin_x;
word origin_y;
word x_pos;
word window_x_pos;
//word window_y_pos;
origin_x=Window_pos_X+(Window_palette_button_list->Pos_X+3)*Menu_factor_X;
origin_y=Window_pos_Y+(Window_palette_button_list->Pos_Y+3)*Menu_factor_Y;
for (x_pos=0,window_x_pos=origin_x;x_pos<16;x_pos++,window_x_pos+=(Menu_factor_X*10))
Block(window_x_pos,origin_y,Menu_factor_X*3,Menu_factor_Y*80,MC_Light);
Update_rect(origin_x,origin_y,ToWinL(160),ToWinH(80));
}
// ---- Tracer les TAGs sur les palettes du menu Palette ou du menu Shade ----
void Tag_color_range(byte start,byte end)
{
word origin_x;
word origin_y;
//word x_pos;
word y_pos;
//word window_x_pos;
word window_y_pos;
word index;
// On efface les anciens TAGs
for (index=0;index<=start;index++)
Window_rectangle(Window_palette_button_list->Pos_X+3+((index>>4)*10),
Window_palette_button_list->Pos_Y+3+((index&15)* 5),
3,5,MC_Light);
for (index=end;index<256;index++)
Window_rectangle(Window_palette_button_list->Pos_X+3+((index>>4)*10),
Window_palette_button_list->Pos_Y+3+((index&15)* 5),
3,5,MC_Light);
// On affiche le 1er TAG
origin_x=(Window_palette_button_list->Pos_X+3)+(start>>4)*10;
origin_y=(Window_palette_button_list->Pos_Y+3)+(start&15)* 5;
for (y_pos=0,window_y_pos=origin_y ;y_pos<5;y_pos++,window_y_pos++)
Pixel_in_window(origin_x ,window_y_pos,MC_Black);
for (y_pos=0,window_y_pos=origin_y+1;y_pos<3;y_pos++,window_y_pos++)
Pixel_in_window(origin_x+1,window_y_pos,MC_Black);
Pixel_in_window(origin_x+2,origin_y+2,MC_Black);
if (start!=end)
{
// On complte le 1er TAG
Pixel_in_window(origin_x+1,origin_y+4,MC_Black);
// On affiche le 2me TAG
origin_x=(Window_palette_button_list->Pos_X+3)+(end>>4)*10;
origin_y=(Window_palette_button_list->Pos_Y+3)+(end&15)* 5;
for (y_pos=0,window_y_pos=origin_y; y_pos<5; y_pos++,window_y_pos++)
Pixel_in_window(origin_x ,window_y_pos,MC_Black);
for (y_pos=0,window_y_pos=origin_y; y_pos<4; y_pos++,window_y_pos++)
Pixel_in_window(origin_x+1,window_y_pos,MC_Black);
Pixel_in_window(origin_x+2,origin_y+2,MC_Black);
// On TAG toutes les couleurs intermdiaires
for (index=start+1;indexPos_X+3+((index>>4)*10),
Window_palette_button_list->Pos_Y+3+((index&15)* 5),
2,5,MC_Black);
// On efface l'ventuelle pointe d'une ancienne extrmit de l'intervalle
Pixel_in_window(Window_palette_button_list->Pos_X+5+((index>>4)*10),
Window_palette_button_list->Pos_Y+5+((index&15)* 5),
MC_Light);
}
}
Update_window_area(Window_palette_button_list->Pos_X+3,Window_palette_button_list->Pos_Y+3,12*16,5*16);
}
//------------------ Dessiner un scroller dans une fentre -------------------
void Compute_slider_cursor_length(T_Scroller_button * button)
{
if (button->Nb_elements>button->Nb_visibles)
{
button->Cursor_length=(button->Nb_visibles*(button->Length-24))/button->Nb_elements;
if (!(button->Cursor_length))
button->Cursor_length=1;
}
else
{
button->Cursor_length=button->Length-24;
}
}
void Window_draw_slider(T_Scroller_button * button)
{
word slider_position;
if (button->Is_horizontal)
{
slider_position=button->Pos_X+12;
Window_rectangle(slider_position,
button->Pos_Y,
button->Length-24,11,MC_Black/*MC_Dark*/);
if (button->Nb_elements>button->Nb_visibles)
slider_position+=
((button->Length-24-button->Cursor_length)*(button->Position)+(button->Nb_elements-button->Nb_visibles)/2)/(button->Nb_elements-button->Nb_visibles);
Window_rectangle(slider_position,
button->Pos_Y,
button->Cursor_length,11,MC_OnBlack/*MC_White*/);
Update_window_area(button->Pos_X,
button->Pos_Y,
button->Length,11);
}
else
{
slider_position=button->Pos_Y+12;
Window_rectangle(button->Pos_X,
slider_position,
11,button->Length-24,MC_Black/*MC_Dark*/);
if (button->Nb_elements>button->Nb_visibles)
slider_position+=
((button->Length-24-button->Cursor_length)*(button->Position)+(button->Nb_elements-button->Nb_visibles)/2)/(button->Nb_elements-button->Nb_visibles);
//
//(button->Position*) / (button->Nb_elements-button->Nb_visibles));
Window_rectangle(button->Pos_X,
slider_position,
11,button->Cursor_length,MC_OnBlack/*MC_White*/);
Update_window_area(button->Pos_X,
button->Pos_Y,
11,button->Length);
}
}
void Window_draw_scroller_button(T_Scroller_button * button)
{
if (button->Is_horizontal)
{
Window_display_frame_generic(button->Pos_X-1,button->Pos_Y-1,button->Length+2,13,MC_Black,MC_Black,MC_Dark,MC_Dark,MC_Dark);
Window_display_frame_mono(button->Pos_X+11,button->Pos_Y-1,button->Length-22,13,MC_Black);
Window_display_frame_out(button->Pos_X,button->Pos_Y,11,11);
Window_display_frame_out(button->Pos_X+button->Length-11,button->Pos_Y,11,11);
Print_in_window(button->Pos_X+2,button->Pos_Y+2,"\033",MC_Black,MC_Light);
Print_in_window(button->Pos_X+button->Length-9,button->Pos_Y+2,"\032",MC_Black,MC_Light);
}
else
{
Window_display_frame_generic(button->Pos_X-1,button->Pos_Y-1,13,button->Length+2,MC_Black,MC_Black,MC_Dark,MC_Dark,MC_Dark);
Window_display_frame_mono(button->Pos_X-1,button->Pos_Y+11,13,button->Length-22,MC_Black);
Window_display_frame_out(button->Pos_X,button->Pos_Y,11,11);
Window_display_frame_out(button->Pos_X,button->Pos_Y+button->Length-11,11,11);
Print_in_window(button->Pos_X+2,button->Pos_Y+2,"\030",MC_Black,MC_Light);
Print_in_window(button->Pos_X+2,button->Pos_Y+button->Length-9,"\031",MC_Black,MC_Light);
}
Window_draw_slider(button);
}
//--------------- Dessiner une zone de saisie dans une fentre ---------------
void Window_draw_input_bouton(word x_pos,word y_pos,word width_in_characters)
{
Window_display_frame_in(x_pos,y_pos,(width_in_characters<<3)+3,11);
}
//------------ Modifier le contenu (caption) d'une zone de saisie ------------
void Window_input_content(T_Special_button * button, char * content)
{
Print_in_window_limited(button->Pos_X+2,button->Pos_Y+2,content,button->Width/8,MC_Black,MC_Light);
}
//------------ Effacer le contenu (caption) d'une zone de saisie ------------
void Window_clear_input_button(T_Special_button * button)
{
Block((button->Pos_X+2)*Menu_factor_X+Window_pos_X,(button->Pos_Y+2)*Menu_factor_Y+Window_pos_Y,(button->Width/8)*8*Menu_factor_X,8*Menu_factor_Y,MC_Light);
Update_rect((button->Pos_X+2)*Menu_factor_X+Window_pos_X,(button->Pos_Y+2)*Menu_factor_Y+Window_pos_Y,button->Width/8*8*Menu_factor_X,8*Menu_factor_Y);
}
//------ Rajout d'un bouton la liste de ceux prsents dans la fentre ------
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 * temp=NULL;
Window_nb_buttons++;
if (clickable)
{
temp=(T_Normal_button *)malloc(sizeof(T_Normal_button));
temp->Number =Window_nb_buttons;
temp->Pos_X =x_pos;
temp->Pos_Y =y_pos;
temp->Width =width;
temp->Height =height;
temp->Clickable=clickable;
temp->Shortcut =shortcut;
temp->Repeatable=0;
temp->Next=Window_normal_button_list;
Window_normal_button_list=temp;
}
Window_draw_normal_bouton(x_pos,y_pos,width,height,title,undersc_letter,clickable);
return temp;
}
//------ Rajout d'un bouton la liste de ceux prsents dans la fentre ------
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_Normal_button * temp=NULL;
Window_nb_buttons++;
if (clickable)
{
temp=(T_Normal_button *)malloc(sizeof(T_Normal_button));
temp->Number =Window_nb_buttons;
temp->Pos_X =x_pos;
temp->Pos_Y =y_pos;
temp->Width =width;
temp->Height =height;
temp->Shortcut=shortcut;
temp->Repeatable=1;
temp->Next=Window_normal_button_list;
Window_normal_button_list=temp;
}
Window_draw_normal_bouton(x_pos,y_pos,width,height,title,undersc_letter,clickable);
return temp;
}
T_Palette_button * Window_set_palette_button(word x_pos, word y_pos)
{
T_Palette_button * temp;
temp=(T_Palette_button *)malloc(sizeof(T_Palette_button));
temp->Number =++Window_nb_buttons;
temp->Pos_X =x_pos;
temp->Pos_Y =y_pos;
temp->Next=Window_palette_button_list;
Window_palette_button_list=temp;
Window_draw_palette_bouton(x_pos,y_pos);
return temp;
}
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 * temp;
temp=(T_Scroller_button *)malloc(sizeof(T_Scroller_button));
temp->Number =++Window_nb_buttons;
temp->Is_horizontal =0;
temp->Pos_X =x_pos;
temp->Pos_Y =y_pos;
temp->Length =height;
temp->Nb_elements =nb_elements;
temp->Nb_visibles =nb_elements_visible;
temp->Position =initial_position;
Compute_slider_cursor_length(temp);
temp->Next=Window_scroller_button_list;
Window_scroller_button_list=temp;
Window_draw_scroller_button(temp);
return temp;
}
T_Scroller_button * Window_set_horizontal_scroller_button(word x_pos, word y_pos,
word width,
word nb_elements,
word nb_elements_visible,
word initial_position)
{
T_Scroller_button * temp;
temp=(T_Scroller_button *)malloc(sizeof(T_Scroller_button));
temp->Number =++Window_nb_buttons;
temp->Is_horizontal =1;
temp->Pos_X =x_pos;
temp->Pos_Y =y_pos;
temp->Length =width;
temp->Nb_elements =nb_elements;
temp->Nb_visibles =nb_elements_visible;
temp->Position =initial_position;
Compute_slider_cursor_length(temp);
temp->Next=Window_scroller_button_list;
Window_scroller_button_list=temp;
Window_draw_scroller_button(temp);
return temp;
}
T_Special_button * Window_set_special_button(word x_pos,word y_pos,word width,word height)
{
T_Special_button * temp;
temp=(T_Special_button *)malloc(sizeof(T_Special_button));
temp->Number =++Window_nb_buttons;
temp->Pos_X =x_pos;
temp->Pos_Y =y_pos;
temp->Width =width;
temp->Height =height;
temp->Next=Window_special_button_list;
Window_special_button_list=temp;
return temp;
}
T_Special_button * Window_set_input_button(word x_pos,word y_pos,word width_in_characters)
{
T_Special_button *temp;
temp=Window_set_special_button(x_pos,y_pos,(width_in_characters<<3)+3,11);
Window_draw_input_bouton(x_pos,y_pos,width_in_characters);
return temp;
}
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)
{
T_Dropdown_button *temp;
temp=(T_Dropdown_button *)malloc(sizeof(T_Dropdown_button));
temp->Number =++Window_nb_buttons;
temp->Pos_X =x_pos;
temp->Pos_Y =y_pos;
temp->Width =width;
temp->Height =height;
temp->Display_choice =display_choice;
temp->First_item=NULL;
temp->Dropdown_width=dropdown_width?dropdown_width:width;
temp->Display_centered=display_centered;
temp->Display_arrow=display_arrow;
temp->Active_button=active_button;
temp->Bottom_up=bottom_up;
temp->Next=Window_dropdown_button_list;
Window_dropdown_button_list=temp;
Window_draw_normal_bouton(x_pos,y_pos,width,height,"",-1,1);
if (label && label[0])
Print_in_window(temp->Pos_X+2,temp->Pos_Y+(temp->Height-7)/2,label,MC_Black,MC_Light);
if (display_arrow)
Window_display_icon_sprite(temp->Pos_X+temp->Width-10,temp->Pos_Y+(temp->Height-7)/2,ICON_DROPDOWN);
return temp;
}
// Ajoute un choix une dropdown. Le libell est seulement rfrenc,
// il doit pointer sur une zone qui doit tre encore valide la fermeture
// de la fentre (comprise).
void Window_dropdown_add_item(T_Dropdown_button * dropdown, word btn_number, const char *label)
{
T_Dropdown_choice *temp;
T_Dropdown_choice *last;
temp=(T_Dropdown_choice *)malloc(sizeof(T_Dropdown_choice));
temp->Number =btn_number;
temp->Label=label;
temp->Next=NULL;
last=dropdown->First_item;
if (last)
{
// On cherche le dernier lment
for (;last->Next;last=last->Next)
;
last->Next=temp;
}
else
{
dropdown->First_item=temp;
}
}
// ------------- Suppression de tous les choix d'une dropdown ---------
void Window_dropdown_clear_items(T_Dropdown_button * dropdown)
{
T_Dropdown_choice * next_choice;
while (dropdown->First_item)
{
next_choice=dropdown->First_item->Next;
free(dropdown->First_item);
dropdown->First_item=next_choice;
}
}
//----------------------- Create a List control -----------------------
// These controls are special. They work over two controls previously created:
// - entry_button is the textual area where the list values will be printed.
// - scroller is a scroller button attached to it
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)
{
T_List_button *temp;
temp=(T_List_button *)malloc(sizeof(T_List_button));
temp->Number =++Window_nb_buttons;
temp->List_start = 0;
temp->Cursor_position = 0;
temp->Entry_button = entry_button;
temp->Scroller = scroller;
temp->Draw_list_item = draw_list_item;
temp->Color_index = color_index;
temp->Next=Window_list_button_list;
Window_list_button_list=temp;
return temp;
}
void Window_redraw_list(T_List_button * list)
{
int i;
for (i=Min(list->Scroller->Nb_visibles-1, list->Scroller->Nb_elements-1); i>=0; i--)
{
list->Draw_list_item(
list->Entry_button->Pos_X,
list->Entry_button->Pos_Y + i * 8,
list->List_start + i,
i == list->Cursor_position);
}
// Remaining rectangle under list
i=list->Scroller->Nb_visibles-list->Scroller->Nb_elements;
if (i>0)
{
byte color;
color = list->Color_index == 0 ? MC_Black :
(list->Color_index == 1 ? MC_Dark :
(list->Color_index == 2 ? MC_Light : MC_White));
Window_rectangle(
list->Entry_button->Pos_X,
list->Entry_button->Pos_Y+list->Scroller->Nb_elements*8,
list->Entry_button->Width,
i*8,
color);
}
}
//----------------------- Ouverture d'un pop-up -----------------------
void Open_popup(word x_pos, word y_pos, word width,word height)
// Lors de l'appel cette procdure, la souris doit tre affiche.
// En sortie de cette procedure, la souris est efface.
// Note : les pop-ups sont grs comme s'ils taient des sous-fentres, ils ont donc leur propre boucle d'vnements et tout, on peut ajouter des widgets dedans, ...
// Les diffrences sont surtout graphiques :
// -Possibilit de prciser la position XY
// -Pas de titre
// -Pas de cadre en relief mais seulement un plat, et il est blanc au lieu de noir.
{
Windows_open++;
Window_width=width;
Window_height=height;
Window_pos_X=x_pos;
Window_pos_Y=y_pos;
Window_draggable=0;
// Sauvegarde de ce que la fentre remplace
Save_background(&(Window_background[Windows_open-1]), Window_pos_X, Window_pos_Y, width, height);
/*
// Fentre grise
Block(Window_pos_X+1*Menu_factor_X,
Window_pos_Y+1*Menu_factor_Y,
(width-2)*Menu_factor_X,(height-2)*Menu_factor_Y,MC_Light);
// Frame noir puis en relief
Window_display_frame_mono(0,0,width,height,MC_White);
*/
if (Windows_open == 1)
{
Menu_is_visible_before_window=Menu_is_visible;
Menu_is_visible=0;
Menu_Y_before_window=Menu_Y;
Menu_Y=Screen_height;
Cursor_shape_before_window=Cursor_shape;
Cursor_shape=CURSOR_SHAPE_ARROW;
Paintbrush_hidden_before_window=Paintbrush_hidden;
Paintbrush_hidden=1;
}
// Initialisation des listes de boutons de la fentre
Window_normal_button_list =NULL;
Window_palette_button_list =NULL;
Window_scroller_button_list=NULL;
Window_special_button_list =NULL;
Window_dropdown_button_list =NULL;
Window_nb_buttons =0;
}
//----------------------- Fermer une fentre d'options -----------------------
void Close_popup(void)
// Lors de l'appel cette procedure, la souris doit tre affiche.
// En sortie de cette procedure, la souris est efface.
{
T_Normal_button * temp1;
T_Palette_button * temp2;
T_Scroller_button * temp3;
T_Special_button * temp4;
T_Dropdown_button * temp5;
T_List_button * temp6;
Hide_cursor();
while (Window_normal_button_list)
{
temp1=Window_normal_button_list->Next;
free(Window_normal_button_list);
Window_normal_button_list=temp1;
}
while (Window_palette_button_list)
{
temp2=Window_palette_button_list->Next;
free(Window_palette_button_list);
Window_palette_button_list=temp2;
}
while (Window_scroller_button_list)
{
temp3=Window_scroller_button_list->Next;
free(Window_scroller_button_list);
Window_scroller_button_list=temp3;
}
while (Window_special_button_list)
{
temp4=Window_special_button_list->Next;
free(Window_special_button_list);
Window_special_button_list=temp4;
}
while (Window_dropdown_button_list)
{
Window_dropdown_clear_items(Window_dropdown_button_list);
temp5=Window_dropdown_button_list->Next;
free(Window_dropdown_button_list);
Window_dropdown_button_list=temp5;
}
while (Window_list_button_list)
{
temp6=Window_list_button_list->Next;
free(Window_list_button_list);
Window_list_button_list=temp6;
}
if (Windows_open != 1)
{
// Restore de ce que la fentre cachait
Restore_background(Window_background[Windows_open-1], Window_pos_X, Window_pos_Y, Window_width, Window_height);
Window_background[Windows_open-1]=NULL;
Update_rect(Window_pos_X,Window_pos_Y,Window_width*Menu_factor_X,Window_height*Menu_factor_Y);
Windows_open--;
}
else
{
free(Window_background[Windows_open-1]);
Window_background[Windows_open-1] = NULL;
Windows_open--;
Paintbrush_hidden=Paintbrush_hidden_before_window;
Compute_paintbrush_coordinates();
Menu_Y=Menu_Y_before_window;
Menu_is_visible=Menu_is_visible_before_window;
Cursor_shape=Cursor_shape_before_window;
Display_all_screen();
Display_menu();
}
Key=0;
Mouse_K=0;
Old_MX = -1;
Old_MY = -1;
}
//////////////////////////////////////////////////////////////////////////////
// //
// Mini-MOTEUR utilis dans les fentres (menus des boutons...) //
// //
//////////////////////////////////////////////////////////////////////////////
// -- Indique si on a cliqu dans une zone dfinie par deux points extremes --
byte Window_click_in_rectangle(short start_x,short start_y,short end_x,short end_y)
{
short x_pos,y_pos;
x_pos=((short)Mouse_X-Window_pos_X)/Menu_factor_X;
y_pos=((short)Mouse_Y-Window_pos_Y)/Menu_factor_Y;
return ((x_pos>=start_x) &&
(y_pos>=start_y) &&
(x_pos<=end_x) &&
(y_pos<=end_y));
}
// --- Attend que l'on clique dans la palette pour renvoyer la couleur choisie
// ou bien renvoie -1 si on a annul l'action pas click-droit ou Escape ------
short Wait_click_in_palette(T_Palette_button * button)
{
short start_x=button->Pos_X+5;
short start_y=button->Pos_Y+3;
short end_x =button->Pos_X+160;
short end_y =button->Pos_Y+82;
byte selected_color;
byte old_hide_cursor;
byte old_main_magnifier_mode;
Hide_cursor();
old_hide_cursor=Cursor_hidden;
old_main_magnifier_mode=Main_magnifier_mode;
Main_magnifier_mode=0;
Cursor_hidden=0;
Cursor_shape=CURSOR_SHAPE_TARGET;
Display_cursor();
for (;;)
{
while (Get_input(20))
;
if (Mouse_K==LEFT_SIDE)
{
if (Window_click_in_rectangle(start_x,start_y,end_x,end_y))
{
Hide_cursor();
selected_color=(((Mouse_X-Window_pos_X)/Menu_factor_X)-(button->Pos_X+2)) / 10 * 16 +
(((Mouse_Y-Window_pos_Y)/Menu_factor_Y)-(button->Pos_Y+3)) / 5;
Cursor_shape=CURSOR_SHAPE_ARROW;
Cursor_hidden=old_hide_cursor;
Main_magnifier_mode=old_main_magnifier_mode;
Display_cursor();
return selected_color;
}
if ((Mouse_X=Window_pos_X+(Window_width*Menu_factor_X)) ||
(Mouse_Y>=Window_pos_Y+(Window_height*Menu_factor_Y)) )
{
Hide_cursor();
selected_color=Read_pixel(Mouse_X,Mouse_Y);
Cursor_shape=CURSOR_SHAPE_ARROW;
Cursor_hidden=old_hide_cursor;
Main_magnifier_mode=old_main_magnifier_mode;
Display_cursor();
return selected_color;
}
}
if ((Mouse_K==RIGHT_SIDE) || (Key==KEY_ESC))
{
Hide_cursor();
Cursor_shape=CURSOR_SHAPE_ARROW;
Cursor_hidden=old_hide_cursor;
Main_magnifier_mode=old_main_magnifier_mode;
Display_cursor();
return -1;
}
}
}
// -------------- Rcupration d'une couleur derrire un menu ----------------
void Get_color_behind_window(byte * color, byte * click)
{
short old_x=-1;
short old_y=-1;
short index;
short a,b,c,d; // Variables temporaires et multitches...
byte * buffer = NULL;
char str[25];
byte cursor_was_hidden;
Hide_cursor();
cursor_was_hidden=Cursor_hidden;
Cursor_hidden=0;
Save_background(&buffer,Window_pos_X,Window_pos_Y,Window_width,Window_height);
a=Menu_Y;
Menu_Y=Menu_Y_before_window;
b=Menu_is_visible;
Menu_is_visible=Menu_is_visible_before_window;
Display_all_screen();
Display_menu();
Menu_Y=a;
Menu_is_visible=b;
Cursor_shape=CURSOR_SHAPE_COLORPICKER;
b=Paintbrush_hidden;
Paintbrush_hidden=1;
c=-1; // color pointe: au dbut aucune, comme a on initialise tout
if (Menu_is_visible_before_window)
Print_in_menu(Menu_tooltip[BUTTON_CHOOSE_COL],0);
Display_cursor();
do
{
Get_input(20);
if ((Mouse_X!=old_x) || (Mouse_Y!=old_y))
{
Hide_cursor();
a=Read_pixel(Mouse_X,Mouse_Y);
if (a!=c)
{
c=a; // Mise jour de la couleur pointe
if (Menu_is_visible_before_window)
{
sprintf(str,"%d",a);
d=strlen(str);
strcat(str," (");
sprintf(str+strlen(str),"%d",Main_palette[a].R);
strcat(str,",");
sprintf(str+strlen(str),"%d",Main_palette[a].G);
strcat(str,",");
sprintf(str+strlen(str),"%d",Main_palette[a].B);
strcat(str,")");
a=24-d;
for (index=strlen(str); indexScreen_width-width)
{
new_x=Screen_width-width;
dx = Mouse_X - new_x;
}
new_y=Mouse_Y-dy;
if (new_y<0)
{
new_y=0;
dy = Mouse_Y;
}
if (new_y>Screen_height-height)
{
new_y=Screen_height-height;
dy = Mouse_Y - new_y;
}
if ((new_x!=old_x) || (new_y!=old_y))
{
Hide_cursor();
Horizontal_XOR_line(old_x,old_y,width);
Vertical_XOR_line(old_x,old_y+1,height-2);
Vertical_XOR_line(old_x+width-1,old_y+1,height-2);
Horizontal_XOR_line(old_x,old_y+height-1,width);
Horizontal_XOR_line(new_x,new_y,width);
Vertical_XOR_line(new_x,new_y+1,height-2);
Vertical_XOR_line(new_x+width-1,new_y+1,height-2);
Horizontal_XOR_line(new_x,new_y+height-1,width);
Display_cursor();
Update_rect(old_x,old_y,width,height);
Update_rect(new_x,new_y,width,height);
}
}
Hide_cursor();
Horizontal_XOR_line(new_x,new_y,width);
Vertical_XOR_line(new_x,new_y+1,height-2);
Vertical_XOR_line(new_x+width-1,new_y+1,height-2);
Horizontal_XOR_line(new_x,new_y+height-1,width);
if ((new_x!=Window_pos_X)
|| (new_y!=Window_pos_Y))
{
a=Menu_Y;
Menu_Y=Menu_Y_before_window;
b=Menu_is_visible;
Menu_is_visible=Menu_is_visible_before_window;
//Display_all_screen();
//Display_menu();
Menu_Y=a;
Menu_is_visible=b;
// Sauvegarde du contenu actuel de la fentre
Save_background(&buffer, Window_pos_X, Window_pos_Y, Window_width, Window_height);
// Restore de ce que la fentre cachait
Restore_background(Window_background[Windows_open-1], Window_pos_X, Window_pos_Y, Window_width, Window_height);
Window_background[Windows_open-1] = NULL;
// Sauvegarde de ce que la fentre remplace
Save_background(&(Window_background[Windows_open-1]), new_x, new_y, Window_width, Window_height);
// Raffichage de la fentre
Restore_background(buffer, new_x, new_y, Window_width, Window_height);
buffer = NULL;
// Mise jour du rectangle englobant
Update_rect(
(new_x>Window_pos_X)?Window_pos_X:new_x,
(new_y>Window_pos_Y)?Window_pos_Y:new_y,
((new_x>Window_pos_X)?(new_x-Window_pos_X):(Window_pos_X-new_x)) + Window_width*Menu_factor_X,
((new_y>Window_pos_Y)?(new_y-Window_pos_Y):(Window_pos_Y-new_y)) + Window_height*Menu_factor_Y);
Window_pos_X=new_x;
Window_pos_Y=new_y;
}
else
{
// Update pour effacer le rectangle XOR
Update_rect(Window_pos_X, Window_pos_Y, Window_width*Menu_factor_X, Window_height*Menu_factor_Y);
}
Cursor_shape=CURSOR_SHAPE_ARROW;
Display_cursor();
}
///
/// 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)
{
short nb_choices;
short choice_index;
short selected_index;
short old_selected_index;
short box_height;
T_Dropdown_choice *item;
// Taille de l'ombre porte (en plus des dimensions normales)
#define SHADOW_RIGHT 3
#define SHADOW_BOTTOM 4
// Comptage des items pour calculer la taille
nb_choices=0;
for (item=button->First_item; item!=NULL; item=item->Next)
{
nb_choices++;
}
box_height=3+nb_choices*8+1;
// Open a new stacked "window" to serve as drawing area.
Open_popup(
off_x+(button->Pos_X)*Menu_factor_X,
off_y+(button->Pos_Y+(button->Bottom_up?-box_height:button->Height))*Menu_factor_Y,
button->Dropdown_width+SHADOW_RIGHT,
box_height+SHADOW_BOTTOM);
// Dessin de la boite
// Bord gauche
Block(Window_pos_X,Window_pos_Y,Menu_factor_X,box_height*Menu_factor_Y,MC_Black);
// Frame fonce et blanc
Window_display_frame_out(1,0,button->Dropdown_width-1,box_height);
// Ombre porte
if (SHADOW_BOTTOM)
{
Block(Window_pos_X+SHADOW_RIGHT*Menu_factor_X,
Window_pos_Y+box_height*Menu_factor_Y,
button->Dropdown_width*Menu_factor_X,
SHADOW_BOTTOM*Menu_factor_Y,
MC_Black);
Block(Window_pos_X,
Window_pos_Y+box_height*Menu_factor_Y,
SHADOW_RIGHT*Menu_factor_X,
Menu_factor_Y,
MC_Black);
}
if (SHADOW_RIGHT)
{
Block(Window_pos_X+button->Dropdown_width*Menu_factor_X,
Window_pos_Y+SHADOW_BOTTOM*Menu_factor_Y,
SHADOW_RIGHT*Menu_factor_X,
(box_height-SHADOW_BOTTOM)*Menu_factor_Y,
MC_Black);
Block(Window_pos_X+button->Dropdown_width*Menu_factor_X,
Window_pos_Y,
Menu_factor_X,
SHADOW_BOTTOM*Menu_factor_Y,
MC_Black);
}
selected_index=-1;
while (1)
{
old_selected_index = selected_index;
// Fentre grise
Block(Window_pos_X+2*Menu_factor_X,
Window_pos_Y+1*Menu_factor_Y,
(button->Dropdown_width-3)*Menu_factor_X,(box_height-2)*Menu_factor_Y,MC_Light);
// Affichage des items
for(item=button->First_item,choice_index=0; item!=NULL; item=item->Next,choice_index++)
{
byte color_1;
byte color_2;
if (choice_index==selected_index)
{
color_1=MC_White;
color_2=MC_Dark;
Block(Window_pos_X+3*Menu_factor_X,
Window_pos_Y+((2+choice_index*8)*Menu_factor_Y),
(button->Dropdown_width-5)*Menu_factor_X,(8)*Menu_factor_Y,MC_Dark);
}
else
{
color_1=MC_Black;
color_2=MC_Light;
}
Print_in_window(3,2+choice_index*8,item->Label,color_1,color_2);
}
Update_rect(Window_pos_X,Window_pos_Y,Window_width*Menu_factor_X,Window_height*Menu_factor_Y);
Display_cursor();
do
{
// Attente
Get_input(20);
// Mise jour du survol
selected_index=Window_click_in_rectangle(2,2,button->Dropdown_width-2,box_height-1)?
(((Mouse_Y-Window_pos_Y)/Menu_factor_Y-2)>>3) : -1;
} while (Mouse_K && selected_index==old_selected_index);
if (!Mouse_K)
break;
Hide_cursor();
}
Close_popup();
if (selected_index>=0 && selected_indexFirst_item; selected_index; item=item->Next,selected_index--)
;
return item;
}
return NULL;
}
// Gestion des dropdown
short Window_dropdown_on_click(T_Dropdown_button *button)
{
T_Dropdown_choice * item;
// Highlight the button
Hide_cursor();
Window_select_normal_button(button->Pos_X,button->Pos_Y,button->Width,button->Height);
// Handle the dropdown's logic
item = Dropdown_activate(button, Window_pos_X, Window_pos_Y);
// Unhighlight the button
Window_unselect_normal_button(button->Pos_X,button->Pos_Y,button->Width,button->Height);
Display_cursor();
if (item == NULL)
{
Window_attribute2=-1;
return 0;
}
if (button->Display_choice)
{
// Automatically update the label of the dropdown list.
int text_length = (button->Width-4-(button->Display_arrow?8:0))/8;
// Clear original label area
Window_rectangle(button->Pos_X+2,button->Pos_Y+(button->Height-7)/2,text_length*8,8,MC_Light);
Print_in_window_limited(button->Pos_X+2,button->Pos_Y+(button->Height-7)/2,item->Label,text_length ,MC_Black,MC_Light);
}
Window_attribute2=item->Number;
return button->Number;
}
// --- Fonction de clic sur un bouton a peu prs ordinaire:
// Attend que l'on relache le bouton, et renvoie le numero du bouton si on
// est rest dessus, 0 si on a annul en sortant du bouton.
short Window_normal_button_onclick(word x_pos, word y_pos, word width, word height, short btn_number)
{
while(1)
{
Hide_cursor();
Window_select_normal_button(x_pos,y_pos,width,height);
Display_cursor();
while (Window_click_in_rectangle(x_pos,y_pos,x_pos+width-1,y_pos+height-1))
{
Get_input(20);
if (!Mouse_K)
{
Hide_cursor();
Window_unselect_normal_button(x_pos,y_pos,width,height);
Display_cursor();
return btn_number;
}
}
Hide_cursor();
Window_unselect_normal_button(x_pos,y_pos,width,height);
Display_cursor();
while (!(Window_click_in_rectangle(x_pos,y_pos,x_pos+width-1,y_pos+height-1)))
{
Get_input(20);
if (!Mouse_K)
return 0;
}
}
}
// --- Returns the number of the clicked button (-1:out of the window, 0:none) ---
short Window_get_clicked_button(void)
{
T_Normal_button * temp1;
T_Palette_button * temp2;
T_Scroller_button * temp3;
T_Special_button * temp4;
T_Dropdown_button * temp5;
Window_attribute1=Mouse_K;
// Test click on normal buttons
for (temp1=Window_normal_button_list; temp1; temp1=temp1->Next)
{
if ((Input_sticky_control == 0 || Input_sticky_control == temp1->Number)
&& Window_click_in_rectangle(temp1->Pos_X,temp1->Pos_Y,temp1->Pos_X+temp1->Width-1,temp1->Pos_Y+temp1->Height-1))
{
Input_sticky_control = temp1->Number;
if (temp1->Repeatable)
{
Hide_cursor();
Window_select_normal_button(temp1->Pos_X,temp1->Pos_Y,temp1->Width,temp1->Height);
Display_cursor();
Delay_with_active_mouse((Mouse_K==1)? Config.Delay_left_click_on_slider : Config.Delay_right_click_on_slider);
Hide_cursor();
Window_unselect_normal_button(temp1->Pos_X,temp1->Pos_Y,temp1->Width,temp1->Height);
Display_cursor();
return temp1->Number;
}
return Window_normal_button_onclick(temp1->Pos_X,temp1->Pos_Y,temp1->Width,temp1->Height,temp1->Number);
}
}
// Test click on "Palette" buttons
for (temp2=Window_palette_button_list; temp2; temp2=temp2->Next)
{
if ((Input_sticky_control == 0 || Input_sticky_control == temp2->Number)
&& Window_click_in_rectangle(temp2->Pos_X+5,temp2->Pos_Y+3,temp2->Pos_X+160,temp2->Pos_Y+82))
{
Input_sticky_control = temp2->Number;
// We store the clicked color in Attribute2
Window_attribute2 = (((Mouse_X-Window_pos_X)/Menu_factor_X)-(temp2->Pos_X+2)) / 10 * 16 +
(((Mouse_Y-Window_pos_Y)/Menu_factor_Y)-(temp2->Pos_Y+3)) / 5;
return temp2->Number;
}
}
// Test click on slider/scroller bars
for (temp3=Window_scroller_button_list; temp3; temp3=temp3->Next)
{
// Button Up arrow
if ((Input_sticky_control == 0 || Input_sticky_control == (temp3->Number|1024))
&& Window_click_in_rectangle(temp3->Pos_X,temp3->Pos_Y,temp3->Pos_X+10,temp3->Pos_Y+10))
{
Input_sticky_control = temp3->Number | 1024;
Hide_cursor();
Window_select_normal_button(temp3->Pos_X,temp3->Pos_Y,11,11);
if (temp3->Position)
{
temp3->Position--;
Window_attribute1=1;
Window_attribute2=temp3->Position;
Window_draw_slider(temp3);
}
else
Window_attribute1=0;
Display_cursor();
Delay_with_active_mouse((Mouse_K==1)? Config.Delay_left_click_on_slider : Config.Delay_right_click_on_slider);
Hide_cursor();
Window_unselect_normal_button(temp3->Pos_X,temp3->Pos_Y,11,11);
Display_cursor();
return (Window_attribute1)? temp3->Number : 0;
}
// Button Down arrow
if ((Input_sticky_control == 0 || Input_sticky_control == (temp3->Number|2048))
&& ((temp3->Is_horizontal && Window_click_in_rectangle(temp3->Pos_X+temp3->Length-11,temp3->Pos_Y,temp3->Pos_X+temp3->Length-1,temp3->Pos_Y+10))
|| (!temp3->Is_horizontal && Window_click_in_rectangle(temp3->Pos_X,temp3->Pos_Y+temp3->Length-11,temp3->Pos_X+10,temp3->Pos_Y+temp3->Length-1))))
{
Input_sticky_control = temp3->Number | 2048;
Hide_cursor();
if (temp3->Is_horizontal)
Window_select_normal_button(temp3->Pos_X+temp3->Length-11,temp3->Pos_Y,11,11);
else
Window_select_normal_button(temp3->Pos_X,temp3->Pos_Y+temp3->Length-11,11,11);
if (temp3->Position+temp3->Nb_visiblesNb_elements)
{
temp3->Position++;
Window_attribute1=2;
Window_attribute2=temp3->Position;
Window_draw_slider(temp3);
}
else
Window_attribute1=0;
Display_cursor();
Delay_with_active_mouse((Mouse_K==1)? Config.Delay_left_click_on_slider : Config.Delay_right_click_on_slider);
Hide_cursor();
if (temp3->Is_horizontal)
Window_unselect_normal_button(temp3->Pos_X+temp3->Length-11,temp3->Pos_Y,11,11);
else
Window_unselect_normal_button(temp3->Pos_X,temp3->Pos_Y+temp3->Length-11,11,11);
Display_cursor();
return (Window_attribute1)? temp3->Number : 0;
}
// Middle slider
if ((Input_sticky_control == temp3->Number) || (Input_sticky_control==0 &&
((!temp3->Is_horizontal && Window_click_in_rectangle(temp3->Pos_X,temp3->Pos_Y+12,temp3->Pos_X+10,temp3->Pos_Y+temp3->Length-13))
||(temp3->Is_horizontal && Window_click_in_rectangle(temp3->Pos_X+12,temp3->Pos_Y,temp3->Pos_X+temp3->Length-13,temp3->Pos_Y+10)))))
{
Input_sticky_control = temp3->Number;
if (temp3->Nb_elements>temp3->Nb_visibles)
{
// If there is enough room to make the cursor move:
long mouse_pos;
long origin;
// Window_attribute2 receives the position of the cursor.
if (temp3->Is_horizontal)
mouse_pos =(Mouse_X-Window_pos_X) / Menu_factor_X - (temp3->Pos_X+12);
else
mouse_pos =(Mouse_Y-Window_pos_Y) / Menu_factor_Y - (temp3->Pos_Y+12);
// The following formula is wicked. The issue is that you want two
// different behaviors:
// *) If the range is bigger than the pixel precision, the last pixel
// should map to max value, exactly.
// *) Otherwise, the possible cursor positions are separated by
// at least one full pixel, so we should find the valid position
// closest to the center of the mouse cursor position pixel.
origin = (temp3->Nb_visibles-1)*(temp3->Length-24)/temp3->Nb_elements/2;
Window_attribute2 = (mouse_pos - origin) * (temp3->Nb_elements-(temp3->Cursor_length>1?0:1)) / (temp3->Length-24-1);
if (Window_attribute2<0)
Window_attribute2=0;
else if (Window_attribute2+temp3->Nb_visibles>temp3->Nb_elements)
Window_attribute2=temp3->Nb_elements-temp3->Nb_visibles;
// If the cursor moved
if (temp3->Position!=Window_attribute2)
{
temp3->Position=Window_attribute2;
Window_attribute1=3;
Hide_cursor();
Window_draw_slider(temp3);
Display_cursor();
}
else
// If the cursor moved
Window_attribute1=0;
}
else
// If there's not enough room to make the cursor move:
Window_attribute1=0;
return (Window_attribute1)? temp3->Number : 0;
}
}
// Test click on a special button
for (temp4=Window_special_button_list; temp4; temp4=temp4->Next)
{
if ((Input_sticky_control == 0 || Input_sticky_control == temp4->Number)
&& Window_click_in_rectangle(temp4->Pos_X,temp4->Pos_Y,temp4->Pos_X+temp4->Width-1,temp4->Pos_Y+temp4->Height-1))
{
Input_sticky_control = temp4->Number;
return temp4->Number;
}
}
// Test click on a dropdown box
for (temp5=Window_dropdown_button_list; temp5; temp5=temp5->Next)
{
if ((Input_sticky_control == 0 || Input_sticky_control == temp5->Number)
&& Window_click_in_rectangle(temp5->Pos_X,temp5->Pos_Y,temp5->Pos_X+temp5->Width-1,temp5->Pos_Y+temp5->Height-1))
{
Input_sticky_control = temp5->Number;
if (Mouse_K & temp5->Active_button)
return Window_dropdown_on_click(temp5);
else
{
Window_attribute2=-1;
return Window_normal_button_onclick(temp5->Pos_X,temp5->Pos_Y,temp5->Width,temp5->Height,temp5->Number);
}
}
}
return 0;
}
short Window_get_button_shortcut(void)
{
T_Normal_button * temp;
if (Key & MOD_SHIFT)
Window_attribute1=RIGHT_SIDE;
else
Window_attribute1=LEFT_SIDE;
// On fait une premire recherche
temp=Window_normal_button_list;
while (temp!=NULL)
{
if (temp->Shortcut==Key)
{
Hide_cursor();
Window_select_normal_button(temp->Pos_X,temp->Pos_Y,temp->Width,temp->Height);
Display_cursor();
Delay_with_active_mouse(Config.Delay_right_click_on_slider);
Hide_cursor();
Window_unselect_normal_button(temp->Pos_X,temp->Pos_Y,temp->Width,temp->Height);
Display_cursor();
return temp->Number;
}
temp=temp->Next;
}
// Si la recherche n'a pas t fructueuse ET que l'utilisateur appuyait sur
// , on regarde si un bouton ne pourrait pas ragir comme si
// n'tait pas appuy.
if (Window_attribute1==RIGHT_SIDE)
{
temp=Window_normal_button_list;
while (temp!=NULL)
{
if (temp->Shortcut==(Key&0x0FFF))
return temp->Number;
temp=temp->Next;
}
}
// Handle arrow keys, end/home, and mouse wheel that have
// a certain behavior if a list control is present.
if (Window_list_button_list)
{
T_List_button *list = Window_list_button_list;
// If there's more than one of such control, only capture
// events if the mouse cursor is over it.
if (list->Next)
{
// to do
}
}
return 0;
}
short Window_clicked_button(void)
{
short Button;
byte old_mouse_k;
old_mouse_k=Mouse_K;
Get_input(20);
// Handle clicks
if (Mouse_K)
{
if ((Mouse_X=Window_pos_X+(Window_width*Menu_factor_X))
|| (Mouse_Y>=Window_pos_Y+(Window_height*Menu_factor_Y)))
{
if (Input_sticky_control == 0 || Input_sticky_control == -1)
{
Input_sticky_control = -1;
return -1;
}
else
{
return 0;
}
}
if (!Input_sticky_control && Window_draggable && Mouse_Y < Window_pos_Y+(12*Menu_factor_Y))
{
Move_window(Mouse_X-Window_pos_X,Mouse_Y-Window_pos_Y);
}
else
{
short clicked_button;
T_List_button * list;
static Uint32 time_last_click = 0;
static int last_list_number = -1;
Uint32 time_now;
// Check which controls was clicked (by rectangular area)
clicked_button = Window_get_clicked_button();
// Check if it's part of a list control
for (list=Window_list_button_list; list!=NULL; list=list->Next)
{
if (list->Entry_button->Number == clicked_button)
{
// Click in the textual part of a list.
short clicked_line;
clicked_line = (((Mouse_Y-Window_pos_Y)/Menu_factor_Y)-list->Entry_button->Pos_Y)>>3;
if (clicked_line >= list->Scroller->Nb_elements) // Below last line
return 0;
time_now = SDL_GetTicks();
if (clicked_line == list->Cursor_position)
{
// Double click check
if (old_mouse_k==0 && last_list_number==list->Number && time_now - time_last_click < Config.Double_click_speed)
{
time_last_click = time_now;
Input_sticky_control=0;
// Store the selected value as attribute2
Window_attribute2=list->List_start + list->Cursor_position;
// Return the control ID of the "special button" that covers the list.
return list->Entry_button->Number;
}
time_last_click = time_now;
last_list_number=list->Number;
// Already selected : don't activate anything
return 0;
}
Hide_cursor();
// Redraw one item as disabled
if (list->Cursor_position>=0 && list->Cursor_positionScroller->Nb_visibles)
list->Draw_list_item(
list->Entry_button->Pos_X,
list->Entry_button->Pos_Y + list->Cursor_position * 8,
list->List_start + list->Cursor_position,
0);
list->Cursor_position = clicked_line;
// Redraw one item as enabled
if (list->Cursor_position>=0 && list->Cursor_positionScroller->Nb_visibles)
list->Draw_list_item(
list->Entry_button->Pos_X,
list->Entry_button->Pos_Y + list->Cursor_position * 8,
list->List_start + list->Cursor_position,
1);
Display_cursor();
// Store the selected value as attribute2
Window_attribute2=list->List_start + list->Cursor_position;
// Return the control ID of the list.
return list->Number;
}
else if (list->Scroller->Number == clicked_button)
{
// Click in the scroller part of a list
if (list->List_start == list->Scroller->Position)
return 0; // Didn't actually move
// Update scroller indices
list->Cursor_position += list->List_start;
list->List_start = list->Scroller->Position;
list->Cursor_position -= list->List_start;
// Need to redraw all
Hide_cursor();
Window_redraw_list(list);
Display_cursor();
}
}
return clicked_button;
}
}
// Intercept keys
if (Key)
{
T_List_button * list;
Button=Window_get_button_shortcut();
if (Button)
{
Key=0;
return Button;
}
// Check if there's a list control and the keys can control it
for (list=Window_list_button_list; list!=NULL; list=list->Next)
{
// FIXME: Make only one list have the keyboard focus.
if (1)
{
if (Key==SDLK_UP && (list->Cursor_position+list->List_start)>0)
{
Key=0;
Hide_cursor();
list->Cursor_position--;
if (list->Cursor_position<0)
{
list->List_start=list->List_start+list->Cursor_position;
list->Cursor_position=0;
// Mise jour du scroller
list->Scroller->Position=list->List_start;
Window_draw_slider(list->Scroller);
}
Window_redraw_list(list);
Display_cursor();
// Store the selected value as attribute2
Window_attribute2=list->List_start + list->Cursor_position;
// Return the control ID of the list.
return list->Number;
}
if (Key==SDLK_DOWN && (list->Cursor_position+list->List_start)<(list->Scroller->Nb_elements-1))
{
Key=0;
Hide_cursor();
list->Cursor_position++;
if (list->Cursor_position>(list->Scroller->Nb_visibles-1))
{
list->List_start=list->List_start+list->Cursor_position-(list->Scroller->Nb_visibles-1);
list->Cursor_position=(list->Scroller->Nb_visibles-1);
// Mise jour du scroller
list->Scroller->Position=list->List_start;
Window_draw_slider(list->Scroller);
}
Window_redraw_list(list);
Display_cursor();
// Store the selected value as attribute2
Window_attribute2=list->List_start + list->Cursor_position;
// Return the control ID of the list.
return list->Number;
}
if (Key==SDLK_HOME && (list->Cursor_position!=0 || list->List_start!=0))
{
Key=0;
Hide_cursor();
list->Cursor_position=0;
list->List_start=0;
// Mise jour du scroller
list->Scroller->Position=list->List_start;
Window_draw_slider(list->Scroller);
Window_redraw_list(list);
Display_cursor();
// Store the selected value as attribute2
Window_attribute2=list->List_start + list->Cursor_position;
// Return the control ID of the list.
return list->Number;
}
if (Key==SDLK_END && (list->Cursor_position+list->List_start)<(list->Scroller->Nb_elements-1))
{
Key=0;
Hide_cursor();
list->Cursor_position=(list->Scroller->Nb_elements-1)-list->List_start;
if (list->Cursor_position>(list->Scroller->Nb_visibles-1))
{
list->List_start=list->List_start+list->Cursor_position-(list->Scroller->Nb_visibles-1);
list->Cursor_position=(list->Scroller->Nb_visibles-1);
// Mise jour du scroller
list->Scroller->Position=list->List_start;
Window_draw_slider(list->Scroller);
}
Window_redraw_list(list);
Display_cursor();
// Store the selected value as attribute2
Window_attribute2=list->List_start + list->Cursor_position;
// Return the control ID of the list.
return list->Number;
}
if (Key==SDLK_PAGEDOWN && (list->Cursor_position+list->List_start)<(list->Scroller->Nb_elements-1))
{
Key=0;
Hide_cursor();
if (list->Scroller->Nb_elementsScroller->Nb_visibles)
{
list->Cursor_position=list->Scroller->Nb_elements-1;
}
else if(list->Cursor_position!=list->Scroller->Nb_visibles-1)
{
list->Cursor_position=list->Scroller->Nb_visibles-1;
}
else
{
list->List_start+=list->Scroller->Nb_visibles;
if (list->List_start+list->Scroller->Nb_visibles>list->Scroller->Nb_elements)
{
list->List_start=list->Scroller->Nb_elements-list->Scroller->Nb_visibles;
}
// Mise jour du scroller
list->Scroller->Position=list->List_start;
Window_draw_slider(list->Scroller);
}
Window_redraw_list(list);
Display_cursor();
// Store the selected value as attribute2
Window_attribute2=list->List_start + list->Cursor_position;
// Return the control ID of the list.
return list->Number;
}
if (Key==SDLK_PAGEUP && (list->Cursor_position+list->List_start)>0)
{
Key=0;
Hide_cursor();
if(list->Cursor_position!=0)
{
list->Cursor_position=0;
}
else
{
list->List_start-=list->Scroller->Nb_visibles;
if (list->List_start<0)
{
list->List_start=0;
}
// Mise jour du scroller
list->Scroller->Position=list->List_start;
Window_draw_slider(list->Scroller);
}
Window_redraw_list(list);
Display_cursor();
// Store the selected value as attribute2
Window_attribute2=list->List_start + list->Cursor_position;
// Return the control ID of the list.
return list->Number;
}
if (Key == KEY_MOUSEWHEELUP && list->List_start>0)
{
list->Cursor_position+=list->List_start;
if (list->List_start>=3)
list->List_start-=3;
else
list->List_start=0;
list->Cursor_position-=list->List_start;
// On affiche nouveau la liste
Hide_cursor();
Window_redraw_list(list);
// Mise jour du scroller
list->Scroller->Position=list->List_start;
Window_draw_slider(list->Scroller);
Display_cursor();
}
if (Key==KEY_MOUSEWHEELDOWN && list->List_startScroller->Nb_elements-list->Scroller->Nb_visibles)
{
list->Cursor_position+=list->List_start;
list->List_start+=3;
if (list->List_start+list->Scroller->Nb_visibles>list->Scroller->Nb_elements)
{
list->List_start=list->Scroller->Nb_elements-list->Scroller->Nb_visibles;
}
list->Cursor_position-=list->List_start;
// On affiche nouveau la liste
Hide_cursor();
Window_redraw_list(list);
// Mise jour du scroller
list->Scroller->Position=list->List_start;
Window_draw_slider(list->Scroller);
Display_cursor();
}
}
}
}
return 0;
}
// Fonction qui sert remapper les parties sauvegardes derriere les
// fenetres ouvertes. C'est utilis par exemple par la fenetre de palette
// Qui remappe des couleurs, afin de propager les changements.
void Remap_window_backgrounds(byte * conversion_table, int Min_Y, int Max_Y)
{
int window_index;
byte* EDI;
int dx,cx;
for (window_index=0; window_indexMax_Y)
return;
if (dx+Window_stack[window_index].Pos_Y0;cx--)
{
*EDI = conversion_table[*EDI];
EDI ++;
}
}
}
}
void Delay_with_active_mouse(int speed)
{
Uint32 end;
byte original_mouse_k = Mouse_K;
end = SDL_GetTicks()+speed*10;
do
{
Get_input(20);
} while (Mouse_K == original_mouse_k && SDL_GetTicks()