~ubuntu-branches/ubuntu/maverick/grafx2/maverick

« back to all changes in this revision

Viewing changes to src/windows.c

  • Committer: Bazaar Package Importer
  • Author(s): Gürkan Sengün
  • Date: 2010-03-22 12:07:47 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20100322120747-g0jel6vf6mjkc53s
Tags: 2.2-1
* New upstream version, fixes FTBFS with binutils-gold. (Closes: #554742)
* Bump standards version to 3.8.4.
* debian/control: Add liblua5.1-0-dev and pkg-config to build depends.
* debian/rules: Drop dh_desktop call.
* debian/copyright: Update years.
* Switch to dpkg-source format version 3.0 (quilt).
* debian/watch: Added.
* Added patch to fix spelling errors in source code.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* vim:expandtab:ts=2 sw=2:
 
2
*/
 
3
/*  Grafx2 - The Ultimate 256-color bitmap paint program
 
4
 
 
5
    Copyright 2008      Franck Charlet
 
6
    Copyright 2007-2008 Adrien Destugues
 
7
    Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
 
8
 
 
9
    Grafx2 is free software; you can redistribute it and/or
 
10
    modify it under the terms of the GNU General Public License
 
11
    as published by the Free Software Foundation; version 2
 
12
    of the License.
 
13
 
 
14
    Grafx2 is distributed in the hope that it will be useful,
 
15
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
    GNU General Public License for more details.
 
18
 
 
19
    You should have received a copy of the GNU General Public License
 
20
    along with Grafx2; if not, see <http://www.gnu.org/licenses/>
 
21
 
 
22
********************************************************************************
 
23
 
 
24
    Graphical interface management functions (windows, menu, cursor)
 
25
*/
 
26
 
 
27
#include <math.h>
 
28
#include <stdlib.h> // atoi()
 
29
#include <string.h> // strncpy() strlen()
 
30
 
 
31
#include "windows.h"
 
32
 
 
33
#include "engine.h"
 
34
#include "errors.h"
 
35
#include "global.h"
 
36
#include "graph.h"
 
37
#include "input.h"
 
38
#include "misc.h"
 
39
#include "readline.h"
 
40
#include "sdlscreen.h"
 
41
 
 
42
/// Width of one layer button, in pixels before scaling
 
43
word Layer_button_width = 1;
 
44
 
 
45
// L'encapsulation tente une perc�e...ou un dernier combat.
 
46
 
 
47
// Nombre de cellules r�el dans la palette du menu
 
48
word Menu_cells_X;
 
49
word Palette_cells_X()
 
50
{
 
51
  return Menu_cells_X;
 
52
}
 
53
word Menu_cells_Y;
 
54
word Palette_cells_Y()
 
55
{
 
56
  return Menu_cells_Y;
 
57
}
 
58
 
 
59
// Affichage d'un pixel dans le menu (si visible)
 
60
void Pixel_in_menu(word bar, word x, word y, byte color)
 
61
{
 
62
  if (Menu_is_visible && Menu_bars[bar].Visible)
 
63
    Block(x*Menu_factor_X,(y+Menu_bars[bar].Top)*Menu_factor_Y+Menu_Y,Menu_factor_X,Menu_factor_Y,color);
 
64
}
 
65
 
 
66
// Affichage d'un pixel dans le menu et met a jour la bitmap de skin
 
67
void Pixel_in_menu_and_skin(word bar, word x, word y, byte color)
 
68
{
 
69
  Pixel_in_menu(bar, x, y, color);
 
70
  Menu_bars[bar].Skin[y*Menu_bars[bar].Skin_width + x] = color;  
 
71
}
 
72
 
 
73
// Affichage d'un pixel dans la fen�tre (la fen�tre doit �tre visible)
 
74
void Pixel_in_window(word x,word y,byte color)
 
75
{
 
76
    Block((x*Menu_factor_X)+Window_pos_X,(y*Menu_factor_Y)+Window_pos_Y,Menu_factor_X,Menu_factor_Y,color);
 
77
}
 
78
 
 
79
// Affichage d'un rectangle dans la fen�tre (la fen�tre doit �tre visible)
 
80
void Window_rectangle(word x_pos,word y_pos,word width,word height,byte color)
 
81
{
 
82
  Block((x_pos*Menu_factor_X)+Window_pos_X,(y_pos*Menu_factor_Y)+Window_pos_Y,width*Menu_factor_X,height*Menu_factor_Y,color);
 
83
}
 
84
 
 
85
 
 
86
// -- Affichages de diff�rents cadres dans une fen�tre -----------------------
 
87
 
 
88
  // -- Frame g�n�ral avec couleurs param�trables --
 
89
 
 
90
void Window_display_frame_generic(word x_pos,word y_pos,word width,word height,
 
91
                                    byte color_tl,byte color_br,byte color_s,byte color_tlc,byte color_brc)
 
92
// Param�tres de couleurs:
 
93
// color_tl =Bords Haut et Gauche
 
94
// color_br =Bords Bas et Droite
 
95
// color_s  =Coins Haut-Droite et Bas-Gauche
 
96
// color_tlc=Coin Haut-Gauche
 
97
// color_brc=Coin Bas-Droite
 
98
{
 
99
  // Bord haut (sans les extr�mit�s)
 
100
  Block(Window_pos_X+((x_pos+1)*Menu_factor_X),
 
101
        Window_pos_Y+(y_pos*Menu_factor_Y),
 
102
        (width-2)*Menu_factor_X,Menu_factor_Y,color_tl);
 
103
 
 
104
  // Bord bas (sans les extr�mit�s)
 
105
  Block(Window_pos_X+((x_pos+1)*Menu_factor_X),
 
106
        Window_pos_Y+((y_pos+height-1)*Menu_factor_Y),
 
107
        (width-2)*Menu_factor_X,Menu_factor_Y,color_br);
 
108
 
 
109
  // Bord gauche (sans les extr�mit�s)
 
110
  Block(Window_pos_X+(x_pos*Menu_factor_X),
 
111
        Window_pos_Y+((y_pos+1)*Menu_factor_Y),
 
112
        Menu_factor_X,(height-2)*Menu_factor_Y,color_tl);
 
113
 
 
114
  // Bord droite (sans les extr�mit�s)
 
115
  Block(Window_pos_X+((x_pos+width-1)*Menu_factor_X),
 
116
        Window_pos_Y+((y_pos+1)*Menu_factor_Y),
 
117
        Menu_factor_X,(height-2)*Menu_factor_Y,color_br);
 
118
 
 
119
  // Coin haut gauche
 
120
  Pixel_in_window(x_pos,y_pos,color_tlc);
 
121
  // Coin haut droite
 
122
  Pixel_in_window(x_pos+width-1,y_pos,color_s);
 
123
  // Coin bas droite
 
124
  Pixel_in_window(x_pos+width-1,y_pos+height-1,color_brc);
 
125
  // Coin bas gauche
 
126
  Pixel_in_window(x_pos,y_pos+height-1,color_s);
 
127
}
 
128
 
 
129
  // -- Frame dont tout le contour est d'une seule couleur --
 
130
 
 
131
void Window_display_frame_mono(word x_pos,word y_pos,word width,word height,byte color)
 
132
{
 
133
  Window_display_frame_generic(x_pos,y_pos,width,height,color,color,color,color,color);
 
134
}
 
135
 
 
136
  // -- Frame creux: fonc� en haut-gauche et clair en bas-droite --
 
137
 
 
138
void Window_display_frame_in(word x_pos,word y_pos,word width,word height)
 
139
{
 
140
  Window_display_frame_generic(x_pos,y_pos,width,height,MC_Dark,MC_White,MC_Light,MC_Dark,MC_White);
 
141
}
 
142
 
 
143
  // -- Frame bomb�: clair en haut-gauche et fonc� en bas-droite --
 
144
 
 
145
void Window_display_frame_out(word x_pos,word y_pos,word width,word height)
 
146
{
 
147
  Window_display_frame_generic(x_pos,y_pos,width,height,MC_White,MC_Dark,MC_Light,MC_White,MC_Dark);
 
148
}
 
149
 
 
150
  // -- Frame de s�paration: un cadre bomb� dans un cadre creux (3D!!!) --
 
151
 
 
152
void Window_display_frame(word x_pos,word y_pos,word width,word height)
 
153
{
 
154
  Window_display_frame_in(x_pos,y_pos,width,height);
 
155
  Window_display_frame_out(x_pos+1,y_pos+1,width-2,height-2);
 
156
}
 
157
 
 
158
 
 
159
//-- Affichages relatifs � la palette dans le menu ---------------------------
 
160
 
 
161
  // -- Affichage des couleurs courante (fore/back) de pinceau dans le menu --
 
162
 
 
163
void Display_foreback(void)
 
164
{
 
165
  if (Menu_is_visible && Menu_bars[MENUBAR_TOOLS].Visible)
 
166
  {
 
167
    Block((MENU_WIDTH-17)*Menu_factor_X,Menu_Y+Menu_factor_Y,Menu_factor_X<<4,Menu_factor_Y*7,Back_color);
 
168
    Block((MENU_WIDTH-13)*Menu_factor_X,Menu_Y+(Menu_factor_Y<<1),Menu_factor_X<<3,Menu_factor_Y*5,Fore_color);
 
169
 
 
170
    Update_rect((MENU_WIDTH-17)*Menu_factor_X,Menu_Y+Menu_factor_Y,Menu_factor_X<<4,Menu_factor_Y*7);
 
171
  }
 
172
}
 
173
 
 
174
/*! Get the top left corner for the palette cell of a color
 
175
    @param index Index of the color, starting at 0 for the top left one. Limited to Menu_cells_X/Menu_cells_Y.
 
176
*/
 
177
word Palette_cell_X(byte index)
 
178
{
 
179
  if (Config.Palette_vertical)
 
180
  {
 
181
    return (MENU_WIDTH+1+((index-First_color_in_palette)%Menu_cells_X)*Menu_palette_cell_width)*Menu_factor_X;
 
182
  }
 
183
  else
 
184
  {
 
185
    return (MENU_WIDTH+1+((index-First_color_in_palette)/Menu_cells_Y)*Menu_palette_cell_width)*Menu_factor_X;
 
186
  }
 
187
}
 
188
 
 
189
/*! Get the top left corner for the palette cell of a color
 
190
    @param index Index of the color, starting at 0 for the top left one. Limited to Menu_cells_X/Menu_cells_Y.
 
191
*/
 
192
word Palette_cell_Y(byte index)
 
193
{
 
194
  if (Config.Palette_vertical)
 
195
  {
 
196
    return Menu_Y+((1+(((index-First_color_in_palette)/Menu_cells_X)*(Menu_bars[MENUBAR_TOOLS].Height/Menu_cells_Y)))*Menu_factor_Y);
 
197
  }
 
198
  else
 
199
  {
 
200
    return Menu_Y+((1+(((index-First_color_in_palette)%Menu_cells_Y)*(Menu_bars[MENUBAR_TOOLS].Height/Menu_cells_Y)))*Menu_factor_Y);
 
201
  }
 
202
}
 
203
 
 
204
void Set_fore_color(byte color)
 
205
{
 
206
  byte old_fore_color = Fore_color;
 
207
  
 
208
  Fore_color=color;
 
209
  Reposition_palette();
 
210
  Display_foreback();
 
211
  Frame_menu_color(old_fore_color);
 
212
  Frame_menu_color(Fore_color);
 
213
}
 
214
 
 
215
void Set_back_color(byte color)
 
216
{
 
217
  byte old_back_color = Back_color;
 
218
  
 
219
  Back_color=color;
 
220
  Display_foreback();
 
221
  Frame_menu_color(old_back_color);
 
222
  Frame_menu_color(Back_color);
 
223
}
 
224
 
 
225
///
 
226
/// Redraw the cell in the menu palette for ::Fore_color.
 
227
/// This function checks bounds, it won't draw anything if Fore_color is not visible.
 
228
/// @param id: Color number to frame
 
229
void Frame_menu_color(byte id)
 
230
{
 
231
  word start_x,start_y,end_x,end_y;
 
232
  word index;
 
233
  word cell_height=Menu_bars[MENUBAR_TOOLS].Height/Menu_cells_Y;
 
234
  byte color;
 
235
  
 
236
  if (! Menu_bars[MENUBAR_TOOLS].Visible)
 
237
    return;
 
238
 
 
239
  if (id==Fore_color)
 
240
    color = MC_White;
 
241
  else if (id==Back_color)
 
242
    color = MC_Dark;
 
243
  else
 
244
    color = MC_Black;
 
245
 
 
246
  if ((id>=First_color_in_palette) && (id<First_color_in_palette+Menu_cells_X*Menu_cells_Y) && (Menu_is_visible))
 
247
  {
 
248
    if (Config.Separate_colors)
 
249
    {
 
250
      start_x=Palette_cell_X(id)-1*Menu_factor_X;
 
251
      start_y=Palette_cell_Y(id)-1*Menu_factor_Y;
 
252
 
 
253
      // TODO: if color is black, we are unselecting a color. If another color next to it is selected, we
 
254
      // will erase one edge of its selection square.
 
255
      // We should check for that here.
 
256
      // But we have to find which color is above and below (not so easy) and for the horizontal, check we
 
257
      // are not at the edge of the palette. This makes a lot of cases to handle.
 
258
      // Top
 
259
      Block(start_x,start_y,(Menu_palette_cell_width+1)*Menu_factor_X,Menu_factor_Y,color);
 
260
      // Bottom
 
261
      Block(start_x,start_y+cell_height*Menu_factor_Y,(Menu_palette_cell_width+1)*Menu_factor_X,Menu_factor_Y,color);
 
262
 
 
263
      // Left
 
264
      Block(start_x,start_y+Menu_factor_Y,Menu_factor_X,(cell_height -1)* Menu_factor_Y,color);
 
265
      //Right
 
266
      Block(start_x+(Menu_palette_cell_width*Menu_factor_X),start_y+Menu_factor_Y,Menu_factor_X,(cell_height -1)* Menu_factor_Y,color);
 
267
 
 
268
      Update_rect(start_x,start_y,(Menu_palette_cell_width+1)*Menu_factor_X,(cell_height+1)* Menu_factor_Y);
 
269
    }
 
270
    else
 
271
    {
 
272
      // Not separated colors
 
273
      start_x=Palette_cell_X(id);
 
274
      start_y=Palette_cell_Y(id);
 
275
 
 
276
      if (color==MC_Black)
 
277
      {
 
278
        // Color is not selected, no dotted lines
 
279
        Block(start_x,start_y,Menu_palette_cell_width*Menu_factor_X,
 
280
              cell_height*Menu_factor_Y,id);
 
281
 
 
282
        Update_rect(start_x,start_y,Menu_palette_cell_width*Menu_factor_X,cell_height*Menu_factor_Y);
 
283
      }
 
284
      else
 
285
      {
 
286
        end_x=Menu_palette_cell_width-1;
 
287
        end_y=cell_height-1;
 
288
 
 
289
        // Draw dotted lines
 
290
 
 
291
        // Top line
 
292
        for (index=0; index<=end_x; index++)
 
293
          Block(start_x+index*Menu_factor_X,start_y,
 
294
                Menu_factor_X,Menu_factor_Y,
 
295
                ((index)&1)?color:MC_Black);
 
296
        // Left line
 
297
        for (index=1; index<end_y; index++)
 
298
          Block(start_x,start_y+index*Menu_factor_Y,
 
299
                Menu_factor_X,Menu_factor_Y,
 
300
                ((index)&1)?color:MC_Black);
 
301
        // Right line
 
302
        for (index=1; index<end_y; index++)
 
303
          Block(start_x+end_x*Menu_factor_X,start_y+index*Menu_factor_Y,
 
304
                Menu_factor_X,Menu_factor_Y,
 
305
                ((index+end_x)&1)?color:MC_Black);
 
306
        // Bottom line
 
307
        for (index=0; index<=end_x; index++)
 
308
          Block(start_x+index*Menu_factor_X,start_y+end_y*Menu_factor_Y,
 
309
                Menu_factor_X,Menu_factor_Y,
 
310
                ((index+end_y)&1)?color:MC_Black);
 
311
 
 
312
        Update_rect(start_x*Menu_factor_X,start_y*Menu_factor_Y,Menu_palette_cell_width*Menu_factor_X,Menu_Y+cell_height*Menu_factor_Y);
 
313
      }
 
314
    }
 
315
  }
 
316
}
 
317
 
 
318
  // -- Afficher la palette dans le menu --
 
319
 
 
320
void Display_menu_palette(void)
 
321
{
 
322
  int color;
 
323
  byte cell_height=Menu_bars[MENUBAR_TOOLS].Height/Menu_cells_Y;
 
324
  // width: Menu_palette_cell_width
 
325
  
 
326
  if (Menu_is_visible && Menu_bars[MENUBAR_TOOLS].Visible)
 
327
  {
 
328
    Block(
 
329
      Menu_bars[MENUBAR_TOOLS].Width*Menu_factor_X,
 
330
      Menu_Y,
 
331
      Screen_width-(Menu_bars[MENUBAR_TOOLS].Width*Menu_factor_X),
 
332
      (Menu_bars[MENUBAR_TOOLS].Height)*Menu_factor_Y,
 
333
      MC_Black);
 
334
 
 
335
    if (Config.Separate_colors)
 
336
      for (color=First_color_in_palette;color<256&&(color-First_color_in_palette)<Menu_cells_X*Menu_cells_Y;color++)
 
337
        Block(Palette_cell_X(color),
 
338
              Palette_cell_Y(color),
 
339
              (Menu_palette_cell_width-1)*Menu_factor_X,
 
340
              (cell_height-1)*Menu_factor_Y,
 
341
              color);
 
342
    else
 
343
      for (color=First_color_in_palette;color<256&&color-First_color_in_palette<Menu_cells_X*Menu_cells_Y;color++)
 
344
        Block(Palette_cell_X(color),
 
345
              Palette_cell_Y(color),
 
346
              Menu_palette_cell_width*Menu_factor_X,
 
347
              cell_height * Menu_factor_Y,
 
348
              color);
 
349
 
 
350
    Frame_menu_color(Back_color);
 
351
    Frame_menu_color(Fore_color);
 
352
    Update_rect(MENU_WIDTH*Menu_factor_X,Menu_Y,Screen_width-(MENU_WIDTH*Menu_factor_X),(Menu_height-11)*Menu_factor_Y);
 
353
  }
 
354
}
 
355
 
 
356
  // -- Recalculer l'origine de la palette dans le menu pour rendre la
 
357
  //    Fore_color visible --
 
358
 
 
359
void Reposition_palette(void)
 
360
{
 
361
  byte old_color=First_color_in_palette;
 
362
  short cells;
 
363
  if (Config.Palette_vertical)
 
364
    cells=Menu_cells_X;
 
365
  else
 
366
    cells=Menu_cells_Y;
 
367
    
 
368
 
 
369
  if (Fore_color<First_color_in_palette)
 
370
  {
 
371
    while (Fore_color<First_color_in_palette)
 
372
      First_color_in_palette-=cells;
 
373
  }
 
374
  else
 
375
  {
 
376
    while (Fore_color>=First_color_in_palette+Menu_cells_X*Menu_cells_Y)
 
377
      First_color_in_palette+=cells;
 
378
  }
 
379
  if (old_color!=First_color_in_palette)
 
380
    Display_menu_palette();
 
381
}
 
382
 
 
383
void Change_palette_cells()
 
384
{
 
385
  // On initialise avec la configuration de l'utilisateur
 
386
  Menu_cells_X=Config.Palette_cells_X;
 
387
  Menu_cells_Y=Config.Palette_cells_Y;
 
388
  // Mais on sait jamais
 
389
  if (Menu_cells_X<1)
 
390
    Menu_cells_X=1;
 
391
  if (Menu_cells_Y<1)
 
392
    Menu_cells_Y=1;
 
393
  
 
394
  while (1)
 
395
  {
 
396
    Menu_palette_cell_width = ((Screen_width/Menu_factor_X)-(MENU_WIDTH+2)) / Menu_cells_X;
 
397
 
 
398
    // Si �a tient, c'est bon. Sinon, on retente avec une colonne de moins
 
399
    if (Menu_palette_cell_width>2)
 
400
      break;
 
401
    Menu_cells_X--;
 
402
  }
 
403
  
 
404
  // Cale First_color_in_palette sur un multiple du nombre de cellules (arrondi inf�rieur)
 
405
  if (Config.Palette_vertical)
 
406
    First_color_in_palette=First_color_in_palette/Menu_cells_X*Menu_cells_X;
 
407
  else
 
408
    First_color_in_palette=First_color_in_palette/Menu_cells_Y*Menu_cells_Y;
 
409
 
 
410
  // Si le nombre de cellules a beaucoup augment� et qu'on �tait pr�s de
 
411
  // la fin, il faut reculer First_color_in_palette pour montrer plein
 
412
  // de couleurs.
 
413
  if ((int)First_color_in_palette+(Menu_cells_Y)*Menu_cells_X*2>=256)
 
414
    First_color_in_palette=255/Menu_cells_Y*Menu_cells_Y-(Menu_cells_X-1)*Menu_cells_Y;
 
415
 
 
416
  // Mise � jour de la taille du bouton dans le menu. C'est pour pas que
 
417
  // la bordure noire soit active.
 
418
  Buttons_Pool[BUTTON_CHOOSE_COL].Width=(Menu_palette_cell_width*Menu_cells_X)-1;
 
419
  Buttons_Pool[BUTTON_CHOOSE_COL].Height=(Menu_height-11)/Menu_cells_Y*Menu_cells_Y-1;
 
420
}
 
421
 
 
422
// Retrouve la couleur sur laquelle pointe le curseur souris.
 
423
// Cette fonction suppose qu'on a d�ja v�rifi� que le curseur est dans
 
424
// la zone rectangulaire du BUTTON_CHOOSE_COL
 
425
// La fonction renvoie -1 si on est "trop � gauche" (pas possible)
 
426
// ou apr�s la couleur 255 (Ce qui peut arriver si la palette est affich�e
 
427
// avec un nombre de lignes qui n'est pas une puissance de deux.)
 
428
int Pick_color_in_palette()
 
429
{
 
430
  int color;
 
431
  int line;
 
432
  int column;
 
433
 
 
434
  line=(((Mouse_Y-Menu_Y)/Menu_factor_Y)-2)/((Menu_bars[MENUBAR_TOOLS].Height)/Menu_cells_Y);
 
435
  column=(((Mouse_X/Menu_factor_X)-(MENU_WIDTH+1))/Menu_palette_cell_width);
 
436
  if (Config.Palette_vertical)
 
437
  {
 
438
    color=First_color_in_palette+line*Menu_cells_X+column;
 
439
  }
 
440
  else
 
441
  {
 
442
    color=First_color_in_palette+line+column*Menu_cells_Y;
 
443
  }
 
444
  if (color<0 || color>255)
 
445
    return -1;
 
446
  return color;
 
447
}
 
448
 
 
449
/// Draws a solid textured area, to the right of a toolbar.
 
450
void Draw_bar_remainder(word current_menu, word x_off)
 
451
{
 
452
  word y_pos;
 
453
  word x_pos;
 
454
 
 
455
  for (y_pos=0;y_pos<Menu_bars[current_menu].Height;y_pos++)
 
456
    for (x_pos=x_off;x_pos<Screen_width/Menu_factor_X;x_pos++)
 
457
      Pixel_in_menu(current_menu, x_pos, y_pos, Menu_bars[current_menu].Skin[y_pos * Menu_bars[current_menu].Skin_width + Menu_bars[current_menu].Skin_width - 2 + (x_pos&1)]);
 
458
}
 
459
 
 
460
            
 
461
/// Display / update the layer menubar
 
462
void Display_layerbar(void)
 
463
{
 
464
  word x_off=0;
 
465
  word button_width = LAYER_SPRITE_WIDTH;
 
466
  word button_number = Main_backups->Pages->Nb_layers;
 
467
  word horiz_space;
 
468
  word current_button;
 
469
  word repeats=1;
 
470
  
 
471
  if (! Menu_bars[MENUBAR_LAYERS].Visible)
 
472
    return;
 
473
  
 
474
  // Available space in pixels
 
475
  horiz_space = Screen_width / Menu_factor_X - Menu_bars[MENUBAR_LAYERS].Skin_width;
 
476
  
 
477
  // Don't display all buttons if not enough room
 
478
  if (horiz_space/button_width < button_number)
 
479
    button_number = horiz_space/button_width;
 
480
  // Only 16 icons at the moment
 
481
  if (button_number > 16) // can be different from MAX_NB_LAYERS
 
482
    button_number = 16;
 
483
 
 
484
  // Enlarge the buttons themselves if there's enough room
 
485
  while (button_number*(button_width+2) < horiz_space && repeats < 20)
 
486
  {
 
487
    repeats+=1;
 
488
    button_width+=2;
 
489
  }
 
490
  
 
491
  x_off=Menu_bars[MENUBAR_LAYERS].Skin_width;
 
492
  for (current_button=0; current_button<button_number; current_button++)
 
493
  {
 
494
    word x_pos;
 
495
    word y_pos;
 
496
    word sprite_index;
 
497
    
 
498
    if (Main_current_layer == current_button)
 
499
      sprite_index=1;
 
500
    else if (Main_layers_visible & (1 << current_button))
 
501
      sprite_index=0;
 
502
    else
 
503
      sprite_index=2;
 
504
    
 
505
    
 
506
    for (y_pos=0;y_pos<LAYER_SPRITE_HEIGHT;y_pos++)
 
507
    {
 
508
      word source_x=0;
 
509
      
 
510
      for (source_x=0;source_x<LAYER_SPRITE_WIDTH;source_x++)
 
511
      {
 
512
        short i = 1;
 
513
        
 
514
        // This stretches a button, by duplicating the 2nd from right column 
 
515
        // and 3rd column from left.    
 
516
        if (source_x == 1 || (source_x == LAYER_SPRITE_WIDTH-3))
 
517
          i=repeats;
 
518
        
 
519
        for (;i>0; i--)
 
520
        {
 
521
          Pixel_in_menu(MENUBAR_LAYERS, x_pos + x_off, y_pos, Gfx->Layer_sprite[sprite_index][current_button][y_pos][source_x]);
 
522
          x_pos++;
 
523
        }
 
524
      }
 
525
      // Next line
 
526
      x_pos=0;
 
527
    }    
 
528
    // Next button
 
529
    x_off+=button_width;
 
530
  }
 
531
  // Texture any remaining space to the right.
 
532
  // This overwrites any junk like deleted buttons.
 
533
  Draw_bar_remainder(MENUBAR_LAYERS, x_off);
 
534
  
 
535
  // Update the active area of the layers pseudo-button
 
536
  Buttons_Pool[BUTTON_LAYER_SELECT].Width = button_number * button_width;
 
537
  
 
538
  // Required to determine which layer button is clicked
 
539
  Layer_button_width = button_width;
 
540
  
 
541
  // A screen refresh required by some callers
 
542
  Update_rect(
 
543
    Menu_bars[MENUBAR_LAYERS].Skin_width, 
 
544
    Menu_Y+Menu_bars[MENUBAR_LAYERS].Top*Menu_factor_Y, 
 
545
    horiz_space*Menu_factor_X, 
 
546
    Menu_bars[MENUBAR_LAYERS].Height*Menu_factor_Y);
 
547
}
 
548
 
 
549
 
 
550
/// Display the whole menu
 
551
void Display_menu(void)
 
552
{
 
553
  word x_pos;
 
554
  word y_pos;
 
555
  int8_t current_menu;
 
556
  char str[4];
 
557
 
 
558
 
 
559
  if (Menu_is_visible)
 
560
  {
 
561
    // display menu sprite
 
562
    for (current_menu = MENUBAR_COUNT - 1; current_menu >= 0; current_menu --)
 
563
    {
 
564
      if(Menu_bars[current_menu].Visible)
 
565
      {
 
566
        // Skinned area
 
567
        for (y_pos=0;y_pos<Menu_bars[current_menu].Height;y_pos++)
 
568
          for (x_pos=0;x_pos<Menu_bars[current_menu].Skin_width;x_pos++)
 
569
            Pixel_in_menu(current_menu, x_pos, y_pos, Menu_bars[current_menu].Skin[y_pos * Menu_bars[current_menu].Skin_width + x_pos]);
 
570
 
 
571
        if (current_menu == MENUBAR_LAYERS)
 
572
        {
 
573
          // The layerbar has its own display, for the whole length.
 
574
          Display_layerbar();
 
575
        }
 
576
        else
 
577
        {
 
578
          // If some area is remaining to the right, texture it with a copy of
 
579
          // the last two columns
 
580
          Draw_bar_remainder(current_menu, Menu_bars[current_menu].Skin_width);
 
581
        }
 
582
        
 
583
        // Next bar
 
584
      }
 
585
    }
 
586
 
 
587
    // Display palette
 
588
    Display_menu_palette();
 
589
 
 
590
    // Display selected colors
 
591
    Display_foreback();
 
592
 
 
593
 
 
594
    if (!Windows_open)
 
595
    {
 
596
      if ((Mouse_Y<Menu_Y) && // Mouse in the picture area
 
597
          ( (!Main_magnifier_mode) || (Mouse_X<Main_separator_position) || (Mouse_X>=Main_X_zoom) ))
 
598
      {
 
599
        // Prepare display of XY coordinates even if in some cases they will be
 
600
        // erased with some other text
 
601
        if ( (Current_operation!=OPERATION_COLORPICK)
 
602
          && (Current_operation!=OPERATION_REPLACE) )
 
603
          Print_in_menu("X:       Y:             ",0);
 
604
        else
 
605
        {
 
606
          // The colorpicker display the color id between the parentheses
 
607
          Print_in_menu("X:       Y:       (    )",0);
 
608
          Num2str(Colorpicker_color,str,3);
 
609
          Print_in_menu(str,20);
 
610
          Print_general(170*Menu_factor_X,Menu_status_Y," ",0,Colorpicker_color);
 
611
        }
 
612
        Print_coordinates();
 
613
      }
 
614
      Print_filename();
 
615
    }
 
616
    // Now update the area: menu height and whole screen width (including palette)
 
617
    Update_rect(0,Menu_Y,Screen_width,Menu_height*Menu_factor_Y);
 
618
  }
 
619
}
 
620
 
 
621
// -- Affichage de texte -----------------------------------------------------
 
622
 
 
623
  // -- Afficher une cha�ne n'importe o� � l'�cran --
 
624
 
 
625
void Print_general(short x,short y,const char * str,byte text_color,byte background_color)
 
626
{
 
627
  word  index;
 
628
  int x_pos;
 
629
  int y_pos;
 
630
  byte *font_pixel;
 
631
  short real_x;
 
632
  short real_y;
 
633
  byte repeat_menu_x_factor;
 
634
  byte repeat_menu_y_factor;
 
635
 
 
636
  real_y=y;
 
637
  for (y_pos=0;y_pos<8<<3;y_pos+=1<<3)
 
638
  {
 
639
    real_x=0; // Position dans le buffer
 
640
    for (index=0;str[index]!='\0';index++)
 
641
    {
 
642
      // Pointeur sur le premier pixel du caract�re
 
643
      font_pixel=Menu_font+(((unsigned char)str[index])<<6);
 
644
      for (x_pos=0;x_pos<8;x_pos+=1)
 
645
        for (repeat_menu_x_factor=0;repeat_menu_x_factor<Menu_factor_X*Pixel_width;repeat_menu_x_factor++)
 
646
          Horizontal_line_buffer[real_x++]=*(font_pixel+x_pos+y_pos)?text_color:background_color;
 
647
    }
 
648
    for (repeat_menu_y_factor=0;repeat_menu_y_factor<Menu_factor_Y;repeat_menu_y_factor++)
 
649
      Display_line_fast(x,real_y++,index*Menu_factor_X*8,Horizontal_line_buffer);
 
650
  }
 
651
}
 
652
 
 
653
/// Draws a char in a window
 
654
void Print_char_in_window(short x_pos,short y_pos,const unsigned char c,byte text_color,byte background_color)
 
655
{
 
656
  short x,y;
 
657
  byte *pixel;
 
658
  x_pos=(x_pos*Menu_factor_X)+Window_pos_X;
 
659
  y_pos=(y_pos*Menu_factor_Y)+Window_pos_Y;
 
660
  // Premier pixel du caract�re
 
661
  pixel=Menu_font + (c<<6);
 
662
  
 
663
  for (y=0;y<8;y++)
 
664
    for (x=0;x<8;x++)
 
665
      Block(x_pos+(x*Menu_factor_X), y_pos+(y*Menu_factor_Y),
 
666
            Menu_factor_X, Menu_factor_Y,
 
667
            (*(pixel++)?text_color:background_color));
 
668
}
 
669
 
 
670
///Draws a char in a window, checking for bounds
 
671
void Print_in_window_limited(short x,short y,const char * str,byte size,byte text_color,byte background_color)
 
672
{
 
673
  char display_string[256];
 
674
  strncpy(display_string, str, size);
 
675
  display_string[size]='\0';
 
676
 
 
677
  if (strlen(str) > size)
 
678
  {
 
679
    display_string[size-1]=ELLIPSIS_CHARACTER;
 
680
  }
 
681
  Print_in_window(x, y, display_string, text_color, background_color);
 
682
}
 
683
 
 
684
/// Draws a string in a window
 
685
void Print_in_window(short x,short y,const char * str,byte text_color,byte background_color)
 
686
{
 
687
  Print_general((x*Menu_factor_X)+Window_pos_X,
 
688
                (y*Menu_factor_Y)+Window_pos_Y,
 
689
                str,text_color,background_color);
 
690
  Update_rect(x*Menu_factor_X+Window_pos_X,y*Menu_factor_Y+Window_pos_Y,8*Menu_factor_X*strlen(str),8*Menu_factor_Y);
 
691
}
 
692
 
 
693
// Draws a string in the menu's status bar
 
694
void Print_in_menu(const char * str, short position)
 
695
{
 
696
  Print_general((18+(position<<3))*Menu_factor_X,Menu_status_Y,str,MC_Black,MC_Light);
 
697
  Update_rect((18+(position<<3))*Menu_factor_X,Menu_status_Y,strlen(str)*8*Menu_factor_X,8*Menu_factor_Y);
 
698
}
 
699
 
 
700
/// Draws the mouse coordinates on the menu
 
701
/// Only update the digits and doesn't refresh the "X: Y:" labels. This function needs to be fast as it is called each time the mouse moves.
 
702
void Print_coordinates(void)
 
703
{
 
704
  char temp[5];
 
705
 
 
706
  if (Menu_is_visible && !Cursor_in_menu)
 
707
  {
 
708
    if ( (Current_operation==OPERATION_COLORPICK)
 
709
      || (Current_operation==OPERATION_REPLACE) )
 
710
    {
 
711
      if ( (Paintbrush_X>=0) && (Paintbrush_Y>=0)
 
712
        && (Paintbrush_X<Main_image_width)
 
713
        && (Paintbrush_Y<Main_image_height) )
 
714
        Colorpicker_color=Read_pixel_from_current_screen(Paintbrush_X,Paintbrush_Y);
 
715
      else
 
716
        Colorpicker_color=0;
 
717
      Colorpicker_X=Paintbrush_X;
 
718
      Colorpicker_Y=Paintbrush_Y;
 
719
 
 
720
      Num2str(Colorpicker_color,temp,3);
 
721
      Print_in_menu(temp,20);
 
722
      Print_general(170*Menu_factor_X,Menu_status_Y," ",0,Colorpicker_color);
 
723
      Update_rect(170*Menu_factor_X,Menu_status_Y,8*Menu_factor_X,8*Menu_factor_Y);
 
724
    }
 
725
 
 
726
    Num2str((dword)Paintbrush_X,temp,4);
 
727
    Print_in_menu(temp,2);
 
728
    Num2str((dword)Paintbrush_Y,temp,4);
 
729
    Print_in_menu(temp,11);
 
730
  }
 
731
}
 
732
 
 
733
  // -- Afficher le nom du fichier dans le menu --
 
734
 
 
735
void Print_filename(void)
 
736
{
 
737
  word max_size;
 
738
  word string_size;
 
739
  char display_string[256];
 
740
 
 
741
  // Determine maximum size, in characters
 
742
  max_size = 12 + (Screen_width / Menu_factor_X - 320) / 8;
 
743
  
 
744
  string_size = strlen(Main_backups->Pages->Filename);
 
745
  
 
746
  // Partial copy of the name
 
747
  strncpy(display_string, Main_backups->Pages->Filename, max_size);
 
748
  display_string[max_size]='\0';
 
749
 
 
750
  if (string_size > max_size)
 
751
  {
 
752
    string_size = max_size;
 
753
    display_string[string_size-1]=ELLIPSIS_CHARACTER;
 
754
  }
 
755
  // Erase whole area
 
756
  Block(Screen_width-max_size*8*Menu_factor_X,
 
757
    Menu_status_Y,Menu_factor_X*max_size*8,Menu_factor_Y<<3,MC_Light);
 
758
  // Print
 
759
  Print_general(Screen_width-(string_size<<3)*Menu_factor_X,Menu_status_Y,display_string,MC_Black,MC_Light);
 
760
}
 
761
 
 
762
// Fonction d'affichage d'une chaine num�rique avec une fonte tr�s fine
 
763
// Sp�cialis�e pour les compteurs RGB
 
764
void Print_counter(short x,short y,const char * str,byte text_color,byte background_color)
 
765
{
 
766
  // Macros pour �crire des litteraux binaires.
 
767
  // Ex: Ob(11110000) == 0xF0
 
768
  #define Ob(x)  ((unsigned)Ob_(0 ## x ## uL))
 
769
  #define Ob_(x) ((x & 1) | (x >> 2 & 2) | (x >> 4 & 4) | (x >> 6 & 8) |                \
 
770
          (x >> 8 & 16) | (x >> 10 & 32) | (x >> 12 & 64) | (x >> 14 & 128))
 
771
 
 
772
  byte thin_font[14][8] = {
 
773
   { // 0
 
774
    Ob(00011100),
 
775
    Ob(00110110),
 
776
    Ob(00110110),
 
777
    Ob(00110110),
 
778
    Ob(00110110),
 
779
    Ob(00110110),
 
780
    Ob(00110110),
 
781
    Ob(00011100)
 
782
   },
 
783
   { // 1
 
784
    Ob(00001100),
 
785
    Ob(00011100),
 
786
    Ob(00111100),
 
787
    Ob(00001100),
 
788
    Ob(00001100),
 
789
    Ob(00001100),
 
790
    Ob(00001100),
 
791
    Ob(00001100)
 
792
   },
 
793
   { // 2
 
794
    Ob(00011100),
 
795
    Ob(00110110),
 
796
    Ob(00000110),
 
797
    Ob(00000110),
 
798
    Ob(00000110),
 
799
    Ob(00001100),
 
800
    Ob(00011000),
 
801
    Ob(00111110)
 
802
   },
 
803
   { // 3
 
804
    Ob(00011100),
 
805
    Ob(00110110),
 
806
    Ob(00000110),
 
807
    Ob(00001100),
 
808
    Ob(00000110),
 
809
    Ob(00000110),
 
810
    Ob(00110110),
 
811
    Ob(00011100)
 
812
   },
 
813
   { // 4
 
814
    Ob(00001100),
 
815
    Ob(00001100),
 
816
    Ob(00011000),
 
817
    Ob(00011000),
 
818
    Ob(00110000),
 
819
    Ob(00110100),
 
820
    Ob(00111110),
 
821
    Ob(00000100)
 
822
   },
 
823
   { // 5
 
824
    Ob(00111110),
 
825
    Ob(00110000),
 
826
    Ob(00110000),
 
827
    Ob(00111100),
 
828
    Ob(00000110),
 
829
    Ob(00000110),
 
830
    Ob(00110110),
 
831
    Ob(00011100)
 
832
   },
 
833
   { // 6
 
834
    Ob(00011100),
 
835
    Ob(00110110),
 
836
    Ob(00110000),
 
837
    Ob(00111100),
 
838
    Ob(00110110),
 
839
    Ob(00110110),
 
840
    Ob(00110110),
 
841
    Ob(00011100)
 
842
   },
 
843
   { // 7
 
844
    Ob(00111110),
 
845
    Ob(00000110),
 
846
    Ob(00000110),
 
847
    Ob(00001100),
 
848
    Ob(00011000),
 
849
    Ob(00011000),
 
850
    Ob(00011000),
 
851
    Ob(00011000)
 
852
   },
 
853
   { // 8
 
854
    Ob(00011100),
 
855
    Ob(00110110),
 
856
    Ob(00110110),
 
857
    Ob(00011100),
 
858
    Ob(00110110),
 
859
    Ob(00110110),
 
860
    Ob(00110110),
 
861
    Ob(00011100)
 
862
   },
 
863
   { // 9
 
864
    Ob(00011100),
 
865
    Ob(00110110),
 
866
    Ob(00110110),
 
867
    Ob(00011110),
 
868
    Ob(00000110),
 
869
    Ob(00000110),
 
870
    Ob(00110110),
 
871
    Ob(00011100)
 
872
   },
 
873
   { // (espace)
 
874
    Ob(00000000),
 
875
    Ob(00000000),
 
876
    Ob(00000000),
 
877
    Ob(00000000),
 
878
    Ob(00000000),
 
879
    Ob(00000000),
 
880
    Ob(00000000),
 
881
    Ob(00000000)
 
882
   },
 
883
   { // +
 
884
    Ob(00000000),
 
885
    Ob(00001000),
 
886
    Ob(00001000),
 
887
    Ob(00111110),
 
888
    Ob(00001000),
 
889
    Ob(00001000),
 
890
    Ob(00000000),
 
891
    Ob(00000000)
 
892
   },
 
893
   { // -
 
894
    Ob(00000000),
 
895
    Ob(00000000),
 
896
    Ob(00000000),
 
897
    Ob(00111110),
 
898
    Ob(00000000),
 
899
    Ob(00000000),
 
900
    Ob(00000000),
 
901
    Ob(00000000)
 
902
   },
 
903
   { // +-
 
904
    Ob(00001000),
 
905
    Ob(00001000),
 
906
    Ob(00111110),
 
907
    Ob(00001000),
 
908
    Ob(00001000),
 
909
    Ob(00000000),
 
910
    Ob(00111110),
 
911
    Ob(00000000)
 
912
   } };
 
913
 
 
914
  word  index;
 
915
  short x_pos;
 
916
  short y_pos;
 
917
  for (index=0;str[index]!='\0';index++)
 
918
  {
 
919
    int char_number;
 
920
    switch(str[index])
 
921
    {
 
922
      case '0':
 
923
      case '1':
 
924
      case '2':
 
925
      case '3':
 
926
      case '4':
 
927
      case '5':
 
928
      case '6':
 
929
      case '7':
 
930
      case '8':
 
931
      case '9':
 
932
        char_number=str[index]-'0';
 
933
        break;
 
934
      case ' ':
 
935
      default:
 
936
        char_number=10;
 
937
        break;
 
938
      case '+':
 
939
        char_number=11;
 
940
        break;
 
941
      case '-':
 
942
        char_number=12;
 
943
        break;
 
944
      case '�':
 
945
        char_number=13;
 
946
        break;
 
947
    }
 
948
    for (y_pos=0;y_pos<8;y_pos++)
 
949
    {
 
950
      for (x_pos=0;x_pos<6;x_pos++)
 
951
      {
 
952
        byte color = (thin_font[char_number][y_pos] & (1 << (6-x_pos))) ? text_color:background_color;
 
953
        Pixel_in_window(x+(index*6+x_pos),y+y_pos,color);
 
954
      }
 
955
    }
 
956
  }
 
957
  Update_rect(Window_pos_X+x*Menu_factor_X,Window_pos_Y+y*Menu_factor_Y,strlen(str)*Menu_factor_X*6,8*Menu_factor_Y);
 
958
}
 
959
 
 
960
 
 
961
 
 
962
///
 
963
/// Window asking for confirmation before an action is performed.
 
964
/// This function is able to display multi-line messages and
 
965
/// center the lines, but the carriage returns have to be explicit.
 
966
/// The function will clip the message in case of problem.
 
967
/// @return 1 if user pressed OK, 0 if CANCEL
 
968
byte Confirmation_box(char * message)
 
969
{
 
970
  short clicked_button;
 
971
  word  window_width = 120;
 
972
  word  nb_lines = 1;
 
973
  const char *c = message;
 
974
  short current_length=0;
 
975
  short current_line;
 
976
 
 
977
  // Count lines, and measure max line length
 
978
  for (c=message; *c != '\0'; c++)
 
979
  {
 
980
    if (*c == '\n')
 
981
    {
 
982
      current_length=0;
 
983
      nb_lines++;
 
984
    }
 
985
    else
 
986
    {
 
987
      current_length++;
 
988
      window_width=Max(window_width, (current_length<<3)+20);
 
989
    }
 
990
  }
 
991
  // Safety
 
992
  if (window_width>310)
 
993
    window_width=310;
 
994
 
 
995
  Open_window(window_width,52+(nb_lines<<3),"Confirmation");
 
996
 
 
997
  c=message;
 
998
  for (current_line=0; current_line < nb_lines; current_line++)
 
999
  {
 
1000
    char * next_eol;
 
1001
    char display_string[36+1];
 
1002
    
 
1003
    next_eol = strchr(c, '\n');
 
1004
    if (next_eol==NULL) // last line
 
1005
      current_length = strlen(c);
 
1006
    else
 
1007
      current_length = next_eol-c;
 
1008
 
 
1009
    // Safeguard
 
1010
    if (current_length>36)
 
1011
      current_length=36;
 
1012
    // Copy part of string in null-terminated buffer
 
1013
    strncpy(display_string, c, current_length);
 
1014
    display_string[current_length]='\0';
 
1015
 
 
1016
    Print_in_window((window_width>>1)-(current_length<<2), 20+(current_line<<3), display_string, MC_Black, MC_Light);
 
1017
    
 
1018
    c += current_length;
 
1019
    if (*c == '\n')
 
1020
      c++;
 
1021
  }
 
1022
 
 
1023
  Window_set_normal_button((window_width/3)-20     ,29+(nb_lines<<3),40,14,"Yes",1,1,SDLK_y); // 1
 
1024
  Window_set_normal_button(((window_width<<1)/3)-20,29+(nb_lines<<3),40,14,"No" ,1,1,SDLK_n); // 2
 
1025
 
 
1026
  Update_rect(Window_pos_X, Window_pos_Y, Window_width*Menu_factor_X, Window_height*Menu_factor_Y);
 
1027
 
 
1028
  Display_cursor();
 
1029
 
 
1030
  do
 
1031
  {
 
1032
    clicked_button=Window_clicked_button();
 
1033
    if (Key==SDLK_RETURN) clicked_button=1;
 
1034
    if (Key==KEY_ESC) clicked_button=2;
 
1035
  }
 
1036
  while (clicked_button<=0);
 
1037
  Key=0;
 
1038
 
 
1039
  Close_window();
 
1040
  Display_cursor();
 
1041
 
 
1042
  return (clicked_button==1)? 1 : 0;
 
1043
}
 
1044
 
 
1045
 
 
1046
/// Window that allows you to enter a single value
 
1047
int Requester_window(char* message, int initial_value)
 
1048
{
 
1049
  short clicked_button = 0;
 
1050
  word window_width;
 
1051
  char str[10];
 
1052
 
 
1053
  window_width=(strlen(message)<<3)+20;
 
1054
 
 
1055
  if (window_width<120)
 
1056
    window_width = 120;
 
1057
 
 
1058
  Open_window(window_width, 60, "Request");
 
1059
 
 
1060
  Print_in_window((window_width>>1)-(strlen(message)<<2), 20, message,
 
1061
    MC_Black, MC_Light);
 
1062
  sprintf(str, "%d", initial_value);
 
1063
  Window_set_input_button(10, 37, 4); // 1
 
1064
  Print_in_window(11, 39, str, MC_Black, MC_Light);
 
1065
  Window_set_normal_button(60 ,37,40,14,"OK",1,1,SDLK_y); // 2
 
1066
  Window_set_normal_button(130,37,60,14,"Cancel" ,1,1,SDLK_n); // 3
 
1067
 
 
1068
  Update_rect(Window_pos_X, Window_pos_Y, Menu_factor_X * window_width,
 
1069
    Menu_factor_Y * 60);
 
1070
  Display_cursor();
 
1071
 
 
1072
  do
 
1073
  {
 
1074
    clicked_button = Window_clicked_button();
 
1075
    if (clicked_button == 1)
 
1076
      Readline(11, 39, str, 4, 1);
 
1077
    if (Key == SDLK_ESCAPE) clicked_button = 2;
 
1078
  }
 
1079
  while (clicked_button <= 0);
 
1080
 
 
1081
  Key = 0;
 
1082
 
 
1083
  Close_window();
 
1084
  Display_cursor();
 
1085
 
 
1086
  return clicked_button==2?-1:atoi(str);
 
1087
}
 
1088
 
 
1089
 
 
1090
/// Window that show a warning message and wait for a click on the OK button
 
1091
void Warning_message(char * message)
 
1092
{
 
1093
  short clicked_button;
 
1094
  word  window_width;
 
1095
 
 
1096
  window_width=(strlen(message)<<3)+20;
 
1097
  if (window_width<120)
 
1098
    window_width=120;
 
1099
 
 
1100
  Open_window(window_width,60,"Warning!");
 
1101
 
 
1102
  Print_in_window((window_width>>1)-(strlen(message)<<2),20,message,MC_Black,MC_Light);
 
1103
  Window_set_normal_button((window_width>>1)-20     ,37,40,14,"OK",1,1,SDLK_RETURN); // 1
 
1104
  Update_rect(Window_pos_X,Window_pos_Y,Menu_factor_X*window_width,Menu_factor_Y*60);
 
1105
  Display_cursor();
 
1106
 
 
1107
  do
 
1108
    clicked_button=Window_clicked_button();
 
1109
  while ((clicked_button<=0) && (Key!=KEY_ESC) && (Key!=SDLK_o));
 
1110
  Key=0;
 
1111
 
 
1112
  Close_window();
 
1113
  Display_cursor();
 
1114
}
 
1115
 
 
1116
/// Window that shows a big message (up to 34x12), and waits for a click on OK.
 
1117
/// On call: Cursor must be displayed
 
1118
/// On exit: Cursor is displayed
 
1119
void Verbose_message(const char *caption, const char * message )
 
1120
{
 
1121
  short clicked_button;
 
1122
  int line;
 
1123
  int last_space;
 
1124
  int nb_char;
 
1125
  char buffer[36];
 
1126
  byte original_cursor_shape = Cursor_shape;
 
1127
 
 
1128
  
 
1129
  Open_window(300,160,caption);
 
1130
  
 
1131
  // Word-wrap the message
 
1132
  for (line=0; line < 12 && *message!='\0'; line++)
 
1133
  {
 
1134
    last_space = -1;
 
1135
    for (nb_char=0; nb_char<35 && message[nb_char]!='\0'; nb_char++)
 
1136
    {
 
1137
      buffer[nb_char]=message[nb_char];
 
1138
      if (message[nb_char] == ' ')
 
1139
      {
 
1140
        last_space = nb_char;
 
1141
      }
 
1142
      else if (message[nb_char] == '\n')
 
1143
      {
 
1144
        last_space = nb_char;
 
1145
        break;
 
1146
      }
 
1147
    }
 
1148
    // Close line buffer
 
1149
    if (message[nb_char]=='\0' || last_space == -1)
 
1150
      last_space = nb_char;
 
1151
    buffer[last_space]='\0';
 
1152
    
 
1153
    // Print
 
1154
    Print_in_window(10,20+line*8,buffer,MC_Black,MC_Light);
 
1155
    
 
1156
    // Next line
 
1157
    message=message+last_space;
 
1158
    // Strip at most one carriage return and any leading spaces
 
1159
    if (*message == '\n')
 
1160
      message++;
 
1161
    while (*message == ' ')
 
1162
      message++;
 
1163
  }
 
1164
 
 
1165
  Window_set_normal_button(300/2-20,160-23,40,14,"OK",1,1,SDLK_RETURN); // 1
 
1166
  Update_window_area(0,0,Window_width,Window_height);
 
1167
  Cursor_shape=CURSOR_SHAPE_ARROW;
 
1168
  Display_cursor();
 
1169
 
 
1170
  do
 
1171
    clicked_button=Window_clicked_button();
 
1172
  while ((clicked_button<=0) && (Key!=KEY_ESC) && (Key!=SDLK_o));
 
1173
  Key=0;
 
1174
 
 
1175
  Close_window();
 
1176
  Cursor_shape=original_cursor_shape;
 
1177
  Display_cursor();
 
1178
}
 
1179
 
 
1180
  // -- Redessiner le sprite d'un bouton dans le menu --
 
1181
 
 
1182
void Display_sprite_in_menu(int btn_number,int sprite_number)
 
1183
{
 
1184
  word x_pos;
 
1185
  word y_pos;
 
1186
  word menu_x_pos;
 
1187
  word menu_y_pos;
 
1188
  byte color;
 
1189
 
 
1190
  menu_y_pos=Buttons_Pool[btn_number].Y_offset;
 
1191
  menu_x_pos=Buttons_Pool[btn_number].X_offset;
 
1192
  if (Buttons_Pool[btn_number].Shape != BUTTON_SHAPE_TRIANGLE_BOTTOM_RIGHT)
 
1193
  {
 
1194
    menu_y_pos+=1;
 
1195
    menu_x_pos+=1;
 
1196
  }
 
1197
  
 
1198
  for (y_pos=0;y_pos<MENU_SPRITE_HEIGHT;y_pos++)
 
1199
    for (x_pos=0;x_pos<MENU_SPRITE_WIDTH;x_pos++)
 
1200
    {
 
1201
      color=Gfx->Menu_sprite[sprite_number][y_pos][x_pos];
 
1202
      Pixel_in_menu_and_skin(MENUBAR_TOOLS, menu_x_pos+x_pos, menu_y_pos+y_pos, color);
 
1203
    }
 
1204
if (Menu_is_visible && Menu_bars[MENUBAR_TOOLS].Visible)
 
1205
  Update_rect(Menu_factor_X*(Buttons_Pool[btn_number].X_offset+1),
 
1206
    (Buttons_Pool[btn_number].Y_offset+1+Menu_bars[MENUBAR_TOOLS].Top)*Menu_factor_Y+Menu_Y,
 
1207
    MENU_SPRITE_WIDTH*Menu_factor_X,MENU_SPRITE_HEIGHT*Menu_factor_Y);
 
1208
}
 
1209
 
 
1210
  // -- Redessiner la forme du pinceau dans le menu --
 
1211
 
 
1212
void Display_paintbrush_in_menu(void)
 
1213
{
 
1214
  short x_pos,y_pos;
 
1215
  short start_x;
 
1216
  short menu_x_pos,menu_y_pos;
 
1217
  short menu_start_x;
 
1218
  byte color;
 
1219
    
 
1220
  switch (Paintbrush_shape)
 
1221
  {
 
1222
    case PAINTBRUSH_SHAPE_COLOR_BRUSH    : // Brush en couleur
 
1223
    case PAINTBRUSH_SHAPE_MONO_BRUSH : // Brush monochrome
 
1224
      for (menu_y_pos=2,y_pos=0;y_pos<MENU_SPRITE_HEIGHT;menu_y_pos++,y_pos++)
 
1225
        for (menu_x_pos=1,x_pos=0;x_pos<MENU_SPRITE_WIDTH;menu_x_pos++,x_pos++)
 
1226
        {
 
1227
          color=Gfx->Menu_sprite[4][y_pos][x_pos];
 
1228
          Pixel_in_menu_and_skin(MENUBAR_TOOLS, menu_x_pos, menu_y_pos, color);
 
1229
        }
 
1230
      break;
 
1231
    default : // Pinceau
 
1232
      // On efface le pinceau pr�c�dent
 
1233
      for (menu_y_pos=2,y_pos=0;y_pos<MENU_SPRITE_HEIGHT;menu_y_pos++,y_pos++)
 
1234
        for (menu_x_pos=1,x_pos=0;x_pos<MENU_SPRITE_WIDTH;menu_x_pos++,x_pos++)
 
1235
        {
 
1236
          Pixel_in_menu_and_skin(MENUBAR_TOOLS, menu_x_pos, menu_y_pos, MC_Light);
 
1237
        }
 
1238
      // On affiche le nouveau
 
1239
      menu_start_x=8-Paintbrush_offset_X;
 
1240
      if (menu_start_x<1)
 
1241
      {
 
1242
        start_x=Paintbrush_offset_X-7;
 
1243
        menu_start_x=1;
 
1244
      }
 
1245
      else
 
1246
        start_x=0;
 
1247
 
 
1248
      menu_y_pos=9-Paintbrush_offset_Y;
 
1249
      if (menu_y_pos<2)
 
1250
      {
 
1251
        y_pos=Paintbrush_offset_Y-7;
 
1252
        menu_y_pos=2;
 
1253
      }
 
1254
      else
 
1255
        y_pos=0;
 
1256
 
 
1257
      for (;((y_pos<Paintbrush_height) && (menu_y_pos<16));menu_y_pos++,y_pos++)
 
1258
        for (menu_x_pos=menu_start_x,x_pos=start_x;((x_pos<Paintbrush_width) && (menu_x_pos<15));menu_x_pos++,x_pos++)
 
1259
        {
 
1260
          color=(Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos])?MC_Black:MC_Light;
 
1261
          Pixel_in_menu_and_skin(MENUBAR_TOOLS, menu_x_pos, menu_y_pos, color);
 
1262
        }
 
1263
  }
 
1264
  if (Menu_is_visible && Menu_bars[MENUBAR_TOOLS].Visible)
 
1265
    Update_rect(0,Menu_Y + Menu_bars[MENUBAR_TOOLS].Top*Menu_factor_Y,MENU_SPRITE_WIDTH*Menu_factor_X+3,MENU_SPRITE_HEIGHT*Menu_factor_Y+3);
 
1266
}
 
1267
 
 
1268
  // -- Dessiner un pinceau pr�d�fini dans la fen�tre --
 
1269
 
 
1270
void Display_paintbrush_in_window(word x,word y,int number)
 
1271
  // Pinceau = 0..NB_PAINTBRUSH_SPRITES-1 : Pinceau pr�d�fini
 
1272
{
 
1273
  word x_pos;
 
1274
  word y_pos;
 
1275
  word window_x_pos;
 
1276
  word window_y_pos;
 
1277
  int x_size;
 
1278
  int y_size;
 
1279
  word origin_x;
 
1280
  word origin_y;
 
1281
 
 
1282
  x_size=Menu_factor_X/Pixel_height;
 
1283
  if (x_size<1)
 
1284
    x_size=1;
 
1285
  y_size=Menu_factor_Y/Pixel_width;
 
1286
  if (y_size<1)
 
1287
    y_size=1;
 
1288
 
 
1289
  origin_x = (x + 8)*Menu_factor_X - (Gfx->Preset_paintbrush_offset_X[number])*x_size+Window_pos_X;
 
1290
  origin_y = (y + 8)*Menu_factor_Y - (Gfx->Preset_paintbrush_offset_Y[number])*y_size+Window_pos_Y;
 
1291
 
 
1292
  for (window_y_pos=0,y_pos=0; y_pos<Gfx->Preset_paintbrush_height[number]; window_y_pos++,y_pos++)
 
1293
    for (window_x_pos=0,x_pos=0; x_pos<Gfx->Preset_paintbrush_width[number]; window_x_pos++,x_pos++)
 
1294
      Block(origin_x+window_x_pos*x_size,origin_y+window_y_pos*y_size,x_size,y_size,(Gfx->Paintbrush_sprite[number][y_pos][x_pos])?MC_Black:MC_Light);
 
1295
  // On n'utilise pas Pixel_in_window() car on ne dessine pas
 
1296
  // forc�ment avec la m�me taille de pixel.
 
1297
 
 
1298
  Update_rect( ToWinX(origin_x), ToWinY(origin_y),
 
1299
        ToWinL(Gfx->Preset_paintbrush_width[number]),
 
1300
        ToWinH(Gfx->Preset_paintbrush_height[number])
 
1301
  );
 
1302
}
 
1303
 
 
1304
  // -- Dessiner des zigouigouis --
 
1305
 
 
1306
void Draw_thingumajig(word x,word y, byte color, short direction)
 
1307
{
 
1308
  word i;
 
1309
 
 
1310
  for (i=0; i<11; i++) Pixel_in_window(x,y+i,color);
 
1311
  x+=direction;
 
1312
  for (i=1; i<10; i++) Pixel_in_window(x,y+i,color);
 
1313
  x+=direction+direction;
 
1314
  for (i=3; i<8; i++) Pixel_in_window(x,y+i,color);
 
1315
  x+=direction+direction;
 
1316
  Pixel_in_window(x,y+5,color);
 
1317
}
 
1318
 
 
1319
  // -- Dessiner un bloc de couleurs d�grad� verticalement
 
1320
 
 
1321
void Display_grad_block_in_window(word x_pos,word y_pos,word block_start,word block_end)
 
1322
{
 
1323
  word total_lines  =Menu_factor_Y<<6; // <=> � 64 lignes fct(Menu_Facteur)
 
1324
  word nb_colors   =(block_start<=block_end)?block_end-block_start+1:block_start-block_end+1;
 
1325
  word Selected_line_mode=(block_start<=block_end)?0:total_lines-1;
 
1326
 
 
1327
  word start_x       =Window_pos_X+(Menu_factor_X*x_pos);
 
1328
  word line_width =Menu_factor_X<<4; // <=> � 16 pixels fct(Menu_Facteur)
 
1329
 
 
1330
  word start_y       =Window_pos_Y+(Menu_factor_Y*y_pos);
 
1331
  word end_y         =start_y+total_lines;
 
1332
  word index;
 
1333
 
 
1334
  if (block_start>block_end)
 
1335
  {
 
1336
    index=block_start;
 
1337
    block_start=block_end;
 
1338
    block_end=index;
 
1339
  }
 
1340
 
 
1341
  for (index=start_y;index<end_y;index++,Selected_line_mode++)
 
1342
    Block(start_x,index,line_width,1,block_start+(nb_colors*Selected_line_mode)/total_lines);
 
1343
 
 
1344
  Update_rect(ToWinX(x_pos),ToWinY(y_pos),ToWinL(16),ToWinH(64));
 
1345
}
 
1346
 
 
1347
 
 
1348
 
 
1349
  // -- Dessiner un petit sprite repr�sentant le type d'un drive --
 
1350
 
 
1351
void Window_display_icon_sprite(word x_pos,word y_pos,byte type)
 
1352
{
 
1353
  word i,j;
 
1354
 
 
1355
  for (j=0; j<ICON_SPRITE_HEIGHT; j++)
 
1356
    for (i=0; i<ICON_SPRITE_WIDTH; i++)
 
1357
      Pixel_in_window(x_pos+i,y_pos+j,Gfx->Icon_sprite[type][j][i]);
 
1358
  Update_rect(ToWinX(x_pos),ToWinY(y_pos),ToWinL(ICON_SPRITE_WIDTH),ToWinH(ICON_SPRITE_HEIGHT));
 
1359
}
 
1360
 
 
1361
 
 
1362
 
 
1363
void Display_menu_palette_avoiding_window(byte * table)
 
1364
{
 
1365
  // On part du principe qu'il n'y a que le bas d'une fen�tre qui puisse
 
1366
  // empi�ter sur la palette... Et c'est d�j� pas mal!
 
1367
  word color,real_color;
 
1368
  word start_x,start_y;
 
1369
  word end_x,end_y;
 
1370
  word width;
 
1371
  word height;
 
1372
  word corner_x=Window_pos_X+Window_width*Menu_factor_X; // |_ Coin bas-droit
 
1373
  word corner_y=Window_pos_Y+Window_height*Menu_factor_Y; // |  de la fen�tre +1
 
1374
 
 
1375
 
 
1376
  if (Config.Separate_colors)
 
1377
  {
 
1378
    width=(Menu_palette_cell_width-1)*Menu_factor_X;
 
1379
    height=Menu_factor_Y*((Menu_height-11)/Menu_cells_Y-1);
 
1380
  }
 
1381
  else
 
1382
  {
 
1383
    width=Menu_palette_cell_width*Menu_factor_X;
 
1384
    height=Menu_factor_Y*((Menu_height-11)/Menu_cells_Y);
 
1385
  }
 
1386
 
 
1387
  for (color=0,real_color=First_color_in_palette;color<Menu_cells_X*Menu_cells_Y;color++,real_color++)
 
1388
  {
 
1389
    if (table[real_color]!=real_color)
 
1390
    {
 
1391
      start_x=Palette_cell_X(real_color);
 
1392
      start_y=Palette_cell_Y(real_color);
 
1393
      end_x=start_x+width;
 
1394
      end_y=start_y+height;
 
1395
 
 
1396
      //   On affiche le bloc en entier si on peut, sinon on le d�coupe autour
 
1397
      // de la fen�tre.
 
1398
      if ( (start_y>=corner_y) || (end_x<=Window_pos_X) || (start_x>=corner_x) )
 
1399
        Block(start_x,start_y,width,height,real_color);
 
1400
      else
 
1401
      {
 
1402
 
 
1403
        if (start_x>=Window_pos_X)
 
1404
        {
 
1405
          if ( (end_x>corner_x) || (end_y>corner_y) )
 
1406
          {
 
1407
            if ( (end_x>corner_x) && (end_y>corner_y) )
 
1408
            {
 
1409
              Block(corner_x,start_y,end_x-corner_x,corner_y-start_y,real_color);
 
1410
              Block(start_x,corner_y,width,end_y-corner_y,real_color);
 
1411
            }
 
1412
            else
 
1413
            {
 
1414
              if (end_y>corner_y)
 
1415
                Block(start_x,corner_y,width,end_y-corner_y,real_color);
 
1416
              else
 
1417
                Block(corner_x,start_y,end_x-corner_x,height,real_color);
 
1418
            }
 
1419
          }
 
1420
        }
 
1421
        else
 
1422
        {
 
1423
          if (end_x<corner_x)
 
1424
          {
 
1425
            if (end_y>corner_y)
 
1426
            {
 
1427
              Block(start_x,start_y,Window_pos_X-start_x,corner_y-start_y,real_color);
 
1428
              Block(start_x,corner_y,width,end_y-corner_y,real_color);
 
1429
            }
 
1430
            else
 
1431
              Block(start_x,start_y,Window_pos_X-start_x,height,real_color);
 
1432
          }
 
1433
          else
 
1434
          {
 
1435
            if (end_y>corner_y)
 
1436
            {
 
1437
              Block(start_x,start_y,Window_pos_X-start_x,corner_y-start_y,real_color);
 
1438
              Block(corner_x,start_y,end_x-corner_x,corner_y-start_y,real_color);
 
1439
              Block(start_x,corner_y,width,end_y-corner_y,real_color);
 
1440
            }
 
1441
            else
 
1442
            {
 
1443
              Block(start_x,start_y,Window_pos_X-start_x,height,real_color);
 
1444
              Block(corner_x,start_y,end_x-corner_x,height,real_color);
 
1445
            }
 
1446
          }
 
1447
        }
 
1448
      }
 
1449
      {
 
1450
        // Affichage du bloc directement dans le "buffer de fond" de la fenetre.
 
1451
        // Cela permet au bloc de couleur d'apparaitre si on d�place la fenetre.
 
1452
        short x_pos;
 
1453
        short y_pos;
 
1454
        short relative_x; // besoin d'une variable sign�e
 
1455
        short relative_y; // besoin d'une variable sign�e
 
1456
        // Attention aux unit�s
 
1457
        relative_x = ((short)start_x - (short)Window_pos_X);
 
1458
        relative_y = ((short)start_y - (short)Window_pos_Y);
 
1459
 
 
1460
        for (y_pos=relative_y;y_pos<(relative_y+height)&&y_pos<Window_height*Menu_factor_Y;y_pos++)
 
1461
          for (x_pos=relative_x;x_pos<(relative_x+width)&&x_pos<Window_width*Menu_factor_X;x_pos++)
 
1462
            if (x_pos>=0&&y_pos>=0)
 
1463
              Pixel_background(x_pos,y_pos,real_color);
 
1464
      }
 
1465
    }
 
1466
  }
 
1467
  Update_rect(MENU_WIDTH*Menu_factor_X,Menu_Y_before_window,Screen_width-(MENU_WIDTH*Menu_factor_X),(Menu_height-11)*Menu_factor_Y);
 
1468
}
 
1469
 
 
1470
// -------- Calcul des bornes de la partie d'image visible � l'�cran ---------
 
1471
void Compute_limits(void)
 
1472
/*
 
1473
  Avant l'appel � cette fonction, les donn�es de la loupe doivent �tre � jour.
 
1474
*/
 
1475
{
 
1476
  if (Main_magnifier_mode)
 
1477
  {
 
1478
    // -- Calcul des limites de la partie non zoom�e de l'image --
 
1479
    Limit_top  =Main_offset_Y;
 
1480
    Limit_left=Main_offset_X;
 
1481
    Limit_visible_bottom   =Limit_top+Menu_Y-1;
 
1482
    Limit_visible_right=Limit_left+Main_separator_position-1;
 
1483
 
 
1484
    if (Limit_visible_bottom>=Main_image_height)
 
1485
      Limit_bottom=Main_image_height-1;
 
1486
    else
 
1487
      Limit_bottom=Limit_visible_bottom;
 
1488
 
 
1489
    if (Limit_visible_right>=Main_image_width)
 
1490
      Limit_right=Main_image_width-1;
 
1491
    else
 
1492
      Limit_right=Limit_visible_right;
 
1493
 
 
1494
    // -- Calcul des limites de la partie zoom�e de l'image --
 
1495
    Limit_top_zoom  =Main_magnifier_offset_Y;
 
1496
    Limit_left_zoom=Main_magnifier_offset_X;
 
1497
    Limit_visible_bottom_zoom   =Limit_top_zoom+Main_magnifier_height-1;
 
1498
    Limit_visible_right_zoom=Limit_left_zoom+Main_magnifier_width-1;
 
1499
 
 
1500
    if (Limit_visible_bottom_zoom>=Main_image_height)
 
1501
      Limit_bottom_zoom=Main_image_height-1;
 
1502
    else
 
1503
      Limit_bottom_zoom=Limit_visible_bottom_zoom;
 
1504
 
 
1505
    if (Limit_visible_right_zoom>=Main_image_width)
 
1506
      Limit_right_zoom=Main_image_width-1;
 
1507
    else
 
1508
      Limit_right_zoom=Limit_visible_right_zoom;
 
1509
  }
 
1510
  else
 
1511
  {
 
1512
    // -- Calcul des limites de la partie visible de l'image --
 
1513
    Limit_top  =Main_offset_Y;
 
1514
    Limit_left=Main_offset_X;
 
1515
    Limit_visible_bottom   =Limit_top+(Menu_is_visible?Menu_Y:Screen_height)-1; // A REVOIR POUR SIMPLIFICATION
 
1516
    Limit_visible_right=Limit_left+Screen_width-1;
 
1517
 
 
1518
    if (Limit_visible_bottom>=Main_image_height)
 
1519
      Limit_bottom=Main_image_height-1;
 
1520
    else
 
1521
      Limit_bottom=Limit_visible_bottom;
 
1522
 
 
1523
    if (Limit_visible_right>=Main_image_width)
 
1524
      Limit_right=Main_image_width-1;
 
1525
    else
 
1526
      Limit_right=Limit_visible_right;
 
1527
  }
 
1528
}
 
1529
 
 
1530
 
 
1531
// -- Calculer les coordonn�es du pinceau en fonction du snap et de la loupe -
 
1532
void Compute_paintbrush_coordinates(void)
 
1533
{
 
1534
  if ((Main_magnifier_mode) && (Mouse_X>=Main_X_zoom))
 
1535
  {
 
1536
    Paintbrush_X=((Mouse_X-Main_X_zoom)/Main_magnifier_factor)+Main_magnifier_offset_X;
 
1537
    Paintbrush_Y=(Mouse_Y/Main_magnifier_factor)+Main_magnifier_offset_Y;
 
1538
  }
 
1539
  else
 
1540
  {
 
1541
    Paintbrush_X=Mouse_X+Main_offset_X;
 
1542
    Paintbrush_Y=Mouse_Y+Main_offset_Y;
 
1543
  }
 
1544
 
 
1545
  if (Snap_mode)
 
1546
  {
 
1547
    Paintbrush_X=(((Paintbrush_X+(Snap_width>>1)-Snap_offset_X)/Snap_width)*Snap_width)+Snap_offset_X;
 
1548
    Paintbrush_Y=(((Paintbrush_Y+(Snap_height>>1)-Snap_offset_Y)/Snap_height)*Snap_height)+Snap_offset_Y;
 
1549
  }
 
1550
  
 
1551
  // Handling the snap axis mode, when shift is pressed.
 
1552
  switch (Current_operation)
 
1553
  {
 
1554
    // Operations that don't implement it
 
1555
    case OPERATION_LINE:
 
1556
      Snap_axis=0;
 
1557
      break;
 
1558
    // Operations that implement it
 
1559
    default:
 
1560
      if (Snap_axis==0 && (SDL_GetModState() & KMOD_SHIFT))
 
1561
      {
 
1562
        // Start "Snap axis" mode
 
1563
        Snap_axis=1;
 
1564
        Snap_axis_origin_X=Paintbrush_X;
 
1565
        Snap_axis_origin_Y=Paintbrush_Y;
 
1566
      } 
 
1567
  }
 
1568
 
 
1569
  if (Snap_axis==1)
 
1570
  {
 
1571
    // Cursor moved
 
1572
    if (Paintbrush_X != Snap_axis_origin_X || Paintbrush_Y != Snap_axis_origin_Y)
 
1573
    {
 
1574
      if ((Paintbrush_X-Snap_axis_origin_X)*(Paintbrush_X-Snap_axis_origin_X) >
 
1575
          (Paintbrush_Y-Snap_axis_origin_Y)*(Paintbrush_Y-Snap_axis_origin_Y))
 
1576
      // Displacement was bigger on X axis: lock Y
 
1577
        Snap_axis=2;
 
1578
      else
 
1579
        Snap_axis=3;
 
1580
    }
 
1581
  }
 
1582
  if (Snap_axis==2)
 
1583
  {
 
1584
    Paintbrush_Y = Snap_axis_origin_Y;
 
1585
  }
 
1586
  else if (Snap_axis==3)
 
1587
  {
 
1588
    Paintbrush_X = Snap_axis_origin_X;
 
1589
  }
 
1590
}
 
1591
 
 
1592
 
 
1593
 
 
1594
// -- Affichage de la limite de l'image -------------------------------------
 
1595
void Display_image_limits(void)
 
1596
{
 
1597
  short start;
 
1598
  short pos;
 
1599
  short end;
 
1600
  byte right_is_visible;
 
1601
  byte bottom_is_visible;
 
1602
  short old_zoom_limit;
 
1603
 
 
1604
  right_is_visible=Main_image_width<((Main_magnifier_mode)?Main_separator_position:Screen_width);
 
1605
  bottom_is_visible   =Main_image_height<Menu_Y;
 
1606
 
 
1607
 
 
1608
  // On v�rifie que la limite � droite est visible:
 
1609
  if (right_is_visible)
 
1610
  {
 
1611
    start=Limit_top;
 
1612
    end=(Limit_bottom<Main_image_height)?
 
1613
        Limit_bottom:Main_image_height;
 
1614
 
 
1615
    if (bottom_is_visible)
 
1616
      end++;
 
1617
 
 
1618
    // Juste le temps d'afficher les limites, on �tend les limites de la loupe
 
1619
    // aux limites visibles, car sinon Pixel_preview ne voudra pas afficher.
 
1620
    old_zoom_limit=Limit_right_zoom;
 
1621
    Limit_right_zoom=Limit_visible_right_zoom;
 
1622
 
 
1623
    for (pos=start;pos<=end;pos++)
 
1624
      Pixel_preview(Main_image_width,pos,((pos+Main_image_height)&1)?MC_White:MC_Black);
 
1625
 
 
1626
    Update_rect(Main_image_width,start,1,end-start + 1);
 
1627
    // On restaure la bonne valeur des limites
 
1628
    Limit_right_zoom=old_zoom_limit;
 
1629
  }
 
1630
 
 
1631
  // On v�rifie que la limite en bas est visible:
 
1632
  if (bottom_is_visible)
 
1633
  {
 
1634
    start=Limit_left;
 
1635
    end=(Limit_right<Main_image_width)?
 
1636
        Limit_right:Main_image_width;
 
1637
 
 
1638
    // On �tend �galement les limites en bas (comme pour la limite droit)
 
1639
    old_zoom_limit=Limit_bottom_zoom;
 
1640
    Limit_bottom_zoom=Limit_visible_bottom_zoom;
 
1641
 
 
1642
    for (pos=start;pos<=end;pos++)
 
1643
      Pixel_preview(pos,Main_image_height,((pos+Main_image_height)&1)?MC_White:MC_Black);
 
1644
 
 
1645
    Update_rect(start,Main_image_height,end-start + 1,1);
 
1646
 
 
1647
    // On restaure la bonne valeur des limites
 
1648
    Limit_bottom_zoom=old_zoom_limit;
 
1649
  }
 
1650
}
 
1651
 
 
1652
 
 
1653
 
 
1654
// -- Recadrer la partie non-zoom�e de l'image par rapport � la partie zoom�e
 
1655
//    lorsqu'on scrolle en mode Loupe --
 
1656
void Position_screen_according_to_zoom(void)
 
1657
{
 
1658
  // Centrage en X
 
1659
  if (Main_image_width>Main_separator_position)
 
1660
  {
 
1661
    Main_offset_X=Main_magnifier_offset_X+(Main_magnifier_width>>1)
 
1662
                         -(Main_separator_position>>1);
 
1663
    if (Main_offset_X<0)
 
1664
      Main_offset_X=0;
 
1665
    else if (Main_image_width<Main_offset_X+Main_separator_position)
 
1666
      Main_offset_X=Main_image_width-Main_separator_position;
 
1667
  }
 
1668
  else
 
1669
    Main_offset_X=0;
 
1670
 
 
1671
  // Centrage en Y
 
1672
  if (Main_image_height>Menu_Y)
 
1673
  {
 
1674
    Main_offset_Y=Main_magnifier_offset_Y+(Main_magnifier_height>>1)
 
1675
                         -(Menu_Y>>1);
 
1676
    if (Main_offset_Y<0)
 
1677
      Main_offset_Y=0;
 
1678
    else if (Main_image_height<Main_offset_Y+Menu_Y)
 
1679
      Main_offset_Y=Main_image_height-Menu_Y;
 
1680
  }
 
1681
  else
 
1682
    Main_offset_Y=0;
 
1683
}
 
1684
 
 
1685
// -- Recenter the non-zoomed part of image around a precise pixel
 
1686
void Position_screen_according_to_position(int target_x, int target_y)
 
1687
{
 
1688
  // Centrage en X
 
1689
  if (Main_image_width>Main_separator_position)
 
1690
  {
 
1691
    Main_offset_X=target_x-Mouse_X;
 
1692
    // Do not allow the zoomed part to show something that the
 
1693
    // non-zoomed part doesn't see. All clipping is computed according
 
1694
    // to the non-zoomed part.
 
1695
    if (Main_magnifier_offset_X<Main_offset_X)
 
1696
      Main_offset_X=Main_magnifier_offset_X;
 
1697
    else if (Main_magnifier_offset_X+Main_magnifier_width > Main_offset_X+Main_separator_position)
 
1698
      Main_offset_X = Main_magnifier_offset_X+Main_magnifier_width-Main_separator_position;
 
1699
    if (Main_offset_X<0)
 
1700
      Main_offset_X=0;
 
1701
    else if (Main_image_width<Main_offset_X+Main_separator_position)
 
1702
      Main_offset_X=Main_image_width-Main_separator_position;
 
1703
      
 
1704
    
 
1705
  }
 
1706
  else
 
1707
    Main_offset_X=0;
 
1708
 
 
1709
  // Centrage en Y
 
1710
  if (Main_image_height>Menu_Y)
 
1711
  {
 
1712
    Main_offset_Y=target_y-Mouse_Y;
 
1713
    // Do not allow the zoomed part to show something that the
 
1714
    // non-zoomed part doesn't see. All clipping is computed according
 
1715
    // to the non-zoomed part.
 
1716
    if (Main_magnifier_offset_Y<Main_offset_Y)
 
1717
      Main_offset_Y=Main_magnifier_offset_Y;
 
1718
    else if (Main_magnifier_offset_Y+Main_magnifier_height > Main_offset_Y)
 
1719
      Main_offset_Y = Main_magnifier_offset_Y+Main_magnifier_height;
 
1720
    if (Main_offset_Y<0)
 
1721
      Main_offset_Y=0;
 
1722
    else if (Main_image_height<Main_offset_Y+Menu_Y)
 
1723
      Main_offset_Y=Main_image_height-Menu_Y;
 
1724
  }
 
1725
  else
 
1726
    Main_offset_Y=0;
 
1727
}
 
1728
 
 
1729
 
 
1730
// - Calcul des donn�es du split en fonction de la proportion de chaque zone -
 
1731
void Compute_separator_data(void)
 
1732
{
 
1733
  //short temp;
 
1734
  short theoric_X=Round(Main_separator_proportion*Screen_width);
 
1735
 
 
1736
  Main_X_zoom=Screen_width-(((Screen_width+(Main_magnifier_factor>>1)-theoric_X)/Main_magnifier_factor)*Main_magnifier_factor);
 
1737
  Main_separator_position=Main_X_zoom-(Menu_factor_X*SEPARATOR_WIDTH);
 
1738
 
 
1739
  // Correction en cas de d�bordement sur la gauche
 
1740
  while (Main_separator_position*(Main_magnifier_factor+1)<Screen_width-(Menu_factor_X*SEPARATOR_WIDTH))
 
1741
  {
 
1742
    Main_separator_position+=Main_magnifier_factor;
 
1743
    Main_X_zoom+=Main_magnifier_factor;
 
1744
  }
 
1745
  // Correction en cas de d�bordement sur la droite
 
1746
  theoric_X=Screen_width-((NB_ZOOMED_PIXELS_MIN-1)*Main_magnifier_factor);
 
1747
  while (Main_X_zoom>=theoric_X)
 
1748
  {
 
1749
    Main_separator_position-=Main_magnifier_factor;
 
1750
    Main_X_zoom-=Main_magnifier_factor;
 
1751
  }
 
1752
}
 
1753
 
 
1754
 
 
1755
 
 
1756
// -------------------- Calcul des information de la loupe -------------------
 
1757
void Compute_magnifier_data(void)
 
1758
/*
 
1759
  Apr�s modification des donn�es de la loupe, il faut recalculer les limites.
 
1760
*/
 
1761
{
 
1762
  Compute_separator_data();
 
1763
 
 
1764
  Main_magnifier_width=(Screen_width-Main_X_zoom)/Main_magnifier_factor;
 
1765
 
 
1766
  Main_magnifier_height=Menu_Y/Main_magnifier_factor;
 
1767
  if (Menu_Y%Main_magnifier_factor)
 
1768
    Main_magnifier_height++;
 
1769
 
 
1770
  if (Main_magnifier_mode && Main_magnifier_offset_X)
 
1771
  {
 
1772
    if (Main_image_width<Main_magnifier_offset_X+Main_magnifier_width)
 
1773
      Main_magnifier_offset_X=Main_image_width-Main_magnifier_width;
 
1774
    if (Main_magnifier_offset_X<0) Main_magnifier_offset_X=0;
 
1775
  }
 
1776
  if (Main_magnifier_mode && Main_magnifier_offset_Y)
 
1777
  {
 
1778
    if (Main_image_height<Main_magnifier_offset_Y+Main_magnifier_height)
 
1779
      Main_magnifier_offset_Y=Main_image_height-Main_magnifier_height;
 
1780
    if (Main_magnifier_offset_Y<0) Main_magnifier_offset_Y=0;
 
1781
  }
 
1782
  
 
1783
}
 
1784
 
 
1785
 
 
1786
/// Changes magnifier factor and updates everything needed
 
1787
void Change_magnifier_factor(byte factor_index, byte point_at_mouse)
 
1788
{
 
1789
  int target_x,target_y; // These coordinates are in image space
 
1790
  byte magnified_view_leads=1;
 
1791
 
 
1792
  // Values that need to be computed before switching to the new zoom factor
 
1793
  if (!point_at_mouse || Cursor_in_menu || !Main_magnifier_mode)
 
1794
  {
 
1795
    // Locate the pixel in center of the magnified area
 
1796
    target_x = Main_magnifier_offset_X + (Main_magnifier_width >> 1);
 
1797
    target_y = Main_magnifier_offset_Y + (Main_magnifier_height >> 1);
 
1798
    point_at_mouse=0;
 
1799
  }
 
1800
  else if (Mouse_X>=Main_X_zoom)
 
1801
  {
 
1802
    // Locate the pixel under the cursor, in magnified area
 
1803
    target_x=((Mouse_X-Main_X_zoom)/Main_magnifier_factor)+Main_magnifier_offset_X;
 
1804
    target_y=(Mouse_Y/Main_magnifier_factor)+Main_magnifier_offset_Y;
 
1805
    point_at_mouse=1;
 
1806
  }
 
1807
  else
 
1808
  {
 
1809
    // Locate the pixel under the cursor, in normal area
 
1810
    target_x=Mouse_X+Main_offset_X;
 
1811
    target_y=Mouse_Y+Main_offset_Y;
 
1812
    magnified_view_leads=0;
 
1813
    point_at_mouse=0;
 
1814
  }
 
1815
 
 
1816
  Main_magnifier_factor=ZOOM_FACTOR[factor_index];
 
1817
  Compute_magnifier_data();
 
1818
 
 
1819
  if (Main_magnifier_mode)
 
1820
  {
 
1821
    // Recompute the magnifier offset (center its view)
 
1822
    if (point_at_mouse)
 
1823
    {
 
1824
      // Target pixel must be located under the mouse position.
 
1825
      Main_magnifier_offset_X = target_x-((Mouse_X-Main_X_zoom)/Main_magnifier_factor);
 
1826
      Main_magnifier_offset_Y = target_y-((Mouse_Y)/Main_magnifier_factor);
 
1827
    }
 
1828
    else
 
1829
    {
 
1830
      // Target pixel must be positioned at new center
 
1831
      Main_magnifier_offset_X = target_x-(Main_magnifier_width>>1);
 
1832
      Main_magnifier_offset_Y = target_y-(Main_magnifier_height>>1);
 
1833
    }
 
1834
    // Fix cases where the image would overflow on edges
 
1835
    if (Main_magnifier_offset_X+Main_magnifier_width>Main_image_width)
 
1836
      Main_magnifier_offset_X=Main_image_width-Main_magnifier_width;
 
1837
    if (Main_magnifier_offset_Y+Main_magnifier_height>Main_image_height)
 
1838
      Main_magnifier_offset_Y=Main_image_height-Main_magnifier_height;
 
1839
    if (Main_magnifier_offset_X<0)
 
1840
      Main_magnifier_offset_X=0;
 
1841
    if (Main_magnifier_offset_Y<0)
 
1842
      Main_magnifier_offset_Y=0;
 
1843
 
 
1844
    if (magnified_view_leads)
 
1845
      Position_screen_according_to_zoom();
 
1846
    else
 
1847
      Position_screen_according_to_position(target_x, target_y);
 
1848
 
 
1849
    Pixel_preview=Pixel_preview_magnifier;
 
1850
 
 
1851
  }
 
1852
  else
 
1853
    Pixel_preview=Pixel_preview_normal;
 
1854
 
 
1855
  Compute_limits();
 
1856
  Compute_paintbrush_coordinates();
 
1857
}
 
1858
 
 
1859
 
 
1860
 
 
1861
  // -- Afficher la barre de s�paration entre les parties zoom�es ou non en
 
1862
  //    mode Loupe --
 
1863
 
 
1864
void Display_separator(void)
 
1865
{
 
1866
  // Partie grise du milieu
 
1867
  Block(Main_separator_position+(Menu_factor_X<<1),Menu_factor_Y,
 
1868
        (SEPARATOR_WIDTH-4)*Menu_factor_X,
 
1869
        Menu_Y-(Menu_factor_Y<<1),MC_Light);
 
1870
 
 
1871
  // Barre noire de gauche
 
1872
  Block(Main_separator_position,0,Menu_factor_X,Menu_Y,MC_Black);
 
1873
 
 
1874
  // Barre noire de droite
 
1875
  Block(Main_X_zoom-Menu_factor_X,0,Menu_factor_X,Menu_Y,MC_Black);
 
1876
 
 
1877
  // Bord haut (blanc)
 
1878
  Block(Main_separator_position+Menu_factor_X,0,
 
1879
        (SEPARATOR_WIDTH-3)*Menu_factor_X,Menu_factor_Y,MC_White);
 
1880
 
 
1881
  // Bord gauche (blanc)
 
1882
  Block(Main_separator_position+Menu_factor_X,Menu_factor_Y,
 
1883
        Menu_factor_X,(Menu_Y-(Menu_factor_Y<<1)),MC_White);
 
1884
 
 
1885
  // Bord droite (gris fonc�)
 
1886
  Block(Main_X_zoom-(Menu_factor_X<<1),Menu_factor_Y,
 
1887
        Menu_factor_X,(Menu_Y-(Menu_factor_Y<<1)),MC_Dark);
 
1888
 
 
1889
  // Bord bas (gris fonc�)
 
1890
  Block(Main_separator_position+(Menu_factor_X<<1),Menu_Y-Menu_factor_Y,
 
1891
        (SEPARATOR_WIDTH-3)*Menu_factor_X,Menu_factor_Y,MC_Dark);
 
1892
 
 
1893
  // Coin bas gauche
 
1894
  Block(Main_separator_position+Menu_factor_X,Menu_Y-Menu_factor_Y,
 
1895
        Menu_factor_X,Menu_factor_Y,MC_Light);
 
1896
  // Coin haut droite
 
1897
  Block(Main_X_zoom-(Menu_factor_X<<1),0,
 
1898
        Menu_factor_X,Menu_factor_Y,MC_Light);
 
1899
 
 
1900
  Update_rect(Main_separator_position,0,SEPARATOR_WIDTH*Menu_factor_X,Menu_Y); // On r�affiche toute la partie � gauche du split, ce qui permet d'effacer son ancienne position
 
1901
}
 
1902
 
 
1903
 
 
1904
 
 
1905
// -- Fonctions de manipulation du curseur -----------------------------------
 
1906
 
 
1907
 
 
1908
  // -- Afficher une barre horizontale XOR zoom�e
 
1909
 
 
1910
void Horizontal_XOR_line_zoom(short x_pos, short y_pos, short width)
 
1911
{
 
1912
  short real_x_pos=Main_X_zoom+(x_pos-Main_magnifier_offset_X)*Main_magnifier_factor;
 
1913
  short real_y_pos=(y_pos-Main_magnifier_offset_Y)*Main_magnifier_factor;
 
1914
  short real_width=width*Main_magnifier_factor;
 
1915
  short end_y_pos=(real_y_pos+Main_magnifier_factor<Menu_Y)?real_y_pos+Main_magnifier_factor:Menu_Y;
 
1916
  short index;
 
1917
 
 
1918
  for (index=real_y_pos; index<end_y_pos; index++)
 
1919
    Horizontal_XOR_line(real_x_pos,index,real_width);
 
1920
 
 
1921
  Update_rect(real_x_pos,real_y_pos,real_width,end_y_pos-real_y_pos);
 
1922
}
 
1923
 
 
1924
 
 
1925
  // -- Afficher une barre verticale XOR zoom�e
 
1926
 
 
1927
void Vertical_XOR_line_zoom(short x_pos, short y_pos, short height)
 
1928
{
 
1929
  short real_x_pos=Main_X_zoom+(x_pos-Main_magnifier_offset_X)*Main_magnifier_factor;
 
1930
  short real_y_pos=(y_pos-Main_magnifier_offset_Y)*Main_magnifier_factor;
 
1931
  short end_y_pos=(real_y_pos+(height*Main_magnifier_factor<Menu_Y))?real_y_pos+(height*Main_magnifier_factor):Menu_Y;
 
1932
  short index;
 
1933
 
 
1934
  for (index=real_y_pos; index<end_y_pos; index++)
 
1935
    Horizontal_XOR_line(real_x_pos,index,Main_magnifier_factor);
 
1936
 
 
1937
  Update_rect(real_x_pos,real_y_pos,Main_magnifier_factor,end_y_pos-real_y_pos);
 
1938
}
 
1939
 
 
1940
 
 
1941
  // -- Afficher le curseur --
 
1942
 
 
1943
void Display_cursor(void)
 
1944
{
 
1945
  byte  shape;
 
1946
  short start_x;
 
1947
  short start_y;
 
1948
  short end_x;
 
1949
  short end_y;
 
1950
  short x_pos;
 
1951
  short y_pos;
 
1952
  short counter_x = 0;
 
1953
  short counter_y;
 
1954
  int   temp;
 
1955
  byte  color;
 
1956
  float cos_a,sin_a;
 
1957
  short x1,y1,x2,y2,x3,y3,x4,y4;
 
1958
 
 
1959
  // Si le curseur est dans le menu ou sur la barre de split, on affiche toujours une fl�che.
 
1960
  if ( ( (Mouse_Y<Menu_Y)
 
1961
      && ( (!Main_magnifier_mode) || (Mouse_X<Main_separator_position) || (Mouse_X>=Main_X_zoom) ) )
 
1962
    || (Windows_open) || (Cursor_shape==CURSOR_SHAPE_HOURGLASS) )
 
1963
    shape=Cursor_shape;
 
1964
  else
 
1965
    shape=CURSOR_SHAPE_ARROW;
 
1966
 
 
1967
  switch(shape)
 
1968
  {
 
1969
    case CURSOR_SHAPE_TARGET :
 
1970
      if (!Paintbrush_hidden)
 
1971
        Display_paintbrush(Paintbrush_X,Paintbrush_Y,Fore_color,1);
 
1972
      if (!Cursor_hidden)
 
1973
      {
 
1974
        if (Config.Cursor==1)
 
1975
        {
 
1976
          start_y=(Mouse_Y<6)?6-Mouse_Y:0;
 
1977
          if (start_y<4)
 
1978
            Vertical_XOR_line  (Mouse_X,Mouse_Y+start_y-6,4-start_y);
 
1979
 
 
1980
          start_x=(Mouse_X<6)?(short)6-Mouse_X:0;
 
1981
          if (start_x<4)
 
1982
            Horizontal_XOR_line(Mouse_X+start_x-6,Mouse_Y,4-start_x);
 
1983
 
 
1984
          end_x=(Mouse_X+7>Screen_width)?Mouse_X+7-Screen_width:0;
 
1985
          if (end_x<4)
 
1986
            Horizontal_XOR_line(Mouse_X+3,Mouse_Y,4-end_x);
 
1987
 
 
1988
          end_y=(Mouse_Y+7>Screen_height)?Mouse_Y+7-Screen_height:0;
 
1989
          if (end_y<4)
 
1990
            Vertical_XOR_line  (Mouse_X,Mouse_Y+3,4-end_y);
 
1991
 
 
1992
          Update_rect(Mouse_X+start_x-6,Mouse_Y+start_y-6,13-end_x,13-end_y);
 
1993
        }
 
1994
        else
 
1995
        {
 
1996
          temp=(Config.Cursor)?CURSOR_SHAPE_THIN_TARGET:CURSOR_SHAPE_TARGET;
 
1997
          start_x=Mouse_X-Gfx->Cursor_offset_X[temp];
 
1998
          start_y=Mouse_Y-Gfx->Cursor_offset_Y[temp];
 
1999
 
 
2000
          for (y_pos=start_y,counter_y=0; counter_y<15 && y_pos < Screen_height;
 
2001
            y_pos++,counter_y++)
 
2002
          {
 
2003
            if( y_pos < 0 ) continue;
 
2004
              for (x_pos=start_x,counter_x=0;
 
2005
                counter_x<15 && x_pos < Screen_width; x_pos++,counter_x++)
 
2006
              {
 
2007
                if( x_pos < 0 ) continue;
 
2008
                  color=Gfx->Cursor_sprite[temp][counter_y][counter_x];
 
2009
                  Cursor_background[counter_y][counter_x]=Read_pixel(x_pos,y_pos);
 
2010
                  if (color!=MC_Trans)
 
2011
                    Pixel(x_pos,y_pos,color);
 
2012
            }
 
2013
          }
 
2014
 
 
2015
          Update_rect(Max(start_x,0),Max(start_y,0),counter_x,counter_y);
 
2016
        }
 
2017
      }
 
2018
      break;
 
2019
 
 
2020
    case CURSOR_SHAPE_COLORPICKER:
 
2021
      if (!Paintbrush_hidden)
 
2022
        Display_paintbrush(Paintbrush_X,Paintbrush_Y,Fore_color,1);
 
2023
      if (!Cursor_hidden)
 
2024
      {
 
2025
        if (Config.Cursor==1)
 
2026
        {
 
2027
          // Barres formant la croix principale
 
2028
 
 
2029
          start_y=(Mouse_Y<5)?5-Mouse_Y:0;
 
2030
          if (start_y<3)
 
2031
            Vertical_XOR_line  (Mouse_X,Mouse_Y+start_y-5,3-start_y);
 
2032
 
 
2033
          start_x=(Mouse_X<5)?(short)5-Mouse_X:0;
 
2034
          if (start_x<3)
 
2035
            Horizontal_XOR_line(Mouse_X+start_x-5,Mouse_Y,3-start_x);
 
2036
 
 
2037
          end_x=(Mouse_X+6>Screen_width)?Mouse_X+6-Screen_width:0;
 
2038
          if (end_x<3)
 
2039
            Horizontal_XOR_line(Mouse_X+3,Mouse_Y,3-end_x);
 
2040
 
 
2041
          end_y=(Mouse_Y+6>Menu_Y/*Screen_height*/)?Mouse_Y+6-Menu_Y/*Screen_height*/:0;
 
2042
          if (end_y<3)
 
2043
            Vertical_XOR_line  (Mouse_X,Mouse_Y+3,3-end_y);
 
2044
 
 
2045
          // Petites barres aux extr�mit�s
 
2046
 
 
2047
          start_x=(!Mouse_X);
 
2048
          start_y=(!Mouse_Y);
 
2049
          end_x=(Mouse_X>=Screen_width-1);
 
2050
          end_y=(Mouse_Y>=Menu_Y-1);
 
2051
 
 
2052
          if (Mouse_Y>5)
 
2053
            Horizontal_XOR_line(start_x+Mouse_X-1,Mouse_Y-6,3-(start_x+end_x));
 
2054
 
 
2055
          if (Mouse_X>5)
 
2056
            Vertical_XOR_line  (Mouse_X-6,start_y+Mouse_Y-1,3-(start_y+end_y));
 
2057
 
 
2058
          if (Mouse_X<Screen_width-6)
 
2059
            Vertical_XOR_line  (Mouse_X+6,start_y+Mouse_Y-1,3-(start_y+end_y));
 
2060
 
 
2061
          if (Mouse_Y<Menu_Y-6)
 
2062
            Horizontal_XOR_line(start_x+Mouse_X-1,Mouse_Y+6,3-(start_x+end_x));
 
2063
        }
 
2064
        else
 
2065
        {
 
2066
          temp=(Config.Cursor)?CURSOR_SHAPE_THIN_COLORPICKER:CURSOR_SHAPE_COLORPICKER;
 
2067
          start_x=Mouse_X-Gfx->Cursor_offset_X[temp];
 
2068
          start_y=Mouse_Y-Gfx->Cursor_offset_Y[temp];
 
2069
 
 
2070
          for (y_pos=start_y,counter_y=0;counter_y<15;y_pos++,counter_y++)
 
2071
          {
 
2072
            if(y_pos<0) continue;
 
2073
            if(y_pos>=Screen_height) break;
 
2074
            for (x_pos=start_x,counter_x=0;counter_x<15;x_pos++,counter_x++)
 
2075
            {
 
2076
              if(x_pos<0) continue;
 
2077
              if(x_pos>=Screen_width) break;
 
2078
              color=Gfx->Cursor_sprite[temp][counter_y][counter_x];
 
2079
              // On sauvegarde dans Cursor_background pour restaurer plus tard
 
2080
              Cursor_background[counter_y][counter_x]=Read_pixel(x_pos,y_pos);
 
2081
              if (color!=MC_Trans)
 
2082
                Pixel(x_pos,y_pos,color);
 
2083
            }
 
2084
          }
 
2085
          Update_rect(Max(start_x,0),Max(start_y,0),counter_x,counter_y);
 
2086
        }
 
2087
      }
 
2088
      break;
 
2089
 
 
2090
    case CURSOR_SHAPE_MULTIDIRECTIONAL :
 
2091
    case CURSOR_SHAPE_HORIZONTAL :
 
2092
      if (Cursor_hidden)
 
2093
        break;
 
2094
 
 
2095
    case CURSOR_SHAPE_ARROW :
 
2096
    case CURSOR_SHAPE_HOURGLASS :
 
2097
      start_x=Mouse_X-Gfx->Cursor_offset_X[shape];
 
2098
      start_y=Mouse_Y-Gfx->Cursor_offset_Y[shape];
 
2099
      for (y_pos=start_y,counter_y=0;counter_y<15;y_pos++,counter_y++)
 
2100
      {
 
2101
        if(y_pos<0) continue;
 
2102
        if(y_pos>=Screen_height) break;
 
2103
        for (x_pos=start_x,counter_x=0;counter_x<15;x_pos++,counter_x++)
 
2104
        {
 
2105
          if(x_pos<0) continue;
 
2106
          if(x_pos>=Screen_width) break;
 
2107
          color=Gfx->Cursor_sprite[shape][counter_y][counter_x];
 
2108
          // On sauvegarde dans Cursor_background pour restaurer plus tard
 
2109
          Cursor_background[counter_y][counter_x]=Read_pixel(x_pos,y_pos);
 
2110
          if (color!=MC_Trans)
 
2111
              Pixel(x_pos,y_pos,color);
 
2112
        }
 
2113
      }
 
2114
      Update_rect(Max(start_x,0),Max(start_y,0),counter_x,counter_y);
 
2115
      break;
 
2116
 
 
2117
    case CURSOR_SHAPE_XOR_TARGET :
 
2118
      x_pos=Paintbrush_X-Main_offset_X;
 
2119
      y_pos=Paintbrush_Y-Main_offset_Y;
 
2120
 
 
2121
      counter_x=(Main_magnifier_mode)?Main_separator_position:Screen_width; // width de la barre XOR
 
2122
      if ((y_pos<Menu_Y) && (Paintbrush_Y>=Limit_top))
 
2123
      {
 
2124
        Horizontal_XOR_line(0,Paintbrush_Y-Main_offset_Y,counter_x);
 
2125
        Update_rect(0,Paintbrush_Y-Main_offset_Y,counter_x,1);
 
2126
      }
 
2127
 
 
2128
      if ((x_pos<counter_x) && (Paintbrush_X>=Limit_left))
 
2129
      {
 
2130
        Vertical_XOR_line(Paintbrush_X-Main_offset_X,0,Menu_Y);
 
2131
        Update_rect(Paintbrush_X-Main_offset_X,0,1,Menu_Y);
 
2132
      }
 
2133
 
 
2134
      if (Main_magnifier_mode)
 
2135
      {
 
2136
        // UPDATERECT
 
2137
        if ((Paintbrush_Y>=Limit_top_zoom) && (Paintbrush_Y<=Limit_visible_bottom_zoom))
 
2138
          Horizontal_XOR_line_zoom(Limit_left_zoom,Paintbrush_Y,Main_magnifier_width);
 
2139
        if ((Paintbrush_X>=Limit_left_zoom) && (Paintbrush_X<=Limit_visible_right_zoom))
 
2140
          Vertical_XOR_line_zoom(Paintbrush_X,Limit_top_zoom,Main_magnifier_height);
 
2141
      }
 
2142
      break;
 
2143
    case CURSOR_SHAPE_XOR_RECTANGLE :
 
2144
      // !!! Cette forme ne peut pas �tre utilis�e en mode Loupe !!!
 
2145
 
 
2146
      // Petite croix au centre
 
2147
      start_x=(Mouse_X-3);
 
2148
      start_y=(Mouse_Y-3);
 
2149
      end_x  =(Mouse_X+4);
 
2150
      end_y  =(Mouse_Y+4);
 
2151
      if (start_x<0)
 
2152
        start_x=0;
 
2153
      if (start_y<0)
 
2154
        start_y=0;
 
2155
      if (end_x>Screen_width)
 
2156
        end_x=Screen_width;
 
2157
      if (end_y>Menu_Y)
 
2158
        end_y=Menu_Y;
 
2159
 
 
2160
      Horizontal_XOR_line(start_x,Mouse_Y,end_x-start_x);
 
2161
      Vertical_XOR_line  (Mouse_X,start_y,end_y-start_y);
 
2162
 
 
2163
      // Grand rectangle autour
 
2164
      start_x=Mouse_X-(Main_magnifier_width>>1);
 
2165
      start_y=Mouse_Y-(Main_magnifier_height>>1);
 
2166
      if (start_x+Main_magnifier_width>=Limit_right-Main_offset_X)
 
2167
        start_x=Limit_right-Main_magnifier_width-Main_offset_X+1;
 
2168
      if (start_y+Main_magnifier_height>=Limit_bottom-Main_offset_Y)
 
2169
        start_y=Limit_bottom-Main_magnifier_height-Main_offset_Y+1;
 
2170
      if (start_x<0)
 
2171
        start_x=0;
 
2172
      if (start_y<0)
 
2173
        start_y=0;
 
2174
      end_x=start_x+Main_magnifier_width-1;
 
2175
      end_y=start_y+Main_magnifier_height-1;
 
2176
 
 
2177
      Horizontal_XOR_line(start_x,start_y,Main_magnifier_width);
 
2178
      Vertical_XOR_line(start_x,start_y+1,Main_magnifier_height-2);
 
2179
      Vertical_XOR_line(  end_x,start_y+1,Main_magnifier_height-2);
 
2180
      Horizontal_XOR_line(start_x,  end_y,Main_magnifier_width);
 
2181
 
 
2182
      Update_rect(start_x,start_y,end_x+1-start_x,end_y+1-start_y);
 
2183
 
 
2184
      break;
 
2185
    default: //case CURSOR_SHAPE_XOR_ROTATION :
 
2186
      start_x=1-(Brush_width>>1);
 
2187
      start_y=1-(Brush_height>>1);
 
2188
      end_x=start_x+Brush_width-1;
 
2189
      end_y=start_y+Brush_height-1;
 
2190
 
 
2191
      if (Brush_rotation_center_is_defined)
 
2192
      {
 
2193
        if ( (Brush_rotation_center_X==Paintbrush_X)
 
2194
          && (Brush_rotation_center_Y==Paintbrush_Y) )
 
2195
        {
 
2196
          cos_a=1.0;
 
2197
          sin_a=0.0;
 
2198
        }
 
2199
        else
 
2200
        {
 
2201
          x_pos=Paintbrush_X-Brush_rotation_center_X;
 
2202
          y_pos=Paintbrush_Y-Brush_rotation_center_Y;
 
2203
          cos_a=(float)x_pos/sqrt((x_pos*x_pos)+(y_pos*y_pos));
 
2204
          sin_a=sin(acos(cos_a));
 
2205
          if (y_pos>0) sin_a=-sin_a;
 
2206
        }
 
2207
 
 
2208
        Transform_point(start_x,start_y, cos_a,sin_a, &x1,&y1);
 
2209
        Transform_point(end_x  ,start_y, cos_a,sin_a, &x2,&y2);
 
2210
        Transform_point(start_x,end_y  , cos_a,sin_a, &x3,&y3);
 
2211
        Transform_point(end_x  ,end_y  , cos_a,sin_a, &x4,&y4);
 
2212
 
 
2213
        x1+=Brush_rotation_center_X;
 
2214
        y1+=Brush_rotation_center_Y;
 
2215
        x2+=Brush_rotation_center_X;
 
2216
        y2+=Brush_rotation_center_Y;
 
2217
        x3+=Brush_rotation_center_X;
 
2218
        y3+=Brush_rotation_center_Y;
 
2219
        x4+=Brush_rotation_center_X;
 
2220
        y4+=Brush_rotation_center_Y;
 
2221
        Pixel_figure_preview_xor(Brush_rotation_center_X,Brush_rotation_center_Y,0);
 
2222
        Draw_line_preview_xor(Brush_rotation_center_X,Brush_rotation_center_Y,Paintbrush_X,Paintbrush_Y,0);
 
2223
      }
 
2224
      else
 
2225
      {
 
2226
        x1=x3=1-Brush_width;
 
2227
        y1=y2=start_y;
 
2228
        x2=x4=Paintbrush_X;
 
2229
        y3=y4=end_y;
 
2230
 
 
2231
        x1+=Paintbrush_X;
 
2232
        y1+=Paintbrush_Y;
 
2233
        y2+=Paintbrush_Y;
 
2234
        x3+=Paintbrush_X;
 
2235
        y3+=Paintbrush_Y;
 
2236
        y4+=Paintbrush_Y;
 
2237
        Pixel_figure_preview_xor(Paintbrush_X-end_x,Paintbrush_Y,0);
 
2238
        Draw_line_preview_xor(Paintbrush_X-end_x,Paintbrush_Y,Paintbrush_X,Paintbrush_Y,0);
 
2239
      }
 
2240
 
 
2241
      Draw_line_preview_xor(x1,y1,x2,y2,0);
 
2242
      Draw_line_preview_xor(x2,y2,x4,y4,0);
 
2243
      Draw_line_preview_xor(x4,y4,x3,y3,0);
 
2244
      Draw_line_preview_xor(x3,y3,x1,y1,0);
 
2245
  }
 
2246
}
 
2247
 
 
2248
  // -- Effacer le curseur --
 
2249
 
 
2250
void Hide_cursor(void)
 
2251
{
 
2252
  byte  shape;
 
2253
  int start_x; // int car sont parfois n�gatifs ! (quand on dessine sur un bord)
 
2254
  int start_y;
 
2255
  short end_x;
 
2256
  short end_y;
 
2257
  int x_pos = 0;
 
2258
  int y_pos;
 
2259
  short counter_x = 0;
 
2260
  short counter_y;
 
2261
  int   temp;
 
2262
  float cos_a,sin_a;
 
2263
  short x1,y1,x2,y2,x3,y3,x4,y4;
 
2264
 
 
2265
  if ( ( (Mouse_Y<Menu_Y)
 
2266
      && ( (!Main_magnifier_mode) || (Mouse_X<Main_separator_position)
 
2267
                         || (Mouse_X>=Main_X_zoom) ) )
 
2268
    || (Windows_open) || (Cursor_shape==CURSOR_SHAPE_HOURGLASS) )
 
2269
    shape=Cursor_shape;
 
2270
  else
 
2271
    shape=CURSOR_SHAPE_ARROW;
 
2272
 
 
2273
  switch(shape)
 
2274
  {
 
2275
    case CURSOR_SHAPE_TARGET :
 
2276
      if (!Cursor_hidden)
 
2277
      {
 
2278
        if (Config.Cursor==1)
 
2279
        {
 
2280
          start_y=(Mouse_Y<6)?6-Mouse_Y:0;
 
2281
          if (start_y<4)
 
2282
            Vertical_XOR_line  (Mouse_X,Mouse_Y+start_y-6,4-start_y);
 
2283
 
 
2284
          start_x=(Mouse_X<6)?(short)6-Mouse_X:0;
 
2285
          if (start_x<4)
 
2286
            Horizontal_XOR_line(Mouse_X+start_x-6,Mouse_Y,4-start_x);
 
2287
 
 
2288
          end_x=(Mouse_X+7>Screen_width)?Mouse_X+7-Screen_width:0;
 
2289
          if (end_x<4)
 
2290
            Horizontal_XOR_line(Mouse_X+3,Mouse_Y,4-end_x);
 
2291
 
 
2292
          end_y=(Mouse_Y+7>Screen_height)?Mouse_Y+7-Screen_height:0;
 
2293
          if (end_y<4)
 
2294
            Vertical_XOR_line  (Mouse_X,Mouse_Y+3,4-end_y);
 
2295
 
 
2296
          Update_rect(Mouse_X+start_x-6,Mouse_Y+start_y-6,13-end_x,13-end_y);
 
2297
        }
 
2298
        else
 
2299
        {
 
2300
          temp=(Config.Cursor)?CURSOR_SHAPE_THIN_TARGET:CURSOR_SHAPE_TARGET;
 
2301
          start_x=Mouse_X-Gfx->Cursor_offset_X[temp];
 
2302
          start_y=Mouse_Y-Gfx->Cursor_offset_Y[temp];
 
2303
 
 
2304
          for (y_pos=start_y,counter_y=0;counter_y<15;y_pos++,counter_y++)
 
2305
          {
 
2306
            if(y_pos < 0) continue;
 
2307
            if(y_pos>=Screen_height) break;
 
2308
            for (x_pos=start_x,counter_x=0;counter_x<15;x_pos++,counter_x++)
 
2309
            {
 
2310
              if(x_pos < 0) continue;
 
2311
              else if (x_pos>=Screen_width) break;
 
2312
              Pixel(x_pos,y_pos,Cursor_background[counter_y][counter_x]);
 
2313
            }
 
2314
          }
 
2315
 
 
2316
          Update_rect(Max(start_x,0),Max(start_y,0),x_pos-start_x,y_pos-start_y);
 
2317
        }
 
2318
      }
 
2319
      if (!Paintbrush_hidden)
 
2320
      {
 
2321
        Hide_paintbrush(Paintbrush_X,Paintbrush_Y);
 
2322
      }
 
2323
      break;
 
2324
 
 
2325
    case CURSOR_SHAPE_COLORPICKER:
 
2326
      if (!Cursor_hidden)
 
2327
      {
 
2328
        if (Config.Cursor==1)
 
2329
        {
 
2330
          // Barres formant la croix principale
 
2331
 
 
2332
          start_y=(Mouse_Y<5)?5-Mouse_Y:0;
 
2333
          if (start_y<3)
 
2334
            Vertical_XOR_line  (Mouse_X,Mouse_Y+start_y-5,3-start_y);
 
2335
 
 
2336
          start_x=(Mouse_X<5)?(short)5-Mouse_X:0;
 
2337
          if (start_x<3)
 
2338
            Horizontal_XOR_line(Mouse_X+start_x-5,Mouse_Y,3-start_x);
 
2339
 
 
2340
          end_x=(Mouse_X+6>Screen_width)?Mouse_X+6-Screen_width:0;
 
2341
          if (end_x<3)
 
2342
            Horizontal_XOR_line(Mouse_X+3,Mouse_Y,3-end_x);
 
2343
 
 
2344
          end_y=(Mouse_Y+6>Screen_height)?Mouse_Y+6-Screen_height:0;
 
2345
          if (end_y<3)
 
2346
            Vertical_XOR_line  (Mouse_X,Mouse_Y+3,3-end_y);
 
2347
 
 
2348
          start_x=(!Mouse_X);
 
2349
          start_y=(!Mouse_Y);
 
2350
          end_x=(Mouse_X>=Screen_width-1);
 
2351
          end_y=(Mouse_Y>=Menu_Y-1);
 
2352
 
 
2353
          if (Mouse_Y>5)
 
2354
            Horizontal_XOR_line(start_x+Mouse_X-1,Mouse_Y-6,3-(start_x+end_x));
 
2355
 
 
2356
          if (Mouse_X>5)
 
2357
            Vertical_XOR_line  (Mouse_X-6,start_y+Mouse_Y-1,3-(start_y+end_y));
 
2358
 
 
2359
          if (Mouse_X<Screen_width-6)
 
2360
            Vertical_XOR_line  (Mouse_X+6,start_y+Mouse_Y-1,3-(start_y+end_y));
 
2361
 
 
2362
          if (Mouse_Y<Menu_Y-6)
 
2363
            Horizontal_XOR_line(start_x+Mouse_X-1,Mouse_Y+6,3-(start_x+end_x));
 
2364
 
 
2365
          Update_rect(start_x,start_y,end_x-start_x,end_y-start_y);
 
2366
        }
 
2367
        else
 
2368
        {
 
2369
          temp=(Config.Cursor)?CURSOR_SHAPE_THIN_COLORPICKER:CURSOR_SHAPE_COLORPICKER;
 
2370
          start_x=Mouse_X-Gfx->Cursor_offset_X[temp];
 
2371
          start_y=Mouse_Y-Gfx->Cursor_offset_Y[temp];
 
2372
 
 
2373
          for (y_pos=start_y,counter_y=0;counter_y<15;y_pos++,counter_y++)
 
2374
          {
 
2375
            if(y_pos<0) continue;
 
2376
            if(y_pos>=Screen_height) break;
 
2377
            for (x_pos=start_x,counter_x=0;counter_x<15;x_pos++,counter_x++)
 
2378
            {
 
2379
              if(x_pos<0) continue;
 
2380
              if(x_pos>=Screen_width) break;
 
2381
                  Pixel(x_pos,y_pos,Cursor_background[counter_y][counter_x]);
 
2382
            }
 
2383
          }
 
2384
          Update_rect(Max(start_x,0),Max(start_y,0),counter_x,counter_y);
 
2385
        }
 
2386
      }
 
2387
      if (!Paintbrush_hidden)
 
2388
        Hide_paintbrush(Paintbrush_X,Paintbrush_Y);
 
2389
      break;
 
2390
 
 
2391
    case CURSOR_SHAPE_MULTIDIRECTIONAL :
 
2392
    case CURSOR_SHAPE_HORIZONTAL :
 
2393
      if (Cursor_hidden)
 
2394
        break;
 
2395
 
 
2396
    case CURSOR_SHAPE_ARROW :
 
2397
    case CURSOR_SHAPE_HOURGLASS :
 
2398
      start_x=Mouse_X-Gfx->Cursor_offset_X[shape];
 
2399
      start_y=Mouse_Y-Gfx->Cursor_offset_Y[shape];
 
2400
 
 
2401
      for (y_pos=start_y,counter_y=0;counter_y<15;y_pos++,counter_y++)
 
2402
      {
 
2403
        if(y_pos<0) continue;
 
2404
        if(y_pos>=Screen_height) break;
 
2405
        for (x_pos=start_x,counter_x=0;counter_x<15;x_pos++,counter_x++)
 
2406
        {
 
2407
          if(x_pos<0) continue;
 
2408
          if(x_pos>=Screen_width) break;
 
2409
            Pixel(x_pos,y_pos,Cursor_background[counter_y][counter_x]);
 
2410
        }
 
2411
      }
 
2412
      Update_rect(Max(start_x,0),Max(start_y,0),counter_x,counter_y);
 
2413
      break;
 
2414
 
 
2415
    case CURSOR_SHAPE_XOR_TARGET :
 
2416
      x_pos=Paintbrush_X-Main_offset_X;
 
2417
      y_pos=Paintbrush_Y-Main_offset_Y;
 
2418
 
 
2419
      counter_x=(Main_magnifier_mode)?Main_separator_position:Screen_width; // width de la barre XOR
 
2420
      if ((y_pos<Menu_Y) && (Paintbrush_Y>=Limit_top))
 
2421
      {
 
2422
        Horizontal_XOR_line(0,Paintbrush_Y-Main_offset_Y,counter_x);
 
2423
        Update_rect(0,Paintbrush_Y-Main_offset_Y,counter_x,1);
 
2424
      }
 
2425
 
 
2426
      if ((x_pos<counter_x) && (Paintbrush_X>=Limit_left))
 
2427
      {
 
2428
        Vertical_XOR_line(Paintbrush_X-Main_offset_X,0,Menu_Y);
 
2429
        Update_rect(Paintbrush_X-Main_offset_X,0,1,Menu_Y);
 
2430
      }
 
2431
 
 
2432
      if (Main_magnifier_mode)
 
2433
      {
 
2434
        // UPDATERECT
 
2435
        if ((Paintbrush_Y>=Limit_top_zoom) && (Paintbrush_Y<=Limit_visible_bottom_zoom))
 
2436
          Horizontal_XOR_line_zoom(Limit_left_zoom,Paintbrush_Y,Main_magnifier_width);
 
2437
        if ((Paintbrush_X>=Limit_left_zoom) && (Paintbrush_X<=Limit_visible_right_zoom))
 
2438
          Vertical_XOR_line_zoom(Paintbrush_X,Limit_top_zoom,Main_magnifier_height);
 
2439
      }
 
2440
 
 
2441
 
 
2442
      break;
 
2443
    case CURSOR_SHAPE_XOR_RECTANGLE :
 
2444
      // !!! Cette forme ne peut pas �tre utilis�e en mode Loupe !!!
 
2445
 
 
2446
      // Petite croix au centre
 
2447
      start_x=(Mouse_X-3);
 
2448
      start_y=(Mouse_Y-3);
 
2449
      end_x  =(Mouse_X+4);
 
2450
      end_y  =(Mouse_Y+4);
 
2451
      if (start_x<0)
 
2452
        start_x=0;
 
2453
      if (start_y<0)
 
2454
        start_y=0;
 
2455
      if (end_x>Screen_width)
 
2456
        end_x=Screen_width;
 
2457
      if (end_y>Menu_Y)
 
2458
        end_y=Menu_Y;
 
2459
 
 
2460
      Horizontal_XOR_line(start_x,Mouse_Y,end_x-start_x);
 
2461
      Vertical_XOR_line  (Mouse_X,start_y,end_y-start_y);
 
2462
 
 
2463
      // Grand rectangle autour
 
2464
 
 
2465
      start_x=Mouse_X-(Main_magnifier_width>>1);
 
2466
      start_y=Mouse_Y-(Main_magnifier_height>>1);
 
2467
      if (start_x+Main_magnifier_width>=Limit_right-Main_offset_X)
 
2468
        start_x=Limit_right-Main_magnifier_width-Main_offset_X+1;
 
2469
      if (start_y+Main_magnifier_height>=Limit_bottom-Main_offset_Y)
 
2470
        start_y=Limit_bottom-Main_magnifier_height-Main_offset_Y+1;
 
2471
      if (start_x<0)
 
2472
        start_x=0;
 
2473
      if (start_y<0)
 
2474
        start_y=0;
 
2475
      end_x=start_x+Main_magnifier_width-1;
 
2476
      end_y=start_y+Main_magnifier_height-1;
 
2477
 
 
2478
      Horizontal_XOR_line(start_x,start_y,Main_magnifier_width);
 
2479
      Vertical_XOR_line(start_x,start_y+1,Main_magnifier_height-2);
 
2480
      Vertical_XOR_line(  end_x,start_y+1,Main_magnifier_height-2);
 
2481
      Horizontal_XOR_line(start_x,  end_y,Main_magnifier_width);
 
2482
 
 
2483
      Update_rect(start_x,start_y,end_x+1-start_x,end_y+1-start_y);
 
2484
 
 
2485
      break;
 
2486
    default: //case CURSOR_SHAPE_XOR_ROTATION :
 
2487
      start_x=1-(Brush_width>>1);
 
2488
      start_y=1-(Brush_height>>1);
 
2489
      end_x=start_x+Brush_width-1;
 
2490
      end_y=start_y+Brush_height-1;
 
2491
 
 
2492
      if (Brush_rotation_center_is_defined)
 
2493
      {
 
2494
        if ( (Brush_rotation_center_X==Paintbrush_X)
 
2495
          && (Brush_rotation_center_Y==Paintbrush_Y) )
 
2496
        {
 
2497
          cos_a=1.0;
 
2498
          sin_a=0.0;
 
2499
        }
 
2500
        else
 
2501
        {
 
2502
          x_pos=Paintbrush_X-Brush_rotation_center_X;
 
2503
          y_pos=Paintbrush_Y-Brush_rotation_center_Y;
 
2504
          cos_a=(float)x_pos/sqrt((x_pos*x_pos)+(y_pos*y_pos));
 
2505
          sin_a=sin(acos(cos_a));
 
2506
          if (y_pos>0) sin_a=-sin_a;
 
2507
        }
 
2508
 
 
2509
        Transform_point(start_x,start_y, cos_a,sin_a, &x1,&y1);
 
2510
        Transform_point(end_x  ,start_y, cos_a,sin_a, &x2,&y2);
 
2511
        Transform_point(start_x,end_y  , cos_a,sin_a, &x3,&y3);
 
2512
        Transform_point(end_x  ,end_y  , cos_a,sin_a, &x4,&y4);
 
2513
 
 
2514
        x1+=Brush_rotation_center_X;
 
2515
        y1+=Brush_rotation_center_Y;
 
2516
        x2+=Brush_rotation_center_X;
 
2517
        y2+=Brush_rotation_center_Y;
 
2518
        x3+=Brush_rotation_center_X;
 
2519
        y3+=Brush_rotation_center_Y;
 
2520
        x4+=Brush_rotation_center_X;
 
2521
        y4+=Brush_rotation_center_Y;
 
2522
        Pixel_figure_preview_xor(Brush_rotation_center_X,Brush_rotation_center_Y,0);
 
2523
        Draw_line_preview_xor(Brush_rotation_center_X,Brush_rotation_center_Y,Paintbrush_X,Paintbrush_Y,0);
 
2524
      }
 
2525
      else
 
2526
      {
 
2527
        x1=x3=1-Brush_width;
 
2528
        y1=y2=start_y;
 
2529
        x2=x4=Paintbrush_X;
 
2530
        y3=y4=end_y;
 
2531
 
 
2532
        x1+=Paintbrush_X;
 
2533
        y1+=Paintbrush_Y;
 
2534
        y2+=Paintbrush_Y;
 
2535
        x3+=Paintbrush_X;
 
2536
        y3+=Paintbrush_Y;
 
2537
        y4+=Paintbrush_Y;
 
2538
        Pixel_figure_preview_xor(Paintbrush_X-end_x,Paintbrush_Y,0);
 
2539
        Draw_line_preview_xor(Paintbrush_X-end_x,Paintbrush_Y,Paintbrush_X,Paintbrush_Y,0);
 
2540
      }
 
2541
 
 
2542
      Draw_line_preview_xor(x1,y1,x2,y2,0);
 
2543
      Draw_line_preview_xor(x2,y2,x4,y4,0);
 
2544
      Draw_line_preview_xor(x4,y4,x3,y3,0);
 
2545
      Draw_line_preview_xor(x3,y3,x1,y1,0);
 
2546
  }
 
2547
}
 
2548
 
 
2549
 
 
2550
 
 
2551
// -- Fonction diverses d'affichage ------------------------------------------
 
2552
 
 
2553
  // -- Reafficher toute l'image (en prenant en compte le facteur de zoom) --
 
2554
 
 
2555
void Display_all_screen(void)
 
2556
{
 
2557
  word width;
 
2558
  word height;
 
2559
 
 
2560
  // ---/\/\/\  Partie non zoom�e: /\/\/\---
 
2561
  if (Main_magnifier_mode)
 
2562
  {
 
2563
    if (Main_image_width<Main_separator_position)
 
2564
      width=Main_image_width;
 
2565
    else
 
2566
      width=Main_separator_position;
 
2567
  }
 
2568
  else
 
2569
  {
 
2570
    if (Main_image_width<Screen_width)
 
2571
      width=Main_image_width;
 
2572
    else
 
2573
      width=Screen_width;
 
2574
  }
 
2575
  if (Main_image_height<Menu_Y)
 
2576
    height=Main_image_height;
 
2577
  else
 
2578
    height=Menu_Y;
 
2579
  Display_screen(width,height,Main_image_width);
 
2580
 
 
2581
  // Effacement de la partie non-image dans la partie non zoom�e:
 
2582
  if (Main_magnifier_mode)
 
2583
  {
 
2584
    if (Main_image_width<Main_separator_position && Main_image_width < Screen_width)
 
2585
      Block(Main_image_width,0,(Main_separator_position-Main_image_width),Menu_Y,Main_backups->Pages->Transparent_color);
 
2586
  }
 
2587
  else
 
2588
  {
 
2589
    if (Main_image_width<Screen_width)
 
2590
      Block(Main_image_width,0,(Screen_width-Main_image_width),Menu_Y,Main_backups->Pages->Transparent_color);
 
2591
  }
 
2592
  if (Main_image_height<Menu_Y)
 
2593
    Block(0,Main_image_height,width,(Menu_Y-height),Main_backups->Pages->Transparent_color);
 
2594
 
 
2595
  // ---/\/\/\  Partie zoom�e: /\/\/\---
 
2596
  if (Main_magnifier_mode)
 
2597
  {
 
2598
    // Affichage de la barre de split
 
2599
    Display_separator();
 
2600
 
 
2601
    // Calcul de la largeur visible
 
2602
    if (Main_image_width<Main_magnifier_width)
 
2603
      width=Main_image_width;
 
2604
    else
 
2605
      width=Main_magnifier_width;
 
2606
 
 
2607
    // Calcul du nombre de lignes visibles de l'image zoom�e
 
2608
    if (Main_image_height<Main_magnifier_height)
 
2609
      height=Main_image_height*Main_magnifier_factor;
 
2610
    else
 
2611
      height=Menu_Y;
 
2612
 
 
2613
    Display_zoomed_screen(width,height,Main_image_width,Horizontal_line_buffer);
 
2614
 
 
2615
    // Effacement de la partie non-image dans la partie zoom�e:
 
2616
    if (Main_image_width<Main_magnifier_width)
 
2617
      Block(Main_X_zoom+(Main_image_width*Main_magnifier_factor),0,
 
2618
            (Main_magnifier_width-Main_image_width)*Main_magnifier_factor,
 
2619
            Menu_Y,Main_backups->Pages->Transparent_color);
 
2620
    if (Main_image_height<Main_magnifier_height)
 
2621
      Block(Main_X_zoom,height,width*Main_magnifier_factor,(Menu_Y-height),Main_backups->Pages->Transparent_color);
 
2622
  }
 
2623
 
 
2624
  // ---/\/\/\ Affichage des limites /\/\/\---
 
2625
  if (Config.Display_image_limits)
 
2626
    Display_image_limits();
 
2627
  Update_rect(0,0,Screen_width,Menu_Y); // TODO On peut faire plus fin, en �vitant de mettre � jour la partie � droite du split quand on est en mode loupe. Mais c'est pas vraiment int�ressant ?
 
2628
}
 
2629
 
 
2630
 
 
2631
 
 
2632
byte Best_color(byte r,byte g,byte b)
 
2633
{
 
2634
  short col;
 
2635
  int   delta_r,delta_g,delta_b;
 
2636
  int   dist;
 
2637
  int   best_dist=0x7FFFFFFF;
 
2638
  int   rmean;
 
2639
  byte  best_color=0;
 
2640
 
 
2641
  for (col=0; col<256; col++)
 
2642
  {
 
2643
    if (!Exclude_color[col])
 
2644
    {
 
2645
      delta_r=(int)Main_palette[col].R-r;
 
2646
      delta_g=(int)Main_palette[col].G-g;
 
2647
      delta_b=(int)Main_palette[col].B-b;
 
2648
 
 
2649
      rmean = ( Main_palette[col].R + r ) / 2;
 
2650
 
 
2651
      if (!(dist= ( ( (512+rmean) *delta_r*delta_r) >>8) + 4*delta_g*delta_g + (((767-rmean)*delta_b*delta_b)>>8)))
 
2652
      //if (!(dist=(delta_r*delta_r*30)+(delta_g*delta_g*59)+(delta_b*delta_b*11)))
 
2653
        return col;
 
2654
 
 
2655
      if (dist<best_dist)
 
2656
      {
 
2657
        best_dist=dist;
 
2658
        best_color=col;
 
2659
      }
 
2660
    }
 
2661
  }
 
2662
 
 
2663
  return best_color;
 
2664
}
 
2665
 
 
2666
byte Best_color_nonexcluded(byte red,byte green,byte blue)
 
2667
{
 
2668
  short col;
 
2669
  int   delta_r,delta_g,delta_b;
 
2670
  int   dist;
 
2671
  int   best_dist=0x7FFFFFFF;
 
2672
  int   rmean;
 
2673
  byte  best_color=0;
 
2674
 
 
2675
  for (col=0; col<256; col++)
 
2676
  {
 
2677
    delta_r=(int)Main_palette[col].R-red;
 
2678
    delta_g=(int)Main_palette[col].G-green;
 
2679
    delta_b=(int)Main_palette[col].B-blue;
 
2680
 
 
2681
    if(delta_r == 0 && delta_g == 0 && delta_b == 0) return col;
 
2682
 
 
2683
    rmean = ( Main_palette[col].R + red ) / 2;
 
2684
 
 
2685
    dist= ( ( (512+rmean) *delta_r*delta_r) >>8) + 4*delta_g*delta_g + (((767-rmean)*delta_b*delta_b)>>8);
 
2686
    //dist=(delta_r*delta_r*30)+(delta_g*delta_g*59)+(delta_b*delta_b*11)
 
2687
 
 
2688
    if (dist<best_dist)
 
2689
    {
 
2690
      best_dist=dist;
 
2691
      best_color=col;
 
2692
    }
 
2693
  }
 
2694
  return best_color;
 
2695
}
 
2696
 
 
2697
void Compute_4_best_colors_for_1_menu_color
 
2698
     (byte red, byte green, byte blue, T_Components * palette, byte * table)
 
2699
{
 
2700
  short col;
 
2701
  int   delta_r,delta_g,delta_b;
 
2702
  int   dist;
 
2703
  int   best_dist[4]={0x7FFFFFFF,0x7FFFFFFF,0x7FFFFFFF,0x7FFFFFFF};
 
2704
 
 
2705
 
 
2706
  for (col=0; col<256; col++)
 
2707
  {
 
2708
    delta_r=(int)palette[col].R-red;
 
2709
    delta_g=(int)palette[col].G-green;
 
2710
    delta_b=(int)palette[col].B-blue;
 
2711
 
 
2712
    dist=(delta_r*delta_r*30)+(delta_g*delta_g*59)+(delta_b*delta_b*11);
 
2713
 
 
2714
    if (dist<best_dist[0])
 
2715
    {
 
2716
      best_dist[3]=best_dist[2];
 
2717
      best_dist[2]=best_dist[1];
 
2718
      best_dist[1]=best_dist[0];
 
2719
      best_dist[0]=dist;
 
2720
      table[3]=table[2];
 
2721
      table[2]=table[1];
 
2722
      table[1]=table[0];
 
2723
      table[0]=col;
 
2724
    }
 
2725
    else
 
2726
    {
 
2727
      if (dist<best_dist[1])
 
2728
      {
 
2729
        best_dist[3]=best_dist[2];
 
2730
        best_dist[2]=best_dist[1];
 
2731
        best_dist[1]=dist;
 
2732
        table[3]=table[2];
 
2733
        table[2]=table[1];
 
2734
        table[1]=col;
 
2735
      }
 
2736
      else
 
2737
      {
 
2738
        if (dist<best_dist[2])
 
2739
        {
 
2740
          best_dist[3]=best_dist[2];
 
2741
          best_dist[2]=dist;
 
2742
          table[3]=table[2];
 
2743
          table[2]=col;
 
2744
        }
 
2745
        else
 
2746
        if (dist<best_dist[3])
 
2747
        {
 
2748
          best_dist[3]=dist;
 
2749
          table[3]=col;
 
2750
        }
 
2751
      }
 
2752
    }
 
2753
  }
 
2754
}
 
2755
 
 
2756
 
 
2757
 
 
2758
byte Old_black;
 
2759
byte Old_dark;
 
2760
byte Old_light;
 
2761
byte Old_white;
 
2762
byte Old_trans;
 
2763
 
 
2764
void Remap_pixel(byte * pixel)
 
2765
{
 
2766
  if (*pixel==Old_light)         // On commence par tester le Gris clair
 
2767
    *pixel=MC_Light;             // qui est pas mal utilis�.
 
2768
  else
 
2769
  {
 
2770
    if (*pixel==Old_black)        // Puis le Noir...
 
2771
      *pixel=MC_Black;
 
2772
    else
 
2773
    {
 
2774
      if (*pixel==Old_dark)     // etc...
 
2775
        *pixel=MC_Dark;
 
2776
      else
 
2777
      {
 
2778
        if (*pixel==Old_white)
 
2779
          *pixel=MC_White;
 
2780
        else
 
2781
        {
 
2782
          if (*pixel==Old_trans)
 
2783
            *pixel=MC_Trans;
 
2784
        }
 
2785
      }
 
2786
    }
 
2787
  }
 
2788
}
 
2789
 
 
2790
 
 
2791
 
 
2792
void Remap_screen_after_menu_colors_change(void)
 
2793
{
 
2794
  short index;
 
2795
  byte  conversion_table[256];
 
2796
  short temp/*,temp2*/;
 
2797
 
 
2798
  if ( (MC_Light!=Old_light) || (MC_Dark!=Old_dark) || (MC_White!=Old_white) || (MC_Black !=Old_black )
 
2799
    || (MC_Trans!=Old_trans) )
 
2800
  {
 
2801
    // Cr�ation de la table de conversion
 
2802
    for (index=0; index<256; index++)
 
2803
      conversion_table[index]=index;
 
2804
 
 
2805
    conversion_table[Old_black ]=MC_Black;
 
2806
    conversion_table[Old_dark]=MC_Dark;
 
2807
    conversion_table[Old_light]=MC_Light;
 
2808
    conversion_table[Old_white]=MC_White;
 
2809
 
 
2810
    // Remappage de l'�cran
 
2811
 
 
2812
    temp=Window_height*Menu_factor_Y;
 
2813
 
 
2814
    Remap_screen(Window_pos_X, Window_pos_Y,
 
2815
                 Window_width*Menu_factor_X,
 
2816
                 (Window_pos_Y+temp<Menu_Y_before_window)?temp:Menu_Y_before_window-Window_pos_Y,
 
2817
                 conversion_table);
 
2818
 
 
2819
    if (Menu_is_visible_before_window)
 
2820
    {
 
2821
      Remap_screen(0, Menu_Y_before_window,
 
2822
                   Screen_width, Screen_height-Menu_Y_before_window,
 
2823
                   conversion_table);
 
2824
      // Remappage de la partie du fond de la fenetre qui cacherait le menu...
 
2825
      Remap_window_backgrounds(conversion_table, Menu_Y_before_window, Screen_height);
 
2826
      /*
 
2827
         Il faudrait peut-�tre remapper les pointill�s d�limitant l'image.
 
2828
         Mais �a va �tre chiant parce qu'ils peuvent �tre affich�s en mode Loupe.
 
2829
         Mais de toutes fa�ons, c'est franchement facultatif...
 
2830
      */
 
2831
      // On passe la table juste pour ne rafficher que les couleurs modifi�es
 
2832
      Display_menu_palette_avoiding_window(conversion_table);
 
2833
    }
 
2834
    Clear_border(MC_Black);
 
2835
  }
 
2836
 
 
2837
}
 
2838
 
 
2839
 
 
2840
 
 
2841
 
 
2842
void Compute_optimal_menu_colors(T_Components * palette)
 
2843
{
 
2844
  byte table[4];
 
2845
 
 
2846
  Old_black =MC_Black;
 
2847
  Old_dark = MC_Dark;
 
2848
  Old_light = MC_Light;
 
2849
  Old_white = MC_White;
 
2850
  Old_trans = MC_Trans;
 
2851
 
 
2852
  // Recherche du noir
 
2853
  Compute_4_best_colors_for_1_menu_color
 
2854
    (Config.Fav_menu_colors[0].R, Config.Fav_menu_colors[0].G, Config.Fav_menu_colors[0].B,palette,table);
 
2855
  MC_Black=table[0];
 
2856
 
 
2857
  // Recherche du blanc
 
2858
  Compute_4_best_colors_for_1_menu_color
 
2859
    (Config.Fav_menu_colors[3].R, Config.Fav_menu_colors[3].G, Config.Fav_menu_colors[3].B,palette,table);
 
2860
  if (MC_Black!=table[0])
 
2861
    MC_White=table[0];
 
2862
  else
 
2863
    MC_White=table[1];
 
2864
 
 
2865
  // Recherche du gris clair
 
2866
  Compute_4_best_colors_for_1_menu_color
 
2867
    (Config.Fav_menu_colors[2].R, Config.Fav_menu_colors[2].G, Config.Fav_menu_colors[2].B,palette,table);
 
2868
  if ( (MC_Black!=table[0]) && (MC_White!=table[0]) )
 
2869
    MC_Light=table[0];
 
2870
  else
 
2871
  {
 
2872
    if ( (MC_Black!=table[1]) && (MC_White!=table[1]) )
 
2873
      MC_Light=table[1];
 
2874
    else
 
2875
      MC_Light=table[2];
 
2876
  }
 
2877
 
 
2878
  // Recherche du gris fonc�
 
2879
  Compute_4_best_colors_for_1_menu_color
 
2880
    (Config.Fav_menu_colors[1].R, Config.Fav_menu_colors[1].G, Config.Fav_menu_colors[1].B,palette,table);
 
2881
  if ( (MC_Black!=table[0]) && (MC_White!=table[0]) && (MC_Light!=table[0]) )
 
2882
    MC_Dark=table[0];
 
2883
  else
 
2884
  {
 
2885
    if ( (MC_Black!=table[1]) && (MC_White!=table[1]) && (MC_Light!=table[1]) )
 
2886
      MC_Dark=table[1];
 
2887
    else
 
2888
    {
 
2889
      if ( (MC_Black!=table[2]) && (MC_White!=table[2]) && (MC_Light!=table[2]) )
 
2890
        MC_Dark=table[2];
 
2891
      else
 
2892
        MC_Dark=table[3];
 
2893
    }
 
2894
  }
 
2895
 
 
2896
  // C'est peu probable mais il est possible que MC_Light soit plus fonc�e que
 
2897
  // MC_Dark. Dans ce cas, on les inverse.
 
2898
  if ( ((palette[MC_Light].R*30)+(palette[MC_Light].G*59)+(palette[MC_Light].B*11)) <
 
2899
       ((palette[MC_Dark].R*30)+(palette[MC_Dark].G*59)+(palette[MC_Dark].B*11)) )
 
2900
  {
 
2901
    SWAP_BYTES(MC_Light, MC_Dark);
 
2902
  }
 
2903
 
 
2904
  // On cherche une couleur de transparence diff�rente des 4 autres.
 
2905
  for (MC_Trans=0; ((MC_Trans==MC_Black) || (MC_Trans==MC_Dark) ||
 
2906
                   (MC_Trans==MC_Light) || (MC_Trans==MC_White)); MC_Trans++);
 
2907
 
 
2908
  Remap_menu_sprites();
 
2909
}
 
2910
 
 
2911
/// Remap all menu data when the palette changes or a new skin is loaded
 
2912
void Remap_menu_sprites()
 
2913
{
 
2914
  int i, j, k, l;
 
2915
 
 
2916
  if ( (MC_Light!=Old_light)
 
2917
    || (MC_Dark!=Old_dark)
 
2918
    || (MC_White!=Old_white)
 
2919
    || (MC_Black !=Old_black )
 
2920
    || (MC_Trans!=Old_trans) )
 
2921
  {
 
2922
    // Mouse cursor sprites
 
2923
    for (k=0; k<NB_CURSOR_SPRITES; k++)
 
2924
      for (j=0; j<CURSOR_SPRITE_HEIGHT; j++)
 
2925
        for (i=0; i<CURSOR_SPRITE_WIDTH; i++)
 
2926
          Remap_pixel(&Gfx->Cursor_sprite[k][j][i]);
 
2927
    // Main menu bar
 
2928
    for (j=0; j<Menu_bars[MENUBAR_TOOLS].Height; j++)
 
2929
      for (i=0; i<Menu_bars[MENUBAR_TOOLS].Skin_width; i++)
 
2930
        Remap_pixel(&Gfx->Menu_block[j][i]);
 
2931
    // Menu sprites
 
2932
    for (k=0; k<NB_MENU_SPRITES; k++)
 
2933
      for (j=0; j<MENU_SPRITE_HEIGHT; j++)
 
2934
        for (i=0; i<MENU_SPRITE_WIDTH; i++)
 
2935
          Remap_pixel(&Gfx->Menu_sprite[k][j][i]);
 
2936
    // Effects sprites
 
2937
    for (k=0; k<NB_EFFECTS_SPRITES; k++)
 
2938
      for (j=0; j<MENU_SPRITE_HEIGHT; j++)
 
2939
        for (i=0; i<MENU_SPRITE_WIDTH; i++)
 
2940
          Remap_pixel(&Gfx->Effect_sprite[k][j][i]);
 
2941
    // Layers buttons
 
2942
    for (l=0; l<3; l++)
 
2943
      for (k=0; k<16; k++)
 
2944
        for (j=0; j<LAYER_SPRITE_HEIGHT; j++)
 
2945
          for (i=0; i<LAYER_SPRITE_WIDTH; i++)
 
2946
            Remap_pixel(&Gfx->Layer_sprite[l][k][j][i]);
 
2947
    
 
2948
    // Status bar
 
2949
    for (j=0; j<Menu_bars[MENUBAR_STATUS].Height; j++)
 
2950
      for (i=0; i<Menu_bars[MENUBAR_STATUS].Skin_width; i++)
 
2951
        Remap_pixel(&Gfx->Statusbar_block[j][i]);
 
2952
    // Layer bar
 
2953
    for (j=0; j<Menu_bars[MENUBAR_LAYERS].Height; j++)
 
2954
      for (i=0; i<Menu_bars[MENUBAR_LAYERS].Skin_width; i++)
 
2955
        Remap_pixel(&Gfx->Layerbar_block[j][i]);
 
2956
    
 
2957
    // Help fonts
 
2958
    for (k=0; k<256; k++)
 
2959
      for (j=0; j<8; j++)
 
2960
        for (i=0; i<6; i++)
 
2961
          Remap_pixel(&Gfx->Help_font_norm[k][i][j]);
 
2962
    for (k=0; k<256; k++)
 
2963
      for (j=0; j<8; j++)
 
2964
        for (i=0; i<6; i++)
 
2965
          Remap_pixel(&Gfx->Bold_font[k][i][j]);
 
2966
    for (k=0; k<64; k++)
 
2967
      for (j=0; j<8; j++)
 
2968
        for (i=0; i<6; i++)
 
2969
          Remap_pixel(&Gfx->Help_font_t1[k][i][j]);
 
2970
    for (k=0; k<64; k++)
 
2971
      for (j=0; j<8; j++)
 
2972
        for (i=0; i<6; i++)
 
2973
          Remap_pixel(&Gfx->Help_font_t2[k][i][j]);
 
2974
    for (k=0; k<64; k++)
 
2975
      for (j=0; j<8; j++)
 
2976
        for (i=0; i<6; i++)
 
2977
          Remap_pixel(&Gfx->Help_font_t3[k][i][j]);
 
2978
    for (k=0; k<64; k++)
 
2979
      for (j=0; j<8; j++)
 
2980
        for (i=0; i<6; i++)
 
2981
          Remap_pixel(&Gfx->Help_font_t4[k][i][j]);
 
2982
        
 
2983
    // Drives and other misc. 8x8 icons
 
2984
    for (k=0; k<NB_ICON_SPRITES; k++)
 
2985
      for (j=0; j<ICON_SPRITE_HEIGHT; j++)
 
2986
        for (i=0; i<ICON_SPRITE_WIDTH; i++)
 
2987
          Remap_pixel(&Gfx->Icon_sprite[k][j][i]);
 
2988
 
 
2989
    // Skin preview
 
2990
    for (j = 0; j < 173; j++)
 
2991
      for (i = 0; i < 16; i++)
 
2992
        Remap_pixel(&Gfx->Preview[i][j]);
 
2993
  }
 
2994
  Clear_border(MC_Black);
 
2995
}