1 /* vim:expandtab:ts=2 sw=2:
2 */
3 /*  Grafx2 - The Ultimate 256-color bitmap paint program
4 
5 	Copyright owned by various GrafX2 authors, see COPYRIGHT.txt for details.
6 
7     Grafx2 is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License
9     as published by the Free Software Foundation; version 2
10     of the License.
11 
12     Grafx2 is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with Grafx2; if not, see <http://www.gnu.org/licenses/>
19 */
20 
21 // Signal handler: I activate it for the two platforms who certainly
22 // support them. Feel free to check with others.
23 #if defined(WIN32) || defined(__linux__)
24   #define GRAFX2_CATCHES_SIGNALS
25 #endif
26 
27 #if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
28   #include <proto/exec.h>
29   #include <proto/dos.h>
30 #endif
31 
32 #include <stdio.h>
33 #include <string.h>
34 
35 #if !defined(__VBCC__) && !defined(_MSC_VER)
36     #include <unistd.h>
37 #endif
38 
39 #include <stdlib.h>
40 #include <errno.h>
41 #if defined(USE_SDL) || defined(USE_SDL2)
42 #include <SDL_image.h>
43 #endif
44 #if defined(USE_SDL)
45 #include <SDL_byteorder.h>
46 #endif
47 #if defined (__MINT__)
48   #include <mint/osbind.h>
49 #endif
50 #ifdef GRAFX2_CATCHES_SIGNALS
51   #include <signal.h>
52 #endif
53 #if defined(_MSC_VER)
54 #define strncasecmp _strnicmp
55 #define strdup _strdup
56 #if _MSC_VER < 1900
57 #define snprintf _snprintf
58 #endif
59 #endif
60 
61 #include "gfx2mem.h"
62 #include "buttons.h"
63 #include "const.h"
64 #include "errors.h"
65 #include "global.h"
66 #include "graph.h"
67 #include "init.h"
68 #include "io.h"
69 #include "factory.h"
70 #include "help.h"
71 #include "hotkeys.h"
72 #include "keyboard.h"
73 #include "loadsave.h" // Image_emergency_backup
74 #include "misc.h"
75 #include "mountlist.h" // read_file_system_list
76 #include "operatio.h"
77 #include "palette.h"
78 #include "screen.h"
79 #if defined(USE_SDL) || defined(USE_SDL2)
80 #include "sdlscreen.h"
81 #endif
82 #include "setup.h"
83 #include "struct.h"
84 #include "transform.h"
85 #include "windows.h"
86 #include "layers.h"
87 #include "special.h"
88 #include "gfx2surface.h"
89 
90 char Gui_loading_error_message[256];
91 
92 // Rechercher la liste et le type des lecteurs de la machine
93 
94 #if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
95 void bstrtostr( BSTR in, STRPTR out, TEXT max );
96 #endif
97 
98 // Fonctions de lecture dans la skin de l'interface graphique
GUI_seek_down(T_GFX2_Surface * gui,int * start_x,int * start_y,byte neutral_color,char * section)99 static byte GUI_seek_down(T_GFX2_Surface *gui, int *start_x, int *start_y, byte neutral_color,char * section)
100 {
101   byte color;
102   int y;
103   y=*start_y;
104   *start_x=0;
105   do
106   {
107     color=Get_GFX2_Surface_pixel(gui,*start_x,y);
108     if (color!=neutral_color)
109     {
110       *start_y=y;
111       return 0;
112     }
113     y++;
114   } while (y<gui->h);
115 
116   sprintf(Gui_loading_error_message, "Error in skin file: Was looking down from %d,%d for a '%s', and reached the end of the image\n",
117     *start_x, *start_y, section);
118   return 1;
119 }
120 
GUI_seek_right(T_GFX2_Surface * gui,int * start_x,int start_y,byte neutral_color,char * section)121 static byte GUI_seek_right(T_GFX2_Surface *gui, int *start_x, int start_y, byte neutral_color, char * section)
122 {
123   byte color;
124   int x;
125   x=*start_x;
126 
127   do
128   {
129     color=Get_GFX2_Surface_pixel(gui,x,start_y);
130     if (color!=neutral_color)
131     {
132       *start_x=x;
133       return 0;
134     }
135     x++;
136   } while (x<gui->w);
137 
138   sprintf(Gui_loading_error_message, "Error in skin file: Was looking right from %d,%d for a '%s', and reached the edege of the image\n",
139     *start_x, start_y, section);
140   return 1;
141 }
142 
Read_GUI_block(T_Gui_skin * gfx,T_GFX2_Surface * gui,int start_x,int start_y,void * dest,int width,int height,char * section,int type)143 static byte Read_GUI_block(T_Gui_skin *gfx, T_GFX2_Surface *gui, int start_x, int start_y, void *dest, int width, int height, char * section, int type)
144 {
145   // type: 0 = normal GUI element, only 4 colors allowed
146   // type: 1 = mouse cursor, 4 colors allowed + transparent
147   // type: 2 = brush icon or sieve pattern (only gui->Color[3] and gui->Color_trans)
148   // type: 3 = raw bitmap (splash screen)
149 
150   byte * dest_ptr=dest;
151   int x,y;
152   byte color;
153 
154   // Verification taille
155   if (start_y+height>=gui->h || start_x+width>=gui->w)
156   {
157     sprintf(Gui_loading_error_message, "Error in skin file: Was looking at %d,%d for a %d*%d object (%s) but it doesn't fit the image.\n",
158       start_x, start_y, height, width, section);
159     return 1;
160   }
161 
162   for (y=start_y; y<start_y+height; y++)
163   {
164     for (x=start_x; x<start_x+width; x++)
165     {
166       color=Get_GFX2_Surface_pixel(gui,x,y);
167       if (type==0 && (color != gfx->Color[0] && color != gfx->Color[1] && color != gfx->Color[2] && color != gfx->Color[3]))
168       {
169         sprintf(Gui_loading_error_message, "Error in skin file: Was looking at %d,%d for a %d*%d object (%s) but at %d,%d a pixel was found with color %d which isn't one of the GUI colors (which were detected as %d,%d,%d,%d.\n",
170           start_x, start_y, height, width, section, x, y, color, gfx->Color[0], gfx->Color[1], gfx->Color[2], gfx->Color[3]);
171         return 1;
172       }
173       if (type==1 && (color != gfx->Color[0] && color != gfx->Color[1] && color != gfx->Color[2] && color != gfx->Color[3] && color != gfx->Color_trans))
174       {
175         sprintf(Gui_loading_error_message, "Error in skin file: Was looking at %d,%d for a %d*%d object (%s) but at %d,%d a pixel was found with color %d which isn't one of the mouse colors (which were detected as %d,%d,%d,%d,%d.\n",
176           start_x, start_y, height, width, section, x, y, color, gfx->Color[0], gfx->Color[1], gfx->Color[2], gfx->Color[3], gfx->Color_trans);
177         return 1;
178       }
179       if (type==2)
180       {
181         if (color != gfx->Color[3] && color != gfx->Color_trans)
182         {
183           sprintf(Gui_loading_error_message, "Error in skin file: Was looking at %d,%d for a %d*%d object (%s) but at %d,%d a pixel was found with color %d which isn't one of the brush colors (which were detected as %d on %d.\n",
184             start_x, start_y, height, width, section, x, y, color, gfx->Color[3], gfx->Color_trans);
185           return 1;
186         }
187         // Conversion en 0/1 pour les brosses monochromes internes
188         color = (color != gfx->Color_trans);
189       }
190       *dest_ptr=color;
191       dest_ptr++;
192     }
193   }
194   return 0;
195 }
196 
Read_GUI_pattern(T_Gui_skin * gfx,T_GFX2_Surface * gui,int start_x,int start_y,word * dest,char * section)197 static byte Read_GUI_pattern(T_Gui_skin *gfx, T_GFX2_Surface *gui, int start_x, int start_y, word *dest, char * section)
198 {
199   byte buffer[256];
200   int x,y;
201 
202   if (Read_GUI_block(gfx, gui, start_x, start_y, buffer, 16, 16, section, 2))
203     return 1;
204 
205   for (y=0; y<16; y++)
206   {
207     *dest=0;
208     for (x=0; x<16; x++)
209     {
210       *dest=*dest | buffer[y*16+x]<<x;
211     }
212     dest++;
213   }
214   return 0;
215 }
216 
Center_GUI_cursor(T_Gui_skin * gfx,byte * cursor_buffer,int cursor_number)217 void Center_GUI_cursor(T_Gui_skin *gfx, byte *cursor_buffer, int cursor_number)
218 {
219   int x,y;
220   int start_x, start_y;
221   byte found;
222 
223   // Locate first non-empty column
224   found=0;
225   for (start_x=0;start_x<14;start_x++)
226   {
227     for (y=0;y<29;y++)
228     {
229       if (cursor_buffer[y*29+start_x]!=gfx->Color_trans)
230       {
231         found=1;
232         break;
233       }
234     }
235     if (found)
236       break;
237   }
238   // Locate first non-empty line
239   found=0;
240   for (start_y=0;start_y<14;start_y++)
241   {
242     for (x=0;x<29;x++)
243     {
244       if (cursor_buffer[start_y*29+x]!=gfx->Color_trans)
245       {
246         found=1;
247         break;
248       }
249     }
250     if (found)
251       break;
252   }
253   gfx->Cursor_offset_X[cursor_number]=14-start_x;
254   gfx->Cursor_offset_Y[cursor_number]=14-start_y;
255 
256   for (y=0;y<CURSOR_SPRITE_HEIGHT;y++)
257     for (x=0;x<CURSOR_SPRITE_WIDTH;x++)
258       gfx->Cursor_sprite[cursor_number][y][x]=cursor_buffer[(start_y+y)*29+start_x+x];
259 }
260 
Parse_skin(T_GFX2_Surface * gui,T_Gui_skin * gfx)261 static byte Parse_skin(T_GFX2_Surface * gui, T_Gui_skin *gfx)
262 {
263   int i,j;
264   int cursor_x=0,cursor_y=0;
265   byte color;
266   byte neutral_color; // color neutre utilisée pour délimiter les éléments GUI
267   int char_1=0;  // Indices utilisés pour les 4 "fontes" qui composent les
268   int char_2=0;  // grands titres de l'aide. Chaque indice avance dans
269   int char_3=0;  // l'une des fontes dans l'ordre :  1 2
270   int char_4=0;  //                                  3 4
271   byte mouse_cursor_area[31][29];
272 
273   // Default palette
274   memcpy(gfx->Default_palette, gui->palette, sizeof(T_Palette));
275 
276   // Carré "noir"
277   gfx->Color[0] = Get_GFX2_Surface_pixel(gui,cursor_x,cursor_y);
278   do
279   {
280     if (++cursor_x>=gui->w)
281     {
282       sprintf(Gui_loading_error_message, "Error in GUI skin file: should start with 5 consecutive squares for black, dark, light, white, transparent, then a neutral color\n");
283       return 1;
284     }
285     color=Get_GFX2_Surface_pixel(gui,cursor_x,cursor_y);
286   } while(color==gfx->Color[0]);
287   // Carré "foncé"
288   gfx->Color[1] = color;
289   do
290   {
291     if (++cursor_x>=gui->w)
292     {
293       sprintf(Gui_loading_error_message, "Error in GUI skin file: should start with 5 consecutive squares for black, dark, light, white, transparent, then a neutral color\n");
294       return 1;
295     }
296     color=Get_GFX2_Surface_pixel(gui,cursor_x,cursor_y);
297   } while(color==gfx->Color[1]);
298   // Carré "clair"
299   gfx->Color[2] = color;
300   do
301   {
302     if (++cursor_x>gui->w)
303     {
304       sprintf(Gui_loading_error_message, "Error in GUI skin file: should start with 5 consecutive squares for black, dark, light, white, transparent, then a neutral color\n");
305       return 1;
306     }
307     color=Get_GFX2_Surface_pixel(gui,cursor_x,cursor_y);
308   } while(color==gfx->Color[2]);
309   // Carré "blanc"
310   gfx->Color[3] = color;
311   do
312   {
313     if (++cursor_x>=gui->w)
314     {
315       sprintf(Gui_loading_error_message, "Error in GUI skin file: should start with 5 consecutive squares for black, dark, light, white, transparent, then a neutral color\n");
316       return 1;
317     }
318     color=Get_GFX2_Surface_pixel(gui,cursor_x,cursor_y);
319   } while(color==gfx->Color[3]);
320   // Carré "transparent"
321   gfx->Color_trans=color;
322   do
323   {
324     if (++cursor_x>=gui->w)
325     {
326       sprintf(Gui_loading_error_message, "Error in GUI skin file: should start with 5 consecutive squares for black, dark, light, white, transparent, then a neutral color\n");
327       return 1;
328     }
329     color=Get_GFX2_Surface_pixel(gui,cursor_x,cursor_y);
330   } while(color==gfx->Color_trans);
331   // Reste : couleur neutre
332   neutral_color=color;
333 
334 
335   cursor_x=0;
336   cursor_y=1;
337   while ((color=Get_GFX2_Surface_pixel(gui,cursor_x,cursor_y))==gfx->Color[0])
338   {
339     cursor_y++;
340     if (cursor_y>=gui->h)
341     {
342       sprintf(Gui_loading_error_message, "Error in GUI skin file: should start with 5 consecutive squares for black, dark, light, white, transparent, then a neutral color\n");
343       return 1;
344     }
345   }
346 
347   // Menu
348   if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "menu"))
349     return 1;
350   if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Menu_block[0], Menu_bars[MENUBAR_TOOLS].Skin_width, Menu_bars[MENUBAR_TOOLS].Height,"menu",0))
351     return 1;
352 
353   // Preview
354   cursor_x += Menu_bars[MENUBAR_TOOLS].Skin_width;
355   if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "preview"))
356     return 1;
357   if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Preview, 173, 16, "preview", 0))
358     return 1;
359   cursor_y+= Menu_bars[MENUBAR_TOOLS].Height;
360 
361   // Layerbar
362   if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "layer bar"))
363     return 1;
364   if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Layerbar_block[0], 144, 10,"layer bar",0))
365     return 1;
366   cursor_y+= Menu_bars[MENUBAR_LAYERS].Height;
367 
368   // Animbar
369   if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "anim bar"))
370     return 1;
371   if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Animbar_block[0], 236, 14,"anim bar",0))
372     return 1;
373   cursor_y+= Menu_bars[MENUBAR_ANIMATION].Height;
374 
375   // Status bar
376   if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "status bar"))
377     return 1;
378   if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Statusbar_block[0], Menu_bars[MENUBAR_STATUS].Skin_width, Menu_bars[MENUBAR_STATUS].Height,"status bar",0))
379     return 1;
380   cursor_y+= Menu_bars[MENUBAR_STATUS].Height;
381 
382   // Menu (selected)
383   if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "selected menu"))
384     return 1;
385   if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Menu_block[1], Menu_bars[MENUBAR_TOOLS].Skin_width, Menu_bars[MENUBAR_TOOLS].Height,"selected menu",0))
386     return 1;
387   cursor_y+= Menu_bars[MENUBAR_TOOLS].Height;
388 
389   // Layerbar (selected)
390   if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "selected layer bar"))
391     return 1;
392   if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Layerbar_block[1], 144, 10,"selected layer bar",0))
393     return 1;
394   cursor_y+= Menu_bars[MENUBAR_LAYERS].Height;
395 
396   // Animbar (selected)
397   if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "selected anim bar"))
398     return 1;
399   if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Animbar_block[1], 236, 14,"selected anim bar",0))
400     return 1;
401   cursor_y+= Menu_bars[MENUBAR_ANIMATION].Height;
402 
403   // Status bar (selected)
404   if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "selected status bar"))
405     return 1;
406   if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Statusbar_block[1], Menu_bars[MENUBAR_STATUS].Skin_width, Menu_bars[MENUBAR_STATUS].Height,"selected status bar",0))
407     return 1;
408   cursor_y+= Menu_bars[MENUBAR_STATUS].Height;
409 
410   // Effects
411   for (i=0; i<NB_EFFECTS_SPRITES; i++)
412   {
413     if (i==0)
414     {
415       if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "effect sprite"))
416         return 1;
417     }
418     else
419     {
420       if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "effect sprite"))
421         return 1;
422     }
423     if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Effect_sprite[i], EFFECT_SPRITE_WIDTH, EFFECT_SPRITE_HEIGHT, "effect sprite",0))
424       return 1;
425     cursor_x+=EFFECT_SPRITE_WIDTH;
426   }
427   cursor_y+=EFFECT_SPRITE_HEIGHT;
428 
429   // Layer sprite
430   for (j=0; j<3; j++)
431   {
432     for (i=0; i<16; i++)
433     {
434       if (i==0)
435       {
436         if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "layer sprite"))
437           return 1;
438       }
439       else
440       {
441         if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "layer sprite"))
442           return 1;
443       }
444       if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Layer_sprite[j][i], LAYER_SPRITE_WIDTH, LAYER_SPRITE_HEIGHT, "layer sprite",1))
445         return 1;
446       cursor_x+=LAYER_SPRITE_WIDTH;
447     }
448     cursor_y+=LAYER_SPRITE_HEIGHT;
449   }
450 
451 
452   // Mouse cursors
453   for (i=0; i<NB_CURSOR_SPRITES; i++)
454   {
455     if (i==0)
456     {
457       if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "mouse cursor"))
458         return 1;
459     }
460     else
461     {
462       if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "mouse cursor"))
463         return 1;
464     }
465     if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, mouse_cursor_area, 29, 31, "mouse cursor",1))
466       return 1;
467     Center_GUI_cursor(gfx, (byte *)mouse_cursor_area,i);
468     cursor_x+=29;
469   }
470   cursor_y+=31;
471 
472   // Menu sprites
473   for (i=0; i<NB_MENU_SPRITES; i++)
474   {
475     if (i==0)
476     {
477       if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "menu sprite"))
478         return 1;
479     }
480     else
481     {
482       if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "menu sprite"))
483         return 1;
484     }
485     if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Menu_sprite[0][i], MENU_SPRITE_WIDTH, MENU_SPRITE_HEIGHT, "menu sprite",1))
486       return 1;
487     cursor_x+=MENU_SPRITE_WIDTH;
488   }
489   cursor_y+=MENU_SPRITE_HEIGHT;
490 
491   // Menu sprites (selected)
492   for (i=0; i<NB_MENU_SPRITES; i++)
493   {
494     if (i==0)
495     {
496       if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "selected menu sprite"))
497         return 1;
498     }
499     else
500     {
501       if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "selected menu sprite"))
502         return 1;
503     }
504     if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Menu_sprite[1][i], MENU_SPRITE_WIDTH, MENU_SPRITE_HEIGHT, "selected menu sprite",1))
505       return 1;
506     cursor_x+=MENU_SPRITE_WIDTH;
507   }
508   cursor_y+=MENU_SPRITE_HEIGHT;
509 
510   // Drive sprites
511   for (i=0; i<NB_ICON_SPRITES; i++)
512   {
513     if (i==0)
514     {
515       if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "sprite drive"))
516         return 1;
517     }
518     else
519     {
520       if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "sprite drive"))
521         return 1;
522     }
523     if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Icon_sprite[i], ICON_SPRITE_WIDTH, ICON_SPRITE_HEIGHT, "sprite drive",1))
524       return 1;
525     cursor_x+=ICON_SPRITE_WIDTH;
526   }
527   cursor_y+=ICON_SPRITE_HEIGHT;
528 
529   // Logo splash screen
530 
531   if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "logo menu"))
532     return 1;
533   if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Logo_grafx2, 231, 56, "logo menu",3))
534     return 1;
535   cursor_y+=56;
536 
537   // Trames
538   for (i=0; i<NB_PRESET_SIEVE; i++)
539   {
540     if (i==0)
541     {
542       if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "sieve pattern"))
543         return 1;
544     }
545     else
546     {
547       if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "sieve pattern"))
548         return 1;
549     }
550     if (Read_GUI_pattern(gfx, gui, cursor_x, cursor_y, gfx->Sieve_pattern[i],"sieve pattern"))
551       return 1;
552     cursor_x+=16;
553   }
554   cursor_y+=16;
555 
556   // Help font: Normal
557   for (i=0; i<256; i++)
558   {
559     // Each line holds 32 symbols
560     if ((i%32)==0)
561     {
562       if (i!=0)
563         cursor_y+=8;
564       if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "help font (norm)"))
565         return 1;
566     }
567     else
568     {
569       if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "help font (norm)"))
570         return 1;
571     }
572     if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, &(gfx->Help_font_norm[i][0][0]), 6, 8, "help font (norm)",0))
573       return 1;
574     cursor_x+=6;
575   }
576   cursor_y+=8;
577 
578   // Help font: Bold
579   for (i=0; i<256; i++)
580   {
581     // Each line holds 32 symbols
582     if ((i%32)==0)
583     {
584       if (i!=0)
585         cursor_y+=8;
586       if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "help font (bold)"))
587         return 1;
588     }
589     else
590     {
591       if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "help font (bold)"))
592         return 1;
593     }
594     if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, &(gfx->Bold_font[i][0][0]), 6, 8, "help font (bold)",0))
595       return 1;
596     cursor_x+=6;
597   }
598   cursor_y+=8;
599 
600   // Help font: Title
601   for (i=0; i<256; i++)
602   {
603     byte * dest;
604     // Each line holds 64 symbols
605     if ((i%64)==0)
606     {
607       if (i!=0)
608         cursor_y+=8;
609       if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "help font (title)"))
610         return 1;
611     }
612     else
613     {
614       if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "help font (title)"))
615         return 1;
616     }
617 
618     if (i&1)
619       if (i&64)
620         dest=&(gfx->Help_font_t4[char_4++][0][0]);
621       else
622         dest=&(gfx->Help_font_t2[char_2++][0][0]);
623     else
624       if (i&64)
625         dest=&(gfx->Help_font_t3[char_3++][0][0]);
626       else
627         dest=&(gfx->Help_font_t1[char_1++][0][0]);
628 
629     if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, dest, 6, 8, "help font (title)",0))
630       return 1;
631     cursor_x+=6;
632   }
633   cursor_y+=8;
634 
635   // Copy unselected bitmaps to current ones
636   memcpy(gfx->Menu_block[2], gfx->Menu_block[0],
637     Menu_bars[MENUBAR_TOOLS].Skin_width*Menu_bars[MENUBAR_TOOLS].Height);
638   memcpy(gfx->Layerbar_block[2], gfx->Layerbar_block[0],
639     sizeof(gfx->Layerbar_block[0]));
640   memcpy(gfx->Animbar_block[2], gfx->Animbar_block[0],
641     sizeof(gfx->Animbar_block[0]));
642   memcpy(gfx->Statusbar_block[2], gfx->Statusbar_block[0],
643     Menu_bars[MENUBAR_STATUS].Skin_width*Menu_bars[MENUBAR_STATUS].Height);
644 
645 
646   return 0;
647 }
648 
Load_graphics(const char * skin_file,T_Gradient_array * gradients)649 T_Gui_skin * Load_graphics(const char * skin_file, T_Gradient_array *gradients)
650 {
651   T_Gui_skin * gfx;
652   char * directory;
653   size_t len;
654   T_GFX2_Surface * gui;
655 
656   if (skin_file == NULL || skin_file[0] == '\0')
657   {
658     sprintf(Gui_loading_error_message, "Wrong skin file name \"\"\n");
659     return NULL;
660   }
661 
662   gfx = (T_Gui_skin *)GFX2_malloc(sizeof(T_Gui_skin));
663   if (gfx == NULL)
664   {
665     sprintf(Gui_loading_error_message, "Not enough memory to read skin file\n");
666     return NULL;
667   }
668 
669   // Read the "skin" file
670   len = strlen(Data_directory) + strlen(SKINS_SUBDIRECTORY) + 1;
671   directory = GFX2_malloc(len);
672   if (directory == NULL)
673   {
674     free(gfx);
675     return NULL;
676   }
677   snprintf(directory, len, "%s%s", Data_directory, SKINS_SUBDIRECTORY);
678 
679   gui = Load_surface(skin_file, directory, gradients);
680   if (!gui)
681   {
682     sprintf(Gui_loading_error_message, "Unable to load the skin image (missing? not an image file?) : %s in %s\n", skin_file, directory);
683     free(directory);
684     free(gfx);
685     gfx = NULL;
686     return NULL;
687   }
688   free(directory);
689   if (Parse_skin(gui, gfx) != 0)
690   {
691     free(gfx);
692     gfx = NULL;
693   }
694   Free_GFX2_Surface(gui);
695   return gfx;
696 }
697 
698 // ---- font loading -----
699 
Parse_font(T_GFX2_Surface * image,int is_main)700 static byte * Parse_font(T_GFX2_Surface * image, int is_main)
701 {
702   byte * font;
703   int character;
704   byte color;
705   int x, y;
706   int chars_per_line;
707   int character_count;
708 
709   // Check image size
710   if (image->w % 8)
711   {
712     sprintf(Gui_loading_error_message, "Error in font file: Image width is not a multiple of 8.\n");
713     return NULL;
714   }
715   character_count = (image->w * image->h) / (8*8);
716   if (is_main && character_count < 256)
717   {
718     sprintf(Gui_loading_error_message, "Error in font file: Image is too small to be a 256-character 8x8 font.\n");
719     return NULL;
720   }
721   font = (byte *)GFX2_malloc(8*8*character_count);
722   if (font == NULL)
723   {
724     sprintf(Gui_loading_error_message, "Not enough memory to read font file\n");
725     return NULL;
726   }
727   chars_per_line = image->w/8;
728 
729   for (character=0; character < character_count; character++)
730   {
731     for (y=0; y<8; y++)
732     {
733       for (x=0;x<8; x++)
734       {
735         // Pick pixel
736         color = Get_GFX2_Surface_pixel(image, (character % chars_per_line)*8+x, (character / chars_per_line)*8+y);
737         if (color > 1)
738         {
739           sprintf(Gui_loading_error_message, "Error in font file: Only colors 0 and 1 can be used for the font.\n");
740           free(font);
741           return NULL;
742         }
743         // Put it in font. 0 = BG, 1 = FG.
744         font[character*64 + y*8 + x]=color;
745       }
746     }
747   }
748   return font;
749 }
750 
Load_font(const char * font_name,int is_main)751 byte * Load_font(const char * font_name, int is_main)
752 {
753   byte * font = NULL;
754   size_t len;
755   char * directory;
756   T_GFX2_Surface * image;
757 
758   if (font_name == NULL || font_name[0] == '\0')
759   {
760     sprintf(Gui_loading_error_message, "Wrong font name \"\"\n");
761     return NULL;
762   }
763 
764   // Read the file containing the image
765   len = strlen(Data_directory) + strlen(SKINS_SUBDIRECTORY) + 1;
766   directory = GFX2_malloc(len);
767   if (directory == NULL)
768     return NULL;
769   snprintf(directory, len, "%s%s", Data_directory, SKINS_SUBDIRECTORY);
770 
771   image = Load_surface(font_name, directory, NULL);
772   if (!image)
773   {
774     sprintf(Gui_loading_error_message, "Unable to load the font image (missing? not an image file?)\n%s in %s\n", font_name, directory);
775     free(directory);
776     return NULL;
777   }
778   free(directory);
779   font = Parse_font(image, is_main);
780   Free_GFX2_Surface(image);
781   return font;
782 }
783 
Load_Unicode_font(const char * fullname,const char * filename)784 static void Load_Unicode_font(const char * fullname, const char * filename)
785 {
786   T_Unicode_Font * ufont;
787   byte * font;
788   unsigned int first, last;
789   (void)fullname;
790 
791   if (strncasecmp(filename, "unicode_", 8) != 0)
792     return;
793   if (sscanf(filename + 8, "%04X-%04X.", &first, &last) == 2)
794   {
795     font = Load_font(filename, 0);
796     if (font)
797     {
798       ufont = GFX2_malloc(sizeof(T_Unicode_Font));
799       if (ufont != NULL)
800       {
801         ufont->FirstChar = first;
802         ufont->LastChar = last;
803         ufont->FontData = font;
804         ufont->Next = Unicode_fonts;
805         Unicode_fonts = ufont;
806       }
807     }
808   }
809   else
810     Warning_with_format("Could not parse filename %s", filename);
811 }
812 
Load_Unicode_fonts(void)813 void Load_Unicode_fonts(void)
814 {
815   char * directory;
816 
817   directory = Filepath_append_to_dir(Data_directory, SKINS_SUBDIRECTORY);
818   For_each_file(directory, Load_Unicode_font);
819   free(directory);
820 }
821 
822 // Initialisation des boutons:
823 
824   // Action factice:
825 
Do_nothing(int btn)826 static void Do_nothing(int btn)
827 {
828   (void)btn;
829 }
830 
831   // Initialiseur d'un bouton:
832 
833 static
Init_button(byte btn_number,const char * tooltip,word x_offset,word y_offset,word width,word height,byte shape,Func_btn_action left_action,Func_btn_action right_action,byte left_instant,byte right_instant,Func_btn_action unselect_action,byte family)834 void Init_button(byte        btn_number,
835                  const char* tooltip,
836                  word        x_offset, word   y_offset,
837                  word        width,    word   height,
838                  byte        shape,
839                  Func_btn_action left_action, Func_btn_action right_action,
840                  byte        left_instant,    byte        right_instant,
841                  Func_btn_action unselect_action,
842                  byte        family)
843 {
844   Buttons_Pool[btn_number].X_offset        =x_offset;
845   Buttons_Pool[btn_number].Y_offset        =y_offset;
846   Buttons_Pool[btn_number].Width           =width-1;
847   Buttons_Pool[btn_number].Height          =height-1;
848   Buttons_Pool[btn_number].Pressed         =0;
849   Buttons_Pool[btn_number].Icon            =-1;
850   Buttons_Pool[btn_number].Shape           =shape;
851   Buttons_Pool[btn_number].Tooltip         =tooltip;
852   Buttons_Pool[btn_number].Left_action     =left_action;
853   Buttons_Pool[btn_number].Right_action    =right_action;
854   Buttons_Pool[btn_number].Left_instant    =left_instant;
855   Buttons_Pool[btn_number].Right_instant   =right_instant;
856   Buttons_Pool[btn_number].Unselect_action =unselect_action;
857   Buttons_Pool[btn_number].Family          =family;
858 }
859 
860 
861   // Initiliseur de tous les boutons:
862 
Init_buttons(void)863 void Init_buttons(void)
864 {
865   byte button_index;
866 
867   for (button_index=0;button_index<NB_BUTTONS;button_index++)
868   {
869     Buttons_Pool[button_index].Left_shortcut[0]=0;
870     Buttons_Pool[button_index].Left_shortcut[1]=0;
871     Buttons_Pool[button_index].Right_shortcut[0]=0;
872     Buttons_Pool[button_index].Right_shortcut[1]=0;
873     Init_button(button_index,
874                 "",
875                 0,0,
876                 1,1,
877                 BUTTON_SHAPE_RECTANGLE,
878                 Do_nothing,Do_nothing,
879                 0,0,
880                 Do_nothing,
881                 0);
882   }
883 
884   // Ici viennent les déclarations des boutons que l'on sait gérer
885   #include "init_buttons.h"
886 
887 }
888 
889 
890 
891 // Initialisation des opérations:
892 
893   // Initialiseur d'une opération:
894 
Init_operation(byte operation_number,byte mouse_button,byte stack_index,Func_action action,byte hide_cursor,byte fast_mouse)895 void Init_operation(byte operation_number,
896                            byte mouse_button,
897                            byte stack_index,
898                            Func_action action,
899                            byte hide_cursor,
900                            byte fast_mouse)
901 {
902   Operation[operation_number][mouse_button]
903            [stack_index].Action=action;
904   Operation[operation_number][mouse_button]
905            [stack_index].Hide_cursor=hide_cursor;
906   Operation[operation_number][mouse_button]
907            [stack_index].Fast_mouse=fast_mouse;
908 }
909 
910 
911   // Initiliseur de toutes les opérations:
912 
Init_operations(void)913 void Init_operations(void)
914 {
915   byte number; // Numéro de l'option en cours d'auto-initialisation
916   byte Button; // Button souris en cours d'auto-initialisation
917   byte stack_index; // Taille de la pile en cours d'auto-initialisation
918   #define HIDE_CURSOR 1
919   #define FAST_MOUSE 1
920 
921   // Auto-initialisation des opérations (vers des actions inoffensives)
922 
923   for (number=0;number<NB_OPERATIONS;number++)
924     for (Button=0;Button<3;Button++)
925       for (stack_index=0;stack_index<OPERATION_STACK_SIZE;stack_index++)
926         Init_operation(number,Button,stack_index,Print_coordinates,0,FAST_MOUSE);
927 
928 
929   // Ici viennent les déclarations détaillées des opérations
930   Init_operation(OPERATION_CONTINUOUS_DRAW,1,0,
931                         Freehand_mode1_1_0,HIDE_CURSOR,0);
932   Init_operation(OPERATION_CONTINUOUS_DRAW,1,2,
933                         Freehand_mode1_1_2,0,0);
934   Init_operation(OPERATION_CONTINUOUS_DRAW,0,2,
935                         Freehand_mode12_0_2,0,0);
936   Init_operation(OPERATION_CONTINUOUS_DRAW,2,0,
937                         Freehand_mode1_2_0,HIDE_CURSOR,0);
938   Init_operation(OPERATION_CONTINUOUS_DRAW,2,2,
939                         Freehand_mode1_2_2,0,0);
940 
941   Init_operation(OPERATION_DISCONTINUOUS_DRAW,1,0,
942                         Freehand_mode2_1_0,HIDE_CURSOR,0);
943   Init_operation(OPERATION_DISCONTINUOUS_DRAW,1,2,
944                         Freehand_mode2_1_2,0,0);
945   Init_operation(OPERATION_DISCONTINUOUS_DRAW,0,2,
946                         Freehand_mode12_0_2,0,0);
947   Init_operation(OPERATION_DISCONTINUOUS_DRAW,2,0,
948                         Freehand_mode2_2_0,HIDE_CURSOR,0);
949   Init_operation(OPERATION_DISCONTINUOUS_DRAW,2,2,
950                         Freehand_mode2_2_2,0,0);
951 
952   Init_operation(OPERATION_POINT_DRAW,1,0,
953                         Freehand_mode3_1_0,HIDE_CURSOR,FAST_MOUSE);
954   Init_operation(OPERATION_POINT_DRAW,2,0,
955                         Freehand_Mode3_2_0,HIDE_CURSOR,FAST_MOUSE);
956   Init_operation(OPERATION_POINT_DRAW,0,1,
957                         Freehand_mode3_0_1,0,FAST_MOUSE);
958 
959   Init_operation(OPERATION_LINE,1,0,
960                         Line_12_0,HIDE_CURSOR,FAST_MOUSE);
961   Init_operation(OPERATION_LINE,1,5,
962                         Line_12_5,0,FAST_MOUSE);
963   Init_operation(OPERATION_LINE,0,5,
964                         Line_0_5,HIDE_CURSOR,FAST_MOUSE);
965   Init_operation(OPERATION_LINE,2,0,
966                         Line_12_0,HIDE_CURSOR,FAST_MOUSE);
967   Init_operation(OPERATION_LINE,2,5,
968                         Line_12_5,0,FAST_MOUSE);
969 
970   Init_operation(OPERATION_K_LINE,1,0,
971                         K_line_12_0,HIDE_CURSOR,FAST_MOUSE);
972   Init_operation(OPERATION_K_LINE,1,6,
973                         K_line_12_6,0,FAST_MOUSE);
974   Init_operation(OPERATION_K_LINE,1,7,
975                         K_line_12_7,HIDE_CURSOR,FAST_MOUSE);
976   Init_operation(OPERATION_K_LINE,2,FAST_MOUSE,
977                         K_line_12_0,HIDE_CURSOR,FAST_MOUSE);
978   Init_operation(OPERATION_K_LINE,2,6,
979                         K_line_12_6,0,FAST_MOUSE);
980   Init_operation(OPERATION_K_LINE,2,7,
981                         K_line_12_7,HIDE_CURSOR,FAST_MOUSE);
982   Init_operation(OPERATION_K_LINE,0,6,
983                         K_line_0_6,HIDE_CURSOR,FAST_MOUSE);
984   Init_operation(OPERATION_K_LINE,0,7,
985                         K_line_12_6,0,FAST_MOUSE);
986 
987   Init_operation(OPERATION_EMPTY_RECTANGLE,1,0,
988                         Rectangle_12_0,HIDE_CURSOR,FAST_MOUSE);
989   Init_operation(OPERATION_EMPTY_RECTANGLE,2,0,
990                         Rectangle_12_0,HIDE_CURSOR,FAST_MOUSE);
991   Init_operation(OPERATION_EMPTY_RECTANGLE,1,5,
992                         Rectangle_12_5,0,FAST_MOUSE);
993   Init_operation(OPERATION_EMPTY_RECTANGLE,2,5,
994                         Rectangle_12_5,0,FAST_MOUSE);
995   Init_operation(OPERATION_EMPTY_RECTANGLE,0,5,
996                         Empty_rectangle_0_5,HIDE_CURSOR,FAST_MOUSE);
997 
998   Init_operation(OPERATION_FILLED_RECTANGLE,1,0,
999                         Rectangle_12_0,HIDE_CURSOR,FAST_MOUSE);
1000   Init_operation(OPERATION_FILLED_RECTANGLE,2,0,
1001                         Rectangle_12_0,HIDE_CURSOR,FAST_MOUSE);
1002   Init_operation(OPERATION_FILLED_RECTANGLE,1,5,
1003                         Rectangle_12_5,0,FAST_MOUSE);
1004   Init_operation(OPERATION_FILLED_RECTANGLE,2,5,
1005                         Rectangle_12_5,0,FAST_MOUSE);
1006   Init_operation(OPERATION_FILLED_RECTANGLE,0,5,
1007                         Filled_rectangle_0_5,HIDE_CURSOR,FAST_MOUSE);
1008 
1009   Init_operation(OPERATION_EMPTY_CIRCLE_CTR,1,0,
1010                         Circle_12_0,HIDE_CURSOR,FAST_MOUSE);
1011   Init_operation(OPERATION_EMPTY_CIRCLE_CTR,2,0,
1012                         Circle_12_0,HIDE_CURSOR,FAST_MOUSE);
1013   Init_operation(OPERATION_EMPTY_CIRCLE_CTR,1,5,
1014                         Circle_12_5,0,FAST_MOUSE);
1015   Init_operation(OPERATION_EMPTY_CIRCLE_CTR,2,5,
1016                         Circle_12_5,0,FAST_MOUSE);
1017   Init_operation(OPERATION_EMPTY_CIRCLE_CTR,0,5,
1018                         Empty_circle_0_5,HIDE_CURSOR,FAST_MOUSE);
1019 
1020   Init_operation(OPERATION_EMPTY_CIRCLE_CRN,1,0,
1021                         Ellipse_12_0,HIDE_CURSOR,FAST_MOUSE);
1022   Init_operation(OPERATION_EMPTY_CIRCLE_CRN,2,0,
1023                         Ellipse_12_0,HIDE_CURSOR,FAST_MOUSE);
1024   Init_operation(OPERATION_EMPTY_CIRCLE_CRN,1,5,
1025                         Ellipse_12_5,0,FAST_MOUSE);
1026   Init_operation(OPERATION_EMPTY_CIRCLE_CRN,2,5,
1027                         Ellipse_12_5,0,FAST_MOUSE);
1028   Init_operation(OPERATION_EMPTY_CIRCLE_CRN,0,5,
1029                         Empty_ellipse_0_5,HIDE_CURSOR,FAST_MOUSE);
1030 
1031   Init_operation(OPERATION_FILLED_CIRCLE_CTR,1,0,
1032                         Circle_12_0,HIDE_CURSOR,FAST_MOUSE);
1033   Init_operation(OPERATION_FILLED_CIRCLE_CTR,2,0,
1034                         Circle_12_0,HIDE_CURSOR,FAST_MOUSE);
1035   Init_operation(OPERATION_FILLED_CIRCLE_CTR,1,5,
1036                         Circle_12_5,0,FAST_MOUSE);
1037   Init_operation(OPERATION_FILLED_CIRCLE_CTR,2,5,
1038                         Circle_12_5,0,FAST_MOUSE);
1039   Init_operation(OPERATION_FILLED_CIRCLE_CTR,0,5,
1040                         Filled_circle_0_5,HIDE_CURSOR,FAST_MOUSE);
1041 
1042   Init_operation(OPERATION_FILLED_CIRCLE_CRN,1,0,
1043                         Ellipse_12_0,HIDE_CURSOR,FAST_MOUSE);
1044   Init_operation(OPERATION_FILLED_CIRCLE_CRN,2,0,
1045                         Ellipse_12_0,HIDE_CURSOR,FAST_MOUSE);
1046   Init_operation(OPERATION_FILLED_CIRCLE_CRN,1,5,
1047                         Ellipse_12_5,0,FAST_MOUSE);
1048   Init_operation(OPERATION_FILLED_CIRCLE_CRN,2,5,
1049                         Ellipse_12_5,0,FAST_MOUSE);
1050   Init_operation(OPERATION_FILLED_CIRCLE_CRN,0,5,
1051                         Filled_ellipse_0_5,HIDE_CURSOR,FAST_MOUSE);
1052 
1053   Init_operation(OPERATION_EMPTY_ELLIPSE_CTR,1,0,
1054                         Ellipse_12_0,HIDE_CURSOR,FAST_MOUSE);
1055   Init_operation(OPERATION_EMPTY_ELLIPSE_CTR,2,0,
1056                         Ellipse_12_0,HIDE_CURSOR,FAST_MOUSE);
1057   Init_operation(OPERATION_EMPTY_ELLIPSE_CTR,1,5,
1058                         Ellipse_12_5,0,FAST_MOUSE);
1059   Init_operation(OPERATION_EMPTY_ELLIPSE_CTR,2,5,
1060                         Ellipse_12_5,0,FAST_MOUSE);
1061   Init_operation(OPERATION_EMPTY_ELLIPSE_CTR,0,5,
1062                         Empty_ellipse_0_5,HIDE_CURSOR,FAST_MOUSE);
1063 
1064   Init_operation(OPERATION_EMPTY_ELLIPSE_CRN,1,0,
1065                         Ellipse_12_0,HIDE_CURSOR,FAST_MOUSE);
1066   Init_operation(OPERATION_EMPTY_ELLIPSE_CRN,2,0,
1067                         Ellipse_12_0,HIDE_CURSOR,FAST_MOUSE);
1068   Init_operation(OPERATION_EMPTY_ELLIPSE_CRN,1,5,
1069                         Ellipse_12_5,0,FAST_MOUSE);
1070   Init_operation(OPERATION_EMPTY_ELLIPSE_CRN,2,5,
1071                         Ellipse_12_5,0,FAST_MOUSE);
1072   Init_operation(OPERATION_EMPTY_ELLIPSE_CRN,0,5,
1073                         Empty_ellipse_0_5,HIDE_CURSOR,FAST_MOUSE);
1074 
1075   Init_operation(OPERATION_FILLED_ELLIPSE_CTR,1,0,
1076                         Ellipse_12_0,HIDE_CURSOR,FAST_MOUSE);
1077   Init_operation(OPERATION_FILLED_ELLIPSE_CTR,2,0,
1078                         Ellipse_12_0,HIDE_CURSOR,FAST_MOUSE);
1079   Init_operation(OPERATION_FILLED_ELLIPSE_CTR,1,5,
1080                         Ellipse_12_5,0,FAST_MOUSE);
1081   Init_operation(OPERATION_FILLED_ELLIPSE_CTR,2,5,
1082                         Ellipse_12_5,0,FAST_MOUSE);
1083   Init_operation(OPERATION_FILLED_ELLIPSE_CTR,0,5,
1084                         Filled_ellipse_0_5,HIDE_CURSOR,FAST_MOUSE);
1085 
1086   Init_operation(OPERATION_FILLED_ELLIPSE_CRN,1,0,
1087                         Ellipse_12_0,HIDE_CURSOR,FAST_MOUSE);
1088   Init_operation(OPERATION_FILLED_ELLIPSE_CRN,2,0,
1089                         Ellipse_12_0,HIDE_CURSOR,FAST_MOUSE);
1090   Init_operation(OPERATION_FILLED_ELLIPSE_CRN,1,5,
1091                         Ellipse_12_5,0,FAST_MOUSE);
1092   Init_operation(OPERATION_FILLED_ELLIPSE_CRN,2,5,
1093                         Ellipse_12_5,0,FAST_MOUSE);
1094   Init_operation(OPERATION_FILLED_ELLIPSE_CRN,0,5,
1095                         Filled_ellipse_0_5,HIDE_CURSOR,FAST_MOUSE);
1096 
1097   Init_operation(OPERATION_FILL,1,0,
1098                         Fill_1_0,0,FAST_MOUSE);
1099   Init_operation(OPERATION_FILL,2,0,
1100                         Fill_2_0,0,FAST_MOUSE);
1101 
1102   Init_operation(OPERATION_REPLACE,1,0,
1103                         Replace_1_0,0,FAST_MOUSE);
1104   Init_operation(OPERATION_REPLACE,2,0,
1105                         Replace_2_0,0,FAST_MOUSE);
1106 
1107   Init_operation(OPERATION_GRAB_BRUSH,1,0,
1108                         Brush_12_0,HIDE_CURSOR,FAST_MOUSE);
1109   Init_operation(OPERATION_GRAB_BRUSH,2,0,
1110                         Brush_12_0,HIDE_CURSOR,FAST_MOUSE);
1111   Init_operation(OPERATION_GRAB_BRUSH,1,5,
1112                         Brush_12_5,0,FAST_MOUSE);
1113   Init_operation(OPERATION_GRAB_BRUSH,2,5,
1114                         Brush_12_5,0,FAST_MOUSE);
1115   Init_operation(OPERATION_GRAB_BRUSH,0,5,
1116                         Brush_0_5,HIDE_CURSOR,FAST_MOUSE);
1117 
1118   Init_operation(OPERATION_STRETCH_BRUSH,1,0,
1119                         Stretch_brush_12_0,HIDE_CURSOR,FAST_MOUSE);
1120   Init_operation(OPERATION_STRETCH_BRUSH,2,0,
1121                         Stretch_brush_12_0,HIDE_CURSOR,FAST_MOUSE);
1122   Init_operation(OPERATION_STRETCH_BRUSH,1,7,
1123                         Stretch_brush_1_7,0,FAST_MOUSE);
1124   Init_operation(OPERATION_STRETCH_BRUSH,0,7,
1125                         Stretch_brush_0_7,0,FAST_MOUSE);
1126   Init_operation(OPERATION_STRETCH_BRUSH,2,7,
1127                         Stretch_brush_2_7,HIDE_CURSOR,FAST_MOUSE);
1128 
1129   Init_operation(OPERATION_ROTATE_BRUSH,1,0,
1130                         Rotate_brush_12_0,HIDE_CURSOR,FAST_MOUSE);
1131   Init_operation(OPERATION_ROTATE_BRUSH,2,0,
1132                         Rotate_brush_12_0,HIDE_CURSOR,FAST_MOUSE);
1133   Init_operation(OPERATION_ROTATE_BRUSH,1,5,
1134                         Rotate_brush_1_5,0,FAST_MOUSE);
1135   Init_operation(OPERATION_ROTATE_BRUSH,0,5,
1136                         Rotate_brush_0_5,0,FAST_MOUSE);
1137   Init_operation(OPERATION_ROTATE_BRUSH,2,5,
1138                         Rotate_brush_2_5,HIDE_CURSOR,FAST_MOUSE);
1139 
1140   Init_operation(OPERATION_DISTORT_BRUSH,0,0,
1141                         Distort_brush_0_0,0,FAST_MOUSE);
1142   Init_operation(OPERATION_DISTORT_BRUSH,1,0,
1143                         Distort_brush_1_0,0,FAST_MOUSE);
1144   Init_operation(OPERATION_DISTORT_BRUSH,1,8,
1145                         Distort_brush_1_8,0,FAST_MOUSE);
1146   Init_operation(OPERATION_DISTORT_BRUSH,2,8,
1147                         Distort_brush_2_8,HIDE_CURSOR,FAST_MOUSE);
1148   Init_operation(OPERATION_DISTORT_BRUSH,2,0,
1149                         Distort_brush_2_0,HIDE_CURSOR,FAST_MOUSE);
1150   Init_operation(OPERATION_DISTORT_BRUSH,1,9,
1151                         Distort_brush_1_9,0,FAST_MOUSE);
1152   Init_operation(OPERATION_DISTORT_BRUSH,0,9,
1153                         Distort_brush_0_9,0,FAST_MOUSE);
1154 
1155 
1156   Init_operation(OPERATION_POLYBRUSH,1,0,
1157                         Filled_polyform_12_0,HIDE_CURSOR,FAST_MOUSE);
1158   Init_operation(OPERATION_POLYBRUSH,2,0,
1159                         Filled_polyform_12_0,HIDE_CURSOR,FAST_MOUSE);
1160   Init_operation(OPERATION_POLYBRUSH,1,8,
1161                         Polybrush_12_8,0,0);
1162   Init_operation(OPERATION_POLYBRUSH,2,8,
1163                         Polybrush_12_8,0,0);
1164   Init_operation(OPERATION_POLYBRUSH,0,8,
1165                         Filled_polyform_0_8,0,FAST_MOUSE);
1166 
1167   Colorpicker_color=-1;
1168   Init_operation(OPERATION_COLORPICK,1,0,
1169                         Colorpicker_12_0,HIDE_CURSOR,FAST_MOUSE);
1170   Init_operation(OPERATION_COLORPICK,2,0,
1171                         Colorpicker_12_0,0,FAST_MOUSE);
1172   Init_operation(OPERATION_COLORPICK,1,1,
1173                         Colorpicker_1_1,0,FAST_MOUSE);
1174   Init_operation(OPERATION_COLORPICK,2,1,
1175                         Colorpicker_2_1,0,FAST_MOUSE);
1176   Init_operation(OPERATION_COLORPICK,0,1,
1177                         Colorpicker_0_1,HIDE_CURSOR,FAST_MOUSE);
1178 
1179   Init_operation(OPERATION_MAGNIFY,1,0,
1180                         Magnifier_12_0,0,FAST_MOUSE);
1181   Init_operation(OPERATION_MAGNIFY,2,0,
1182                         Magnifier_12_0,0,FAST_MOUSE);
1183 
1184   Init_operation(OPERATION_4_POINTS_CURVE,1,0,
1185                         Curve_34_points_1_0,HIDE_CURSOR,FAST_MOUSE);
1186   Init_operation(OPERATION_4_POINTS_CURVE,2,0,
1187                         Curve_34_points_2_0,HIDE_CURSOR,FAST_MOUSE);
1188   Init_operation(OPERATION_4_POINTS_CURVE,1,5,
1189                         Curve_34_points_1_5,0,FAST_MOUSE);
1190   Init_operation(OPERATION_4_POINTS_CURVE,2,5,
1191                         Curve_34_points_2_5,0,FAST_MOUSE);
1192   Init_operation(OPERATION_4_POINTS_CURVE,0,5,
1193                         Curve_4_points_0_5,HIDE_CURSOR,FAST_MOUSE);
1194   Init_operation(OPERATION_4_POINTS_CURVE,1,9,
1195                         Curve_4_points_1_9,0,FAST_MOUSE);
1196   Init_operation(OPERATION_4_POINTS_CURVE,2,9,
1197                         Curve_4_points_2_9,0,FAST_MOUSE);
1198 
1199   Init_operation(OPERATION_3_POINTS_CURVE,1,0,
1200                         Curve_34_points_1_0,HIDE_CURSOR,FAST_MOUSE);
1201   Init_operation(OPERATION_3_POINTS_CURVE,2,0,
1202                         Curve_34_points_2_0,HIDE_CURSOR,FAST_MOUSE);
1203   Init_operation(OPERATION_3_POINTS_CURVE,1,5,
1204                         Curve_34_points_1_5,0,FAST_MOUSE);
1205   Init_operation(OPERATION_3_POINTS_CURVE,2,5,
1206                         Curve_34_points_2_5,0,FAST_MOUSE);
1207   Init_operation(OPERATION_3_POINTS_CURVE,0,5,
1208                         Curve_3_points_0_5,HIDE_CURSOR,FAST_MOUSE);
1209   Init_operation(OPERATION_3_POINTS_CURVE,0,11,
1210                         Curve_3_points_0_11,0,FAST_MOUSE);
1211   Init_operation(OPERATION_3_POINTS_CURVE,1,11,
1212                         Curve_3_points_12_11,0,FAST_MOUSE);
1213   Init_operation(OPERATION_3_POINTS_CURVE,2,11,
1214                         Curve_3_points_12_11,0,FAST_MOUSE);
1215 
1216   Init_operation(OPERATION_AIRBRUSH,1,0,
1217                         Airbrush_1_0,0,0);
1218   Init_operation(OPERATION_AIRBRUSH,2,0,
1219                         Airbrush_2_0,0,0);
1220   Init_operation(OPERATION_AIRBRUSH,1,2,
1221                         Airbrush_12_2,0,0);
1222   Init_operation(OPERATION_AIRBRUSH,2,2,
1223                         Airbrush_12_2,0,0);
1224   Init_operation(OPERATION_AIRBRUSH,0,2,
1225                         Airbrush_0_2,0,0);
1226 
1227   Init_operation(OPERATION_POLYGON,1,0,
1228                         Polygon_12_0,HIDE_CURSOR,FAST_MOUSE);
1229   Init_operation(OPERATION_POLYGON,2,0,
1230                         Polygon_12_0,HIDE_CURSOR,FAST_MOUSE);
1231   Init_operation(OPERATION_POLYGON,1,8,
1232                         K_line_12_6,0,FAST_MOUSE);
1233   Init_operation(OPERATION_POLYGON,2,8,
1234                         K_line_12_6,0,FAST_MOUSE);
1235   Init_operation(OPERATION_POLYGON,1,9,
1236                         Polygon_12_9,HIDE_CURSOR,FAST_MOUSE);
1237   Init_operation(OPERATION_POLYGON,2,9,
1238                         Polygon_12_9,HIDE_CURSOR,FAST_MOUSE);
1239   Init_operation(OPERATION_POLYGON,0,8,
1240                         K_line_0_6,HIDE_CURSOR,FAST_MOUSE);
1241   Init_operation(OPERATION_POLYGON,0,9,
1242                         K_line_12_6,0,FAST_MOUSE);
1243 
1244   Init_operation(OPERATION_POLYFILL,1,0,
1245                         Polyfill_12_0,HIDE_CURSOR,FAST_MOUSE);
1246   Init_operation(OPERATION_POLYFILL,2,0,
1247                         Polyfill_12_0,HIDE_CURSOR,FAST_MOUSE);
1248   Init_operation(OPERATION_POLYFILL,1,8,
1249                         Polyfill_12_8,0,FAST_MOUSE);
1250   Init_operation(OPERATION_POLYFILL,2,8,
1251                         Polyfill_12_8,0,FAST_MOUSE);
1252   Init_operation(OPERATION_POLYFILL,1,9,
1253                         Polyfill_12_9,0,FAST_MOUSE);
1254   Init_operation(OPERATION_POLYFILL,2,9,
1255                         Polyfill_12_9,0,FAST_MOUSE);
1256   Init_operation(OPERATION_POLYFILL,0,8,
1257                         Polyfill_0_8,HIDE_CURSOR,FAST_MOUSE);
1258   Init_operation(OPERATION_POLYFILL,0,9,
1259                         Polyfill_12_8,0,FAST_MOUSE);
1260 
1261   Init_operation(OPERATION_POLYFORM,1,0,
1262                         Polyform_12_0,HIDE_CURSOR,FAST_MOUSE);
1263   Init_operation(OPERATION_POLYFORM,2,0,
1264                         Polyform_12_0,HIDE_CURSOR,FAST_MOUSE);
1265   Init_operation(OPERATION_POLYFORM,1,8,
1266                         Polyform_12_8,0,0);
1267   Init_operation(OPERATION_POLYFORM,2,8,
1268                         Polyform_12_8,0,0);
1269   Init_operation(OPERATION_POLYFORM,0,8,
1270                         Polyform_0_8,0,FAST_MOUSE);
1271 
1272   Init_operation(OPERATION_FILLED_POLYFORM,1,0,
1273                         Filled_polyform_12_0,HIDE_CURSOR,FAST_MOUSE);
1274   Init_operation(OPERATION_FILLED_POLYFORM,2,0,
1275                         Filled_polyform_12_0,HIDE_CURSOR,FAST_MOUSE);
1276   Init_operation(OPERATION_FILLED_POLYFORM,1,8,
1277                         Filled_polyform_12_8,0,0);
1278   Init_operation(OPERATION_FILLED_POLYFORM,2,8,
1279                         Filled_polyform_12_8,0,0);
1280   Init_operation(OPERATION_FILLED_POLYFORM,0,8,
1281                         Filled_polyform_0_8,0,FAST_MOUSE);
1282 
1283   Init_operation(OPERATION_FILLED_CONTOUR,1,0,
1284                         Filled_polyform_12_0,HIDE_CURSOR,0);
1285   Init_operation(OPERATION_FILLED_CONTOUR,2,0,
1286                         Filled_polyform_12_0,HIDE_CURSOR,0);
1287   Init_operation(OPERATION_FILLED_CONTOUR,1,8,
1288                         Filled_polyform_12_8,0,0);
1289   Init_operation(OPERATION_FILLED_CONTOUR,2,8,
1290                         Filled_polyform_12_8,0,0);
1291   Init_operation(OPERATION_FILLED_CONTOUR,0,8,
1292                         Filled_contour_0_8,0,0);
1293 
1294   Init_operation(OPERATION_SCROLL,1,0,
1295                         Scroll_12_0,HIDE_CURSOR,FAST_MOUSE);
1296   Init_operation(OPERATION_SCROLL,2,0,
1297                         Scroll_12_0,HIDE_CURSOR,FAST_MOUSE);
1298   Init_operation(OPERATION_SCROLL,1,5,
1299                         Scroll_12_5,0,FAST_MOUSE);
1300   Init_operation(OPERATION_SCROLL,2,5,
1301                         Scroll_12_5,0,FAST_MOUSE);
1302   Init_operation(OPERATION_SCROLL,0,5,
1303                         Scroll_0_5,HIDE_CURSOR,FAST_MOUSE);
1304 
1305   Init_operation(OPERATION_GRAD_CIRCLE_CTR,1,0,Grad_circle_12_0,HIDE_CURSOR,FAST_MOUSE);
1306   Init_operation(OPERATION_GRAD_CIRCLE_CTR,2,0,Grad_circle_12_0,HIDE_CURSOR,FAST_MOUSE);
1307   Init_operation(OPERATION_GRAD_CIRCLE_CTR,1,6,Grad_circle_12_6,0,FAST_MOUSE);
1308   Init_operation(OPERATION_GRAD_CIRCLE_CTR,2,6,Grad_circle_12_6,0,FAST_MOUSE);
1309   Init_operation(OPERATION_GRAD_CIRCLE_CTR,0,6,Grad_circle_0_6,HIDE_CURSOR,FAST_MOUSE);
1310   Init_operation(OPERATION_GRAD_CIRCLE_CTR,1,8,Grad_circle_12_8,0,FAST_MOUSE);
1311   Init_operation(OPERATION_GRAD_CIRCLE_CTR,2,8,Grad_circle_12_8,0,FAST_MOUSE);
1312   Init_operation(OPERATION_GRAD_CIRCLE_CTR,0,8,Grad_circle_or_ellipse_0_8,0,FAST_MOUSE);
1313 
1314   Init_operation(OPERATION_GRAD_CIRCLE_CRN,1,0,Grad_ellipse_12_0,HIDE_CURSOR,FAST_MOUSE);
1315   Init_operation(OPERATION_GRAD_CIRCLE_CRN,2,0,Grad_ellipse_12_0,HIDE_CURSOR,FAST_MOUSE);
1316   Init_operation(OPERATION_GRAD_CIRCLE_CRN,1,6,Grad_ellipse_12_6,0,FAST_MOUSE);
1317   Init_operation(OPERATION_GRAD_CIRCLE_CRN,2,6,Grad_ellipse_12_6,0,FAST_MOUSE);
1318   Init_operation(OPERATION_GRAD_CIRCLE_CRN,0,6,Grad_ellipse_0_6,HIDE_CURSOR,FAST_MOUSE);
1319   Init_operation(OPERATION_GRAD_CIRCLE_CRN,1,8,Grad_ellipse_12_8,0,FAST_MOUSE);
1320   Init_operation(OPERATION_GRAD_CIRCLE_CRN,2,8,Grad_ellipse_12_8,0,FAST_MOUSE);
1321   Init_operation(OPERATION_GRAD_CIRCLE_CRN,0,8,Grad_circle_or_ellipse_0_8,0,FAST_MOUSE);
1322 
1323   Init_operation(OPERATION_GRAD_ELLIPSE_CTR,1,0,Grad_ellipse_12_0,HIDE_CURSOR,FAST_MOUSE);
1324   Init_operation(OPERATION_GRAD_ELLIPSE_CTR,2,0,Grad_ellipse_12_0,HIDE_CURSOR,FAST_MOUSE);
1325   Init_operation(OPERATION_GRAD_ELLIPSE_CTR,1,6,Grad_ellipse_12_6,0,FAST_MOUSE);
1326   Init_operation(OPERATION_GRAD_ELLIPSE_CTR,2,6,Grad_ellipse_12_6,0,FAST_MOUSE);
1327   Init_operation(OPERATION_GRAD_ELLIPSE_CTR,0,6,Grad_ellipse_0_6,HIDE_CURSOR,FAST_MOUSE);
1328   Init_operation(OPERATION_GRAD_ELLIPSE_CTR,1,8,Grad_ellipse_12_8,0,FAST_MOUSE);
1329   Init_operation(OPERATION_GRAD_ELLIPSE_CTR,2,8,Grad_ellipse_12_8,0,FAST_MOUSE);
1330   Init_operation(OPERATION_GRAD_ELLIPSE_CTR,0,8,Grad_circle_or_ellipse_0_8,0,FAST_MOUSE);
1331 
1332   Init_operation(OPERATION_GRAD_ELLIPSE_CRN,1,0,Grad_ellipse_12_0,HIDE_CURSOR,FAST_MOUSE);
1333   Init_operation(OPERATION_GRAD_ELLIPSE_CRN,2,0,Grad_ellipse_12_0,HIDE_CURSOR,FAST_MOUSE);
1334   Init_operation(OPERATION_GRAD_ELLIPSE_CRN,1,6,Grad_ellipse_12_6,0,FAST_MOUSE);
1335   Init_operation(OPERATION_GRAD_ELLIPSE_CRN,2,6,Grad_ellipse_12_6,0,FAST_MOUSE);
1336   Init_operation(OPERATION_GRAD_ELLIPSE_CRN,0,6,Grad_ellipse_0_6,HIDE_CURSOR,FAST_MOUSE);
1337   Init_operation(OPERATION_GRAD_ELLIPSE_CRN,1,8,Grad_ellipse_12_8,0,FAST_MOUSE);
1338   Init_operation(OPERATION_GRAD_ELLIPSE_CRN,2,8,Grad_ellipse_12_8,0,FAST_MOUSE);
1339   Init_operation(OPERATION_GRAD_ELLIPSE_CRN,0,8,Grad_circle_or_ellipse_0_8,0,FAST_MOUSE);
1340 
1341   Init_operation(OPERATION_GRAD_RECTANGLE,1,0,Grad_rectangle_12_0,0,FAST_MOUSE);
1342   Init_operation(OPERATION_GRAD_RECTANGLE,1,5,Grad_rectangle_12_5,0,FAST_MOUSE);
1343   Init_operation(OPERATION_GRAD_RECTANGLE,0,5,Grad_rectangle_0_5,HIDE_CURSOR,FAST_MOUSE);
1344   Init_operation(OPERATION_GRAD_RECTANGLE,0,7,Grad_rectangle_0_7,0,FAST_MOUSE);
1345   Init_operation(OPERATION_GRAD_RECTANGLE,1,7,Grad_rectangle_12_7,HIDE_CURSOR,FAST_MOUSE);
1346   Init_operation(OPERATION_GRAD_RECTANGLE,2,7,Grad_rectangle_12_7,HIDE_CURSOR,FAST_MOUSE);
1347   Init_operation(OPERATION_GRAD_RECTANGLE,1,9,Grad_rectangle_12_9,HIDE_CURSOR,FAST_MOUSE);
1348   Init_operation(OPERATION_GRAD_RECTANGLE,0,9,Grad_rectangle_0_9,0,FAST_MOUSE);
1349 
1350 
1351   Init_operation(OPERATION_CENTERED_LINES,1,0,
1352                         Centered_lines_12_0,HIDE_CURSOR,FAST_MOUSE);
1353   Init_operation(OPERATION_CENTERED_LINES,2,0,
1354                         Centered_lines_12_0,HIDE_CURSOR,FAST_MOUSE);
1355   Init_operation(OPERATION_CENTERED_LINES,1,3,
1356                         Centered_lines_12_3,0,FAST_MOUSE);
1357   Init_operation(OPERATION_CENTERED_LINES,2,3,
1358                         Centered_lines_12_3,0,FAST_MOUSE);
1359   Init_operation(OPERATION_CENTERED_LINES,0,3,
1360                         Centered_lines_0_3,HIDE_CURSOR,FAST_MOUSE);
1361   Init_operation(OPERATION_CENTERED_LINES,1,7,
1362                         Centered_lines_12_7,0,FAST_MOUSE);
1363   Init_operation(OPERATION_CENTERED_LINES,2,7,
1364                         Centered_lines_12_7,0,FAST_MOUSE);
1365   Init_operation(OPERATION_CENTERED_LINES,0,7,
1366                         Centered_lines_0_7,0,FAST_MOUSE);
1367   Init_operation(OPERATION_RMB_COLORPICK,0,1,
1368                         Rightclick_colorpick_0_1,0,FAST_MOUSE);
1369   Init_operation(OPERATION_PAN_VIEW,0,0,
1370                         Pan_view_0_0,0,FAST_MOUSE);
1371   Init_operation(OPERATION_PAN_VIEW,1,0,
1372                         Pan_view_12_0,0,FAST_MOUSE);
1373   Init_operation(OPERATION_PAN_VIEW,2,0,
1374                         Pan_view_12_0,0,FAST_MOUSE);
1375   Init_operation(OPERATION_PAN_VIEW,1,2,
1376                         Pan_view_12_2,0,FAST_MOUSE);
1377   Init_operation(OPERATION_PAN_VIEW,2,2,
1378                         Pan_view_12_2,0,FAST_MOUSE);
1379   Init_operation(OPERATION_PAN_VIEW,0,2,
1380                         Pan_view_0_2,0,FAST_MOUSE);
1381 
1382 }
1383 
1384 
1385 
1386 //-- Définition des modes vidéo: --------------------------------------------
1387 
1388   // Définition d'un mode:
1389 
Set_video_mode(short width,short height,byte mode,word fullscreen)1390 static void Set_video_mode(short  width,
1391                            short  height,
1392                            byte   mode,
1393                            word   fullscreen)
1394 {
1395   byte supported = 0;
1396 #if defined(USE_SDL2)
1397   SDL_DisplayMode dm;
1398 #endif
1399 
1400   if (Nb_video_modes >= MAX_VIDEO_MODES-1)
1401   {
1402     GFX2_Log(GFX2_ERROR, "Attempt to create too many videomodes. Maximum is: %d\n", MAX_VIDEO_MODES);
1403     return;
1404   }
1405   if (!fullscreen)
1406     supported = 128; // Prefere, non modifiable
1407 #if defined(USE_SDL)
1408   else if (SDL_VideoModeOK(width, height, 8, SDL_FULLSCREEN))
1409     supported = 1; // supported
1410 #elif defined(USE_SDL2)
1411   else if (SDL_GetDisplayMode(0, mode, &dm) == 0) {
1412     if (width == dm.w && height == dm.h)
1413       supported = 1;
1414   }
1415 #endif
1416 
1417   if (!supported) // Not supported : skip this mode
1418     return;
1419 
1420   Video_mode[Nb_video_modes].Width      = width;
1421   Video_mode[Nb_video_modes].Height     = height;
1422   Video_mode[Nb_video_modes].Mode       = mode;
1423   Video_mode[Nb_video_modes].Fullscreen = fullscreen;
1424   Video_mode[Nb_video_modes].State      = supported;
1425   Nb_video_modes ++;
1426 }
1427 
1428 // Utilisé pour trier les modes retournés par SDL
Compare_video_modes(const void * p1,const void * p2)1429 int Compare_video_modes(const void *p1, const void *p2)
1430 {
1431   const T_Video_mode *mode1 = (const T_Video_mode *)p1;
1432   const T_Video_mode *mode2 = (const T_Video_mode *)p2;
1433 
1434   // Tris par largeur
1435   if(mode1->Width - mode2->Width)
1436     return mode1->Width - mode2->Width;
1437 
1438   // Tri par hauteur
1439   return mode1->Height - mode2->Height;
1440 }
1441 
1442 
1443 // Initializes the list of available video modes
Set_all_video_modes(void)1444 void Set_all_video_modes(void)
1445 {
1446 #if defined(USE_SDL)
1447   SDL_Rect** Modes;
1448 #endif
1449   Nb_video_modes=0;
1450 
1451   // The first mode will have index number 0.
1452   // It will be the default mode if an unsupported one
1453   // is requested in gfx2.ini
1454   #if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__) || defined(GCWZERO)
1455   // Native GP2X resolution
1456   Set_video_mode( 320,240,0, 1);
1457   #else
1458   // Window mode, with default size of 640x480
1459   Set_video_mode( 640,480,0, 0);
1460   #endif
1461 
1462   Set_video_mode( 320,200,0, 1);
1463   Set_video_mode( 320,224,0, 1);
1464   #if !defined(__GP2X__) && !defined(__WIZ__) && !defined(__CAANOO__) && !defined(GCWZERO)
1465   // For the GP2X, this one is already declared above.
1466   Set_video_mode( 320,240,0, 1);
1467   #endif
1468   Set_video_mode( 320,256,0, 1);
1469   Set_video_mode( 320,270,0, 1);
1470   Set_video_mode( 320,282,0, 1);
1471   Set_video_mode( 320,300,0, 1);
1472   Set_video_mode( 320,360,0, 1);
1473   Set_video_mode( 320,400,0, 1);
1474   Set_video_mode( 320,448,0, 1);
1475   Set_video_mode( 320,480,0, 1);
1476   Set_video_mode( 320,512,0, 1);
1477   Set_video_mode( 320,540,0, 1);
1478   Set_video_mode( 320,564,0, 1);
1479   Set_video_mode( 320,600,0, 1);
1480   Set_video_mode( 360,200,0, 1);
1481   Set_video_mode( 360,224,0, 1);
1482   Set_video_mode( 360,240,0, 1);
1483   Set_video_mode( 360,256,0, 1);
1484   Set_video_mode( 360,270,0, 1);
1485   Set_video_mode( 360,282,0, 1);
1486   Set_video_mode( 360,300,0, 1);
1487   Set_video_mode( 360,360,0, 1);
1488   Set_video_mode( 360,400,0, 1);
1489   Set_video_mode( 360,448,0, 1);
1490   Set_video_mode( 360,480,0, 1);
1491   Set_video_mode( 360,512,0, 1);
1492   Set_video_mode( 360,540,0, 1);
1493   Set_video_mode( 360,564,0, 1);
1494   Set_video_mode( 360,600,0, 1);
1495   Set_video_mode( 400,200,0, 1);
1496   Set_video_mode( 400,224,0, 1);
1497   Set_video_mode( 400,240,0, 1);
1498   Set_video_mode( 400,256,0, 1);
1499   Set_video_mode( 400,270,0, 1);
1500   Set_video_mode( 400,282,0, 1);
1501   Set_video_mode( 400,300,0, 1);
1502   Set_video_mode( 400,360,0, 1);
1503   Set_video_mode( 400,400,0, 1);
1504   Set_video_mode( 400,448,0, 1);
1505   Set_video_mode( 400,480,0, 1);
1506   Set_video_mode( 400,512,0, 1);
1507   Set_video_mode( 400,540,0, 1);
1508   Set_video_mode( 400,564,0, 1);
1509   Set_video_mode( 400,600,0, 1);
1510   Set_video_mode( 640,224,0, 1);
1511   Set_video_mode( 640,240,0, 1);
1512   Set_video_mode( 640,256,0, 1);
1513   Set_video_mode( 640,270,0, 1);
1514   Set_video_mode( 640,300,0, 1);
1515   Set_video_mode( 640,350,0, 1);
1516   Set_video_mode( 640,400,0, 1);
1517   Set_video_mode( 640,448,0, 1);
1518   Set_video_mode( 640,480,0, 1);
1519   Set_video_mode( 640,512,0, 1);
1520   Set_video_mode( 640,540,0, 1);
1521   Set_video_mode( 640,564,0, 1);
1522   Set_video_mode( 640,600,0, 1);
1523   Set_video_mode( 800,600,0, 1);
1524   Set_video_mode(1024,768,0, 1);
1525 
1526 #if defined(USE_SDL)
1527   Modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
1528   if ((Modes != (SDL_Rect**)0) && (Modes!=(SDL_Rect**)-1))
1529   {
1530     int index;
1531     for (index=0; Modes[index]; index++)
1532     {
1533       int index2;
1534 #if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__) || defined(GCWZERO)
1535       // On the GP2X the first mode is not windowed, so include it in the search.
1536       index2=0;
1537 #else
1538       index2=1;
1539 #endif
1540       for (/**/; index2 < Nb_video_modes; index2++)
1541         if (Modes[index]->w == Video_mode[index2].Width &&
1542             Modes[index]->h == Video_mode[index2].Height)
1543         {
1544           // Was already in the hard-coded list: ok, don't add.
1545           break;
1546         }
1547       if (index2 >= Nb_video_modes && Modes[index]->w>=320 && Modes[index]->h>=200)
1548       {
1549         // New mode to add to the list
1550         Set_video_mode(Modes[index]->w,Modes[index]->h,0, 1);
1551       }
1552     }
1553     // Sort the modes : those found by SDL were listed at the end.
1554     // Note that we voluntarily omit the first entry: the default mode.
1555     qsort(&Video_mode[1], Nb_video_modes - 1, sizeof(T_Video_mode), Compare_video_modes);
1556   }
1557 #elif defined(USE_SDL2)
1558   {
1559     SDL_DisplayMode dm;
1560     int num_modes, mode;
1561     int display = 0;
1562 
1563 
1564     num_modes = SDL_GetNumDisplayModes(display);
1565     for (mode = num_modes; mode >= 0; mode--) // reverse order. from small resolution to big resolution
1566     {
1567       if (SDL_GetDisplayMode(display, mode, &dm) == 0)
1568         Set_video_mode(dm.w, dm.h, mode, 1);
1569     }
1570 
1571     if (SDL_GetDesktopDisplayMode(display, &dm) == 0)
1572     {
1573       // Set the native desktop video mode
1574       Set_video_mode(dm.w, dm.h, num_modes + 1, 1);
1575     }
1576   }
1577 #elif defined(WIN32)
1578   {
1579     int width = 0;
1580     int height = 0;
1581     if (GFX2_GetScreenSize(&width, &height))
1582     {
1583       Video_mode[Nb_video_modes].Width      = width;
1584       Video_mode[Nb_video_modes].Height     = height;
1585       Video_mode[Nb_video_modes].Mode       = 0;
1586       Video_mode[Nb_video_modes].Fullscreen = 1;
1587       Video_mode[Nb_video_modes].State      = 1;
1588       Nb_video_modes ++;
1589     }
1590   }
1591 #endif
1592 }
1593 
1594 //---------------------------------------------------------------------------
1595 
Load_CFG(int reload_all)1596 int Load_CFG(int reload_all)
1597 {
1598   FILE*  Handle;
1599   char * filename;
1600   long file_size;
1601   int  index,index2;
1602   T_Config_header       cfg_header;
1603   T_Config_chunk        Chunk;
1604   T_Config_shortcut_info cfg_shortcut_info;
1605   T_Config_video_mode   cfg_video_mode;
1606   int key_conversion = 0;
1607 
1608   filename = Filepath_append_to_dir(Config_directory, CONFIG_FILENAME);
1609 
1610   GFX2_Log(GFX2_DEBUG, "Load_CFG() trying to load %s\n", filename);
1611 
1612   Handle = fopen(filename, "rb");
1613   if (Handle == NULL)
1614   {
1615     free(filename);
1616     return ERROR_CFG_MISSING;
1617   }
1618   free(filename);
1619 
1620   file_size = File_length_file(Handle);
1621 
1622   if ( (file_size<7)
1623     || (!Read_bytes(Handle, &cfg_header.Signature, 3))
1624     || memcmp(cfg_header.Signature,"CFG",3)
1625     || (!Read_byte(Handle, &cfg_header.Version1))
1626     || (!Read_byte(Handle, &cfg_header.Version2))
1627     || (!Read_byte(Handle, &cfg_header.Beta1))
1628     || (!Read_byte(Handle, &cfg_header.Beta2)) )
1629       goto Erreur_lecture_config;
1630 
1631   // Version DOS de Robinson et X-Man
1632   if ( (cfg_header.Version1== 2)
1633     && (cfg_header.Version2== 0)
1634     && (cfg_header.Beta1== 96))
1635   {
1636     // Les touches (scancodes) sont à convertir)
1637     key_conversion = 1;
1638   }
1639   // Version SDL jusqu'a 98%
1640   else if ( (cfg_header.Version1== 2)
1641     && (cfg_header.Version2== 0)
1642     && (cfg_header.Beta1== 97))
1643   {
1644     // Les touches 00FF (pas de touche) sont a comprendre comme 0x0000
1645     key_conversion = 2;
1646   }
1647   // Version SDL
1648   else if ( (cfg_header.Version1!=VERSION1)
1649     || (cfg_header.Version2!=VERSION2)
1650     || (cfg_header.Beta1!=BETA1)
1651     || (cfg_header.Beta2!=BETA2) )
1652     goto Erreur_config_ancienne;
1653 
1654   // - Lecture des infos contenues dans le fichier de config -
1655   while (Read_byte(Handle, &Chunk.Number))
1656   {
1657     Read_word_le(Handle, &Chunk.Size);
1658     switch (Chunk.Number)
1659     {
1660       case CHUNK_KEYS: // Touches
1661         if (reload_all)
1662         {
1663           for (index=0; index<(long)(Chunk.Size/6); index++)
1664           {
1665             if (!Read_word_le(Handle, &cfg_shortcut_info.Number) ||
1666                 !Read_word_le(Handle, &cfg_shortcut_info.Key) ||
1667                 !Read_word_le(Handle, &cfg_shortcut_info.Key2) )
1668               goto Erreur_lecture_config;
1669             else
1670             {
1671               if (key_conversion==1)
1672               {
1673                 cfg_shortcut_info.Key = Key_for_scancode(cfg_shortcut_info.Key);
1674               }
1675               else if (key_conversion==2)
1676               {
1677                 if (cfg_shortcut_info.Key == 0x00FF)
1678                   cfg_shortcut_info.Key = 0x0000;
1679                 if (cfg_shortcut_info.Key2 == 0x00FF)
1680                   cfg_shortcut_info.Key2 = 0x0000;
1681               }
1682 
1683               for (index2=0;
1684                  ((index2<NB_SHORTCUTS) && (ConfigKey[index2].Number!=cfg_shortcut_info.Number));
1685                  index2++);
1686               if (index2<NB_SHORTCUTS)
1687               {
1688                 switch(Ordering[index2]>>8)
1689                 {
1690                   case 0 :
1691                     Config_Key[Ordering[index2]&0xFF][0]=cfg_shortcut_info.Key;
1692                     Config_Key[Ordering[index2]&0xFF][1]=cfg_shortcut_info.Key2;
1693                     break;
1694                   case 1 :
1695                     Buttons_Pool[Ordering[index2]&0xFF].Left_shortcut[0] = cfg_shortcut_info.Key;
1696                     Buttons_Pool[Ordering[index2]&0xFF].Left_shortcut[1] = cfg_shortcut_info.Key2;
1697                     break;
1698                   case 2 :
1699                     Buttons_Pool[Ordering[index2]&0xFF].Right_shortcut[0] = cfg_shortcut_info.Key;
1700                     Buttons_Pool[Ordering[index2]&0xFF].Right_shortcut[1] = cfg_shortcut_info.Key2;
1701                     break;
1702                 }
1703               }
1704               else
1705                 goto Erreur_lecture_config;
1706             }
1707           }
1708         }
1709         else
1710         {
1711           if (fseek(Handle,Chunk.Size,SEEK_CUR)==-1)
1712             goto Erreur_lecture_config;
1713         }
1714         break;
1715       case CHUNK_VIDEO_MODES: // Modes vidéo
1716         for (index=0; index<(long)(Chunk.Size/5); index++)
1717         {
1718           if (!Read_byte(Handle, &cfg_video_mode.State) ||
1719               !Read_word_le(Handle, &cfg_video_mode.Width) ||
1720               !Read_word_le(Handle, &cfg_video_mode.Height) )
1721             goto Erreur_lecture_config;
1722 
1723 #if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__)
1724           index2=0;
1725 #else
1726           index2=1;
1727 #endif
1728           for (/**/; index2<Nb_video_modes; index2++)
1729           {
1730             if (Video_mode[index2].Width==cfg_video_mode.Width &&
1731                 Video_mode[index2].Height==cfg_video_mode.Height)
1732             {
1733               // On ne prend le paramètre utilisateur que si la résolution
1734               // est effectivement supportée par SDL
1735               // Seules les deux petits bits sont récupérés, car les anciens fichiers
1736               // de configuration (DOS 96.5%) utilisaient d'autres bits.
1737               if (! (Video_mode[index2].State & 128))
1738                 Video_mode[index2].State=cfg_video_mode.State&3;
1739               break;
1740             }
1741           }
1742         }
1743         break;
1744       case CHUNK_SHADE: // Shade
1745         if (reload_all)
1746         {
1747           if (! Read_byte(Handle, &Shade_current) )
1748             goto Erreur_lecture_config;
1749 
1750           for (index=0; index<8; index++)
1751           {
1752             for (index2=0; index2<512; index2++)
1753             {
1754               if (! Read_word_le(Handle, &Shade_list[index].List[index2]))
1755                 goto Erreur_lecture_config;
1756             }
1757             if (! Read_byte(Handle, &Shade_list[index].Step) ||
1758               ! Read_byte(Handle, &Shade_list[index].Mode) )
1759             goto Erreur_lecture_config;
1760           }
1761           Shade_list_to_lookup_tables(Shade_list[Shade_current].List,
1762             Shade_list[Shade_current].Step,
1763             Shade_list[Shade_current].Mode,
1764             Shade_table_left,Shade_table_right);
1765         }
1766         else
1767         {
1768           if (fseek(Handle,Chunk.Size,SEEK_CUR)==-1)
1769             goto Erreur_lecture_config;
1770         }
1771         break;
1772       case CHUNK_MASK: // Masque
1773         if (reload_all)
1774         {
1775           if (!Read_bytes(Handle, Mask_table, 256))
1776             goto Erreur_lecture_config;
1777         }
1778         else
1779         {
1780           if (fseek(Handle,Chunk.Size,SEEK_CUR)==-1)
1781             goto Erreur_lecture_config;
1782         }
1783         break;
1784       case CHUNK_STENCIL: // Stencil
1785         if (reload_all)
1786         {
1787           if (!Read_bytes(Handle, Stencil, 256))
1788             goto Erreur_lecture_config;
1789         }
1790         else
1791         {
1792           if (fseek(Handle,Chunk.Size,SEEK_CUR)==-1)
1793             goto Erreur_lecture_config;
1794         }
1795         break;
1796       case CHUNK_GRADIENTS: // Infos sur les dégradés
1797         // The gradients chunk is deprecated since the data
1798         // is now loaded/saved in GIF and IFF formats.
1799         // The chunk will be completely ignored.
1800         /*if (reload_all)
1801         {
1802           if (! Read_byte(Handle, &Current_gradient))
1803             goto Erreur_lecture_config;
1804           for(index=0;index<16;index++)
1805           {
1806             if (!Read_byte(Handle, &Gradient_array[index].Start) ||
1807                 !Read_byte(Handle, &Gradient_array[index].End) ||
1808                 !Read_dword_le(Handle, &Gradient_array[index].Inverse) ||
1809                 !Read_dword_le(Handle, &Gradient_array[index].Mix) ||
1810                 !Read_dword_le(Handle, &Gradient_array[index].Technique) )
1811             goto Erreur_lecture_config;
1812           }
1813           Load_gradient_data(Current_gradient);
1814         }
1815         else*/
1816         {
1817           if (fseek(Handle,Chunk.Size,SEEK_CUR)==-1)
1818             goto Erreur_lecture_config;
1819         }
1820         break;
1821       case CHUNK_SMOOTH: // Matrice du smooth
1822         if (reload_all)
1823         {
1824           for (index=0; index<3; index++)
1825             for (index2=0; index2<3; index2++)
1826               if (!Read_byte(Handle, &(Smooth_matrix[index][index2])))
1827                 goto Erreur_lecture_config;
1828         }
1829         else
1830         {
1831           if (fseek(Handle,Chunk.Size,SEEK_CUR)==-1)
1832             goto Erreur_lecture_config;
1833         }
1834         break;
1835       case CHUNK_EXCLUDE_COLORS: // Exclude_color
1836         if (reload_all)
1837         {
1838           if (!Read_bytes(Handle, Exclude_color, 256))
1839             goto Erreur_lecture_config;
1840         }
1841         else
1842         {
1843           if (fseek(Handle,Chunk.Size,SEEK_CUR)==-1)
1844             goto Erreur_lecture_config;
1845         }
1846         break;
1847       case CHUNK_QUICK_SHADE: // Quick-shade
1848         if (reload_all)
1849         {
1850           if (!Read_byte(Handle, &Quick_shade_step))
1851             goto Erreur_lecture_config;
1852           if (!Read_byte(Handle, &Quick_shade_loop))
1853             goto Erreur_lecture_config;
1854         }
1855         else
1856         {
1857           if (fseek(Handle,Chunk.Size,SEEK_CUR)==-1)
1858             goto Erreur_lecture_config;
1859         }
1860         break;
1861         case CHUNK_GRID: // Grille
1862         if (reload_all)
1863         {
1864           if (!Read_word_le(Handle, &Snap_width))
1865             goto Erreur_lecture_config;
1866           if (!Read_word_le(Handle, &Snap_height))
1867             goto Erreur_lecture_config;
1868           if (!Read_word_le(Handle, &Snap_offset_X))
1869             goto Erreur_lecture_config;
1870           if (!Read_word_le(Handle, &Snap_offset_Y))
1871             goto Erreur_lecture_config;
1872         }
1873         else
1874         {
1875           if (fseek(Handle,Chunk.Size,SEEK_CUR)==-1)
1876             goto Erreur_lecture_config;
1877         }
1878         break;
1879 
1880       case CHUNK_BRUSH:
1881         if (reload_all)
1882         {
1883           int index;
1884           for (index=0; index<NB_PAINTBRUSH_SPRITES; index++)
1885           {
1886             int i;
1887             byte current_byte=0;
1888             word width,height;
1889 
1890             if (!Read_byte(Handle, &Paintbrush[index].Shape))
1891               goto Erreur_lecture_config;
1892 
1893             if (!Read_word_le(Handle, &width))
1894               goto Erreur_lecture_config;
1895             if (!Read_word_le(Handle, &height))
1896               goto Erreur_lecture_config;
1897 
1898             Paintbrush[index].Width=width;
1899             Paintbrush[index].Height=height;
1900 
1901             if (!Read_word_le(Handle, &Paintbrush[index].Offset_X))
1902               goto Erreur_lecture_config;
1903             if (!Read_word_le(Handle, &Paintbrush[index].Offset_Y))
1904               goto Erreur_lecture_config;
1905 
1906             // Decode binary
1907             for (i=0;i<width*height;i++)
1908             {
1909               if ((i&7) == 0)
1910               {
1911                 // Read one byte
1912                 if (!Read_byte(Handle, &current_byte))
1913                   goto Erreur_lecture_config;
1914               }
1915               Paintbrush[index].Sprite[i/width][i%width] =
1916                 ((current_byte & (0x80 >> (i&7))) != 0);
1917             }
1918           }
1919         }
1920         else
1921         {
1922           if (fseek(Handle,Chunk.Size,SEEK_CUR)==-1)
1923             goto Erreur_lecture_config;
1924         }
1925         break;
1926 
1927 
1928       case CHUNK_SCRIPTS:
1929         if (reload_all)
1930         {
1931           int current_size=0;
1932           int current_script=0;
1933 
1934           while(current_size<Chunk.Size)
1935           {
1936             byte size;
1937 
1938             // Free (old) string
1939             free(Bound_script[current_script]);
1940             Bound_script[current_script]=NULL;
1941 
1942             if (!Read_byte(Handle, &size))
1943               goto Erreur_lecture_config;
1944 
1945             if (size!=0)
1946             {
1947               // Alloc string
1948               Bound_script[current_script] = GFX2_malloc(size+1);
1949               if (Bound_script[current_script] == NULL)
1950                 return ERROR_MEMORY;
1951 
1952               // Init and load string
1953               memset(Bound_script[current_script], 0, size+1);
1954               if (!Read_bytes(Handle, Bound_script[current_script], size))
1955                 goto Erreur_lecture_config;
1956             }
1957             current_size+=size+1;
1958             current_script++;
1959 
1960             // Do not load more strings than hard-coded limit
1961             if (current_script>=10)
1962               break;
1963           }
1964 
1965 
1966         }
1967         break;
1968 
1969       default: // Chunk inconnu
1970         goto Erreur_lecture_config;
1971     }
1972   }
1973 
1974   if (fclose(Handle))
1975     return ERROR_CFG_CORRUPTED;
1976 
1977   return 0;
1978 
1979 Erreur_lecture_config:
1980   fclose(Handle);
1981   return ERROR_CFG_CORRUPTED;
1982 Erreur_config_ancienne:
1983   fclose(Handle);
1984   return ERROR_CFG_OLD;
1985 }
1986 
1987 
Save_CFG(void)1988 int Save_CFG(void)
1989 {
1990   FILE*  Handle;
1991   int  index;
1992   int  index2;
1993   int modes_to_save;
1994   char * filename;
1995   T_Config_header cfg_header;
1996   T_Config_chunk Chunk;
1997   T_Config_shortcut_info cfg_shortcut_info={0,0,0};
1998   T_Config_video_mode   cfg_video_mode={0,0,0};
1999 
2000   filename = Filepath_append_to_dir(Config_directory, CONFIG_FILENAME);
2001 
2002   Handle = fopen(filename, "wb");
2003   if (Handle == NULL)
2004   {
2005     GFX2_Log(GFX2_ERROR, "Failed to open %s for Writing\n", filename);
2006     free(filename);
2007     return ERROR_SAVING_CFG;
2008   }
2009   free(filename);
2010 
2011   // Ecriture du header
2012   memcpy(cfg_header.Signature,"CFG",3);
2013   cfg_header.Version1=VERSION1;
2014   cfg_header.Version2=VERSION2;
2015   cfg_header.Beta1   =BETA1;
2016   cfg_header.Beta2   =BETA2;
2017   if (!Write_bytes(Handle, &cfg_header.Signature,3) ||
2018       !Write_byte(Handle, cfg_header.Version1) ||
2019       !Write_byte(Handle, cfg_header.Version2) ||
2020       !Write_byte(Handle, cfg_header.Beta1) ||
2021       !Write_byte(Handle, cfg_header.Beta2) )
2022     goto Erreur_sauvegarde_config;
2023 
2024   // Enregistrement des touches
2025   Chunk.Number=CHUNK_KEYS;
2026   Chunk.Size=NB_SHORTCUTS*6;
2027 
2028   if (!Write_byte(Handle, Chunk.Number) ||
2029       !Write_word_le(Handle, Chunk.Size) )
2030     goto Erreur_sauvegarde_config;
2031   for (index=0; index<NB_SHORTCUTS; index++)
2032   {
2033     cfg_shortcut_info.Number = ConfigKey[index].Number;
2034     switch(Ordering[index]>>8)
2035     {
2036       case 0 :
2037         cfg_shortcut_info.Key =Config_Key[Ordering[index]&0xFF][0];
2038         cfg_shortcut_info.Key2=Config_Key[Ordering[index]&0xFF][1];
2039         break;
2040       case 1 :
2041         cfg_shortcut_info.Key =Buttons_Pool[Ordering[index]&0xFF].Left_shortcut[0];
2042         cfg_shortcut_info.Key2=Buttons_Pool[Ordering[index]&0xFF].Left_shortcut[1];
2043         break;
2044       case 2 :
2045         cfg_shortcut_info.Key =Buttons_Pool[Ordering[index]&0xFF].Right_shortcut[0];
2046         cfg_shortcut_info.Key2=Buttons_Pool[Ordering[index]&0xFF].Right_shortcut[1];
2047         break;
2048     }
2049     if (!Write_word_le(Handle, cfg_shortcut_info.Number) ||
2050         !Write_word_le(Handle, cfg_shortcut_info.Key) ||
2051         !Write_word_le(Handle, cfg_shortcut_info.Key2) )
2052       goto Erreur_sauvegarde_config;
2053   }
2054 
2055   // D'abord compter les modes pour lesquels l'utilisateur a mis une préférence
2056   modes_to_save=0;
2057 #if defined(__GP2X__) || defined (__WIZ__) || defined (__CAANOO__)
2058   index = 0;
2059 #else
2060   index = 1;
2061 #endif
2062   for (/**/; index<Nb_video_modes; index++)
2063     if (Video_mode[index].State==0 || Video_mode[index].State==2 || Video_mode[index].State==3)
2064       modes_to_save++;
2065 
2066   // Sauvegarde de l'état de chaque mode vidéo
2067   Chunk.Number=CHUNK_VIDEO_MODES;
2068   Chunk.Size=modes_to_save * 5;
2069 
2070   if (!Write_byte(Handle, Chunk.Number) ||
2071       !Write_word_le(Handle, Chunk.Size) )
2072     goto Erreur_sauvegarde_config;
2073 #if defined(__GP2X__) || defined (__WIZ__) || defined (__CAANOO__)
2074   index = 0;
2075 #else
2076   index = 1;
2077 #endif
2078   for (/**/; index<Nb_video_modes; index++)
2079     if (Video_mode[index].State==0 || Video_mode[index].State==2 || Video_mode[index].State==3)
2080     {
2081       cfg_video_mode.State   =Video_mode[index].State;
2082       cfg_video_mode.Width=Video_mode[index].Width;
2083       cfg_video_mode.Height=Video_mode[index].Height;
2084 
2085       if (!Write_byte(Handle, cfg_video_mode.State) ||
2086         !Write_word_le(Handle, cfg_video_mode.Width) ||
2087         !Write_word_le(Handle, cfg_video_mode.Height) )
2088         goto Erreur_sauvegarde_config;
2089     }
2090 
2091   // Ecriture des données du Shade (précédées du shade en cours)
2092   Chunk.Number=CHUNK_SHADE;
2093   Chunk.Size=8209;
2094   if (!Write_byte(Handle, Chunk.Number) ||
2095       !Write_word_le(Handle, Chunk.Size) )
2096     goto Erreur_sauvegarde_config;
2097   if (!Write_byte(Handle, Shade_current))
2098     goto Erreur_sauvegarde_config;
2099   for (index=0; index<8; index++)
2100   {
2101     for (index2=0; index2<512; index2++)
2102     {
2103       if (! Write_word_le(Handle, Shade_list[index].List[index2]))
2104         goto Erreur_sauvegarde_config;
2105     }
2106     if (! Write_byte(Handle, Shade_list[index].Step) ||
2107       ! Write_byte(Handle, Shade_list[index].Mode) )
2108     goto Erreur_sauvegarde_config;
2109   }
2110 
2111   // Sauvegarde des informations du Masque
2112   Chunk.Number=CHUNK_MASK;
2113   Chunk.Size=256;
2114   if (!Write_byte(Handle, Chunk.Number) ||
2115       !Write_word_le(Handle, Chunk.Size) )
2116     goto Erreur_sauvegarde_config;
2117   if (!Write_bytes(Handle, Mask_table,256))
2118     goto Erreur_sauvegarde_config;
2119 
2120   // Sauvegarde des informations du Stencil
2121   Chunk.Number=CHUNK_STENCIL;
2122   Chunk.Size=256;
2123   if (!Write_byte(Handle, Chunk.Number) ||
2124       !Write_word_le(Handle, Chunk.Size) )
2125     goto Erreur_sauvegarde_config;
2126   if (!Write_bytes(Handle, Stencil,256))
2127     goto Erreur_sauvegarde_config;
2128 
2129   // Sauvegarde des informations des dégradés
2130   // The gradients chunk is deprecated since the data
2131   // is now loaded/saved in GIF and IFF formats.
2132   /*
2133   Chunk.Number=CHUNK_GRADIENTS;
2134   Chunk.Size=14*16+1;
2135   if (!Write_byte(Handle, Chunk.Number) ||
2136       !Write_word_le(Handle, Chunk.Size) )
2137     goto Erreur_sauvegarde_config;
2138   if (!Write_byte(Handle, Current_gradient))
2139     goto Erreur_sauvegarde_config;
2140   for(index=0;index<16;index++)
2141   {
2142     if (!Write_byte(Handle,Gradient_array[index].Start) ||
2143         !Write_byte(Handle,Gradient_array[index].End) ||
2144         !Write_dword_le(Handle, Gradient_array[index].Inverse) ||
2145         !Write_dword_le(Handle, Gradient_array[index].Mix) ||
2146         !Write_dword_le(Handle, Gradient_array[index].Technique) )
2147         goto Erreur_sauvegarde_config;
2148   }
2149   */
2150 
2151   // Sauvegarde de la matrice du Smooth
2152   Chunk.Number=CHUNK_SMOOTH;
2153   Chunk.Size=9;
2154   if (!Write_byte(Handle, Chunk.Number) ||
2155       !Write_word_le(Handle, Chunk.Size) )
2156     goto Erreur_sauvegarde_config;
2157   for (index=0; index<3; index++)
2158     for (index2=0; index2<3; index2++)
2159       if (!Write_byte(Handle, Smooth_matrix[index][index2]))
2160         goto Erreur_sauvegarde_config;
2161 
2162   // Sauvegarde des couleurs à exclure
2163   Chunk.Number=CHUNK_EXCLUDE_COLORS;
2164   Chunk.Size=256;
2165   if (!Write_byte(Handle, Chunk.Number) ||
2166       !Write_word_le(Handle, Chunk.Size) )
2167     goto Erreur_sauvegarde_config;
2168  if (!Write_bytes(Handle, Exclude_color, 256))
2169     goto Erreur_sauvegarde_config;
2170 
2171   // Sauvegarde des informations du Quick-shade
2172   Chunk.Number=CHUNK_QUICK_SHADE;
2173   Chunk.Size=2;
2174   if (!Write_byte(Handle, Chunk.Number) ||
2175       !Write_word_le(Handle, Chunk.Size) )
2176     goto Erreur_sauvegarde_config;
2177   if (!Write_byte(Handle, Quick_shade_step))
2178     goto Erreur_sauvegarde_config;
2179   if (!Write_byte(Handle, Quick_shade_loop))
2180     goto Erreur_sauvegarde_config;
2181 
2182   // Sauvegarde des informations de la grille
2183   Chunk.Number=CHUNK_GRID;
2184   Chunk.Size=8;
2185   if (!Write_byte(Handle, Chunk.Number) ||
2186       !Write_word_le(Handle, Chunk.Size) )
2187     goto Erreur_sauvegarde_config;
2188   if (!Write_word_le(Handle, Snap_width))
2189     goto Erreur_sauvegarde_config;
2190   if (!Write_word_le(Handle, Snap_height))
2191     goto Erreur_sauvegarde_config;
2192   if (!Write_word_le(Handle, Snap_offset_X))
2193     goto Erreur_sauvegarde_config;
2194   if (!Write_word_le(Handle, Snap_offset_Y))
2195     goto Erreur_sauvegarde_config;
2196 
2197   // Save brush data
2198   {
2199     long total_size=0;
2200     int index;
2201     // Compute size: monochrome paintbrushes
2202     for (index=0; index<NB_PAINTBRUSH_SPRITES; index++)
2203     {
2204       total_size+=9+(Paintbrush[index].Width*Paintbrush[index].Height+7)/8;
2205     }
2206     /*
2207     // Compute size: brush container
2208     for (index=0; index<BRUSH_CONTAINER_COLUMNS*BRUSH_CONTAINER_ROWS; index++)
2209     {
2210 
2211     }
2212     */
2213     Chunk.Number=CHUNK_BRUSH;
2214     Chunk.Size=total_size;
2215     if (!Write_byte(Handle, Chunk.Number) ||
2216         !Write_word_le(Handle, Chunk.Size) )
2217       goto Erreur_sauvegarde_config;
2218     for (index=0; index<NB_PAINTBRUSH_SPRITES; index++)
2219     {
2220       int i;
2221       byte current_byte=0;
2222       word width,height;
2223 
2224       width=Paintbrush[index].Width;
2225       height=Paintbrush[index].Height;
2226 
2227 
2228       if (!Write_byte(Handle, Paintbrush[index].Shape))
2229         goto Erreur_sauvegarde_config;
2230       if (!Write_word_le(Handle, width))
2231         goto Erreur_sauvegarde_config;
2232       if (!Write_word_le(Handle, height))
2233         goto Erreur_sauvegarde_config;
2234       if (!Write_word_le(Handle, Paintbrush[index].Offset_X))
2235         goto Erreur_sauvegarde_config;
2236       if (!Write_word_le(Handle, Paintbrush[index].Offset_Y))
2237         goto Erreur_sauvegarde_config;
2238       // Encode in binary
2239       for (i=0;i<width*height;i++)
2240       {
2241         if (Paintbrush[index].Sprite[i/width][i%width])
2242           current_byte |= 0x80 >> (i&7);
2243         if ((i&7) == 7)
2244         {
2245           // Write one byte
2246           if (!Write_byte(Handle, current_byte))
2247             goto Erreur_sauvegarde_config;
2248           current_byte=0;
2249         }
2250       }
2251       // Remainder
2252       if ((i&7) != 0)
2253       {
2254         // Write one byte
2255         if (!Write_byte(Handle, current_byte))
2256           goto Erreur_sauvegarde_config;
2257       }
2258     }
2259   }
2260 
2261   // Save script shortcuts
2262   {
2263     int i;
2264     Chunk.Number=CHUNK_SCRIPTS;
2265     // Compute size : Data stored as 10 pascal strings
2266     Chunk.Size=0;
2267     for (i=0; i<10; i++)
2268     {
2269       Chunk.Size += 1;
2270       if (Bound_script[i] != NULL)
2271       {
2272         size_t len = strlen(Bound_script[i]);
2273         if (len < 256)
2274           Chunk.Size += (word)len;
2275       }
2276     }
2277     // Header
2278     if (!Write_byte(Handle, Chunk.Number) ||
2279         !Write_word_le(Handle, Chunk.Size) )
2280       goto Erreur_sauvegarde_config;
2281 
2282     // Strings
2283     for (i=0; i<10; i++)
2284     {
2285       byte size=0;
2286       if (Bound_script[i] != NULL)
2287       {
2288         size_t len = strlen(Bound_script[i]);
2289         if (len < 256)
2290           size = (byte)len;
2291         else
2292           GFX2_Log(GFX2_WARNING, "Cannot save script path (%lu > 255 characters)\n", (unsigned long)len);
2293       }
2294 
2295       if (!Write_byte(Handle, size))
2296         goto Erreur_sauvegarde_config;
2297 
2298       if (size)
2299         if (!Write_bytes(Handle, Bound_script[i], size))
2300           goto Erreur_sauvegarde_config;
2301     }
2302   }
2303 
2304   if (fclose(Handle))
2305     return ERROR_SAVING_CFG;
2306 
2307   return 0;
2308 
2309 Erreur_sauvegarde_config:
2310   fclose(Handle);
2311   return ERROR_SAVING_CFG;
2312 }
2313 
2314 // (Ré)assigne toutes les valeurs de configuration par défaut
Set_config_defaults(void)2315 void Set_config_defaults(void)
2316 {
2317   int index, index2;
2318 
2319   // Keyboard shortcuts
2320   for (index=0; index<NB_SHORTCUTS; index++)
2321   {
2322     switch(Ordering[index]>>8)
2323     {
2324       case 0 :
2325         Config_Key[Ordering[index]&0xFF][0]=ConfigKey[index].Key;
2326         Config_Key[Ordering[index]&0xFF][1]=ConfigKey[index].Key2;
2327         break;
2328       case 1 :
2329         Buttons_Pool[Ordering[index]&0xFF].Left_shortcut[0] = ConfigKey[index].Key;
2330         Buttons_Pool[Ordering[index]&0xFF].Left_shortcut[1] = ConfigKey[index].Key2;
2331         break;
2332       case 2 :
2333         Buttons_Pool[Ordering[index]&0xFF].Right_shortcut[0] = ConfigKey[index].Key;
2334         Buttons_Pool[Ordering[index]&0xFF].Right_shortcut[1] = ConfigKey[index].Key2;
2335         break;
2336     }
2337   }
2338   // Shade
2339   Shade_current=0;
2340   for (index=0; index<8; index++)
2341   {
2342     Shade_list[index].Step=1;
2343     Shade_list[index].Mode=0;
2344     for (index2=0; index2<512; index2++)
2345       Shade_list[index].List[index2]=256;
2346   }
2347   // Shade par défaut pour la palette standard
2348   for (index=0; index<7; index++)
2349     for (index2=0; index2<16; index2++)
2350       Shade_list[0].List[index*17+index2]=index*16+index2+16;
2351 
2352   Shade_list_to_lookup_tables(Shade_list[Shade_current].List,
2353             Shade_list[Shade_current].Step,
2354             Shade_list[Shade_current].Mode,
2355             Shade_table_left,Shade_table_right);
2356 
2357   // Mask
2358   for (index=0; index<256; index++)
2359     Mask_table[index]=0;
2360 
2361   // Stencil
2362   for (index=0; index<256; index++)
2363     Stencil[index]=1;
2364 
2365   // Smooth
2366   Smooth_matrix[0][0]=1;
2367   Smooth_matrix[0][1]=2;
2368   Smooth_matrix[0][2]=1;
2369   Smooth_matrix[1][0]=2;
2370   Smooth_matrix[1][1]=4;
2371   Smooth_matrix[1][2]=2;
2372   Smooth_matrix[2][0]=1;
2373   Smooth_matrix[2][1]=2;
2374   Smooth_matrix[2][2]=1;
2375 
2376   // Exclude colors
2377   for (index=0; index<256; index++)
2378     Exclude_color[index]=0;
2379 
2380   // Quick shade
2381   Quick_shade_step=1;
2382   Quick_shade_loop=0;
2383 
2384   // Grid
2385   Snap_width=Snap_height=8;
2386   Snap_offset_X=Snap_offset_Y=0;
2387 
2388 }
2389 
2390 #ifdef GRAFX2_CATCHES_SIGNALS
2391 
2392 #if defined(WIN32)
2393 #if defined(_MSC_VER)
2394 typedef void (*__p_sig_fn_t)(int);
2395 #endif
2396   #define SIGHANDLER_T __p_sig_fn_t
2397 #elif defined(__macosx__)
2398   typedef void (*sig_t) (int);
2399   #define SIGHANDLER_T sig_t
2400 #else
2401   #define SIGHANDLER_T __sighandler_t
2402 #endif
2403 
2404 // Memorize the signal handlers of SDL
2405 SIGHANDLER_T Handler_TERM=SIG_DFL;
2406 SIGHANDLER_T Handler_INT=SIG_DFL;
2407 SIGHANDLER_T Handler_ABRT=SIG_DFL;
2408 SIGHANDLER_T Handler_SEGV=SIG_DFL;
2409 SIGHANDLER_T Handler_FPE=SIG_DFL;
2410 
Sig_handler(int sig)2411 void Sig_handler(int sig)
2412 {
2413   // Restore default behaviour
2414   signal(SIGTERM, Handler_TERM);
2415   signal(SIGINT, Handler_INT);
2416   signal(SIGABRT, Handler_ABRT);
2417   signal(SIGSEGV, Handler_SEGV);
2418   signal(SIGFPE, Handler_FPE);
2419 
2420   switch(sig)
2421   {
2422     case SIGTERM:
2423     case SIGINT:
2424     case SIGABRT:
2425     case SIGSEGV:
2426       Image_emergency_backup();
2427     default:
2428     break;
2429    }
2430 }
2431 #endif
2432 
Init_sighandler(void)2433 void Init_sighandler(void)
2434 {
2435 #ifdef GRAFX2_CATCHES_SIGNALS
2436   Handler_TERM=signal(SIGTERM,Sig_handler);
2437   Handler_INT =signal(SIGINT,Sig_handler);
2438   Handler_ABRT=signal(SIGABRT,Sig_handler);
2439   Handler_SEGV=signal(SIGSEGV,Sig_handler);
2440   Handler_FPE =signal(SIGFPE,Sig_handler);
2441 #endif
2442 }
2443 
Init_brush_container(void)2444 void Init_brush_container(void)
2445 {
2446   int i;
2447 
2448   for (i=0; i<BRUSH_CONTAINER_COLUMNS*BRUSH_CONTAINER_ROWS; i++)
2449   {
2450     int x,y,c;
2451 
2452     Brush_container[i].Paintbrush_shape=PAINTBRUSH_SHAPE_MAX;
2453     Brush_container[i].Width=0;
2454     Brush_container[i].Height=0;
2455     memset(Brush_container[i].Palette,0,sizeof(T_Palette));
2456     Brush_container[i].Transp_color=0;
2457     for (y=0; y<BRUSH_CONTAINER_PREVIEW_WIDTH; y++)
2458       for (x=0; x<BRUSH_CONTAINER_PREVIEW_HEIGHT; x++)
2459         Brush_container[i].Thumbnail[y][x]=0;
2460     for (c=0; c<256; c++)
2461         Brush_container[i].Colormap[c]=c;
2462 
2463     Brush_container[i].Brush = NULL;
2464   }
2465 }
2466 
Set_current_skin(const char * skinfile,T_Gui_skin * gfx)2467 void Set_current_skin(const char *skinfile, T_Gui_skin *gfx)
2468 {
2469   int i;
2470 
2471   // Free previous one
2472   free(Gfx);
2473 
2474   // Assign main skin pointer
2475   Gfx = gfx;
2476 
2477   // Change config
2478   if(Config.Skin_file != skinfile) // Happens when loading the initial skin
2479   {
2480     free(Config.Skin_file);
2481     Config.Skin_file = strdup(skinfile);
2482   }
2483 
2484   //Config.Fav_menu_colors[0] = gfx->Default_palette[gfx->Color[0]];
2485   //Config.Fav_menu_colors[1] = gfx->Default_palette[gfx->Color[1]];
2486   //Config.Fav_menu_colors[2] = gfx->Default_palette[gfx->Color[2]];
2487   //Config.Fav_menu_colors[3] = gfx->Default_palette[gfx->Color[3]];
2488 
2489   // Reassign GUI color indices
2490   MC_Black = gfx->Color[0];
2491   MC_Dark =  gfx->Color[1];
2492   MC_Light = gfx->Color[2];
2493   MC_White = gfx->Color[3];
2494   MC_Trans = gfx->Color_trans;
2495   MC_OnBlack=MC_Dark;
2496   MC_Window=MC_Light;
2497   MC_Lighter=MC_White;
2498   MC_Darker=MC_Dark;
2499 
2500 
2501   // Set menubars to point to the new data
2502   for (i=0; i<3; i++)
2503   {
2504     Menu_bars[MENUBAR_TOOLS ].Skin[i] = (byte*)&(gfx->Menu_block[i]);
2505     Menu_bars[MENUBAR_LAYERS].Skin[i] = (byte*)&(gfx->Layerbar_block[i]);
2506     Menu_bars[MENUBAR_ANIMATION].Skin[i] = (byte*)&(gfx->Animbar_block[i]);
2507     Menu_bars[MENUBAR_STATUS].Skin[i] = (byte*)&(gfx->Statusbar_block[i]);
2508   }
2509 }
2510 
Init_paintbrush(int index,int width,int height,byte shape,const char * bitmap)2511 void Init_paintbrush(int index, int width, int height, byte shape, const char * bitmap)
2512 {
2513   if (bitmap!=NULL)
2514   {
2515     int i;
2516 
2517     Paintbrush[index].Shape=shape;
2518     Paintbrush[index].Width=width;
2519     Paintbrush[index].Height=height;
2520     Paintbrush[index].Offset_X=width>>1;
2521     Paintbrush[index].Offset_Y=height>>1;
2522 
2523     // Decode pixels
2524     for (i=0;i<width*height;i++)
2525     {
2526       Paintbrush[index].Sprite[i/width][i%width] =
2527         ((bitmap[i/8] & (0x80 >> (i&7))) != 0);
2528     }
2529   }
2530   else
2531   {
2532     Paintbrush_shape=shape;
2533     Set_paintbrush_size(width, height);
2534     Store_paintbrush(index);
2535   }
2536 
2537 }
2538 
2539 
Init_paintbrushes(void)2540 void Init_paintbrushes(void)
2541 {
2542   int index;
2543 
2544   Init_paintbrush( 0, 1, 1,PAINTBRUSH_SHAPE_SQUARE, NULL);
2545   Init_paintbrush( 1, 2, 2,PAINTBRUSH_SHAPE_SQUARE, NULL);
2546   Init_paintbrush( 2, 3, 3,PAINTBRUSH_SHAPE_SQUARE, NULL);
2547   Init_paintbrush( 3, 4, 4,PAINTBRUSH_SHAPE_SQUARE, NULL);
2548   Init_paintbrush( 4, 5, 5,PAINTBRUSH_SHAPE_SQUARE, NULL);
2549   Init_paintbrush( 5, 7, 7,PAINTBRUSH_SHAPE_SQUARE, NULL);
2550   Init_paintbrush( 6, 8, 8,PAINTBRUSH_SHAPE_SQUARE, NULL);
2551   Init_paintbrush( 7,12,12,PAINTBRUSH_SHAPE_SQUARE, NULL);
2552   Init_paintbrush( 8,16,16,PAINTBRUSH_SHAPE_SQUARE, NULL);
2553   Init_paintbrush( 9,16,16,PAINTBRUSH_SHAPE_SIEVE_SQUARE, NULL);
2554   Init_paintbrush(10,15,15,PAINTBRUSH_SHAPE_DIAMOND, NULL);
2555   Init_paintbrush(11, 5, 5,PAINTBRUSH_SHAPE_DIAMOND, NULL);
2556   Init_paintbrush(12, 3, 3,PAINTBRUSH_SHAPE_ROUND, NULL);
2557   Init_paintbrush(13, 4, 4,PAINTBRUSH_SHAPE_ROUND, NULL);
2558   Init_paintbrush(14, 5, 5,PAINTBRUSH_SHAPE_ROUND, NULL);
2559   Init_paintbrush(15, 6, 6,PAINTBRUSH_SHAPE_ROUND, NULL);
2560   Init_paintbrush(16, 8, 8,PAINTBRUSH_SHAPE_ROUND, NULL);
2561   Init_paintbrush(17,10,10,PAINTBRUSH_SHAPE_ROUND, NULL);
2562   Init_paintbrush(18,12,12,PAINTBRUSH_SHAPE_ROUND, NULL);
2563   Init_paintbrush(19,14,14,PAINTBRUSH_SHAPE_ROUND, NULL);
2564   Init_paintbrush(20,16,16,PAINTBRUSH_SHAPE_ROUND, NULL);
2565   Init_paintbrush(21,15,15,PAINTBRUSH_SHAPE_SIEVE_ROUND, NULL);
2566   Init_paintbrush(22,11,11,PAINTBRUSH_SHAPE_SIEVE_ROUND, NULL);
2567   Init_paintbrush(23, 5, 5,PAINTBRUSH_SHAPE_SIEVE_ROUND, NULL);
2568   Init_paintbrush(24, 2, 1,PAINTBRUSH_SHAPE_HORIZONTAL_BAR, NULL);
2569   Init_paintbrush(25, 3, 1,PAINTBRUSH_SHAPE_HORIZONTAL_BAR, NULL);
2570   Init_paintbrush(26, 4, 1,PAINTBRUSH_SHAPE_HORIZONTAL_BAR, NULL);
2571   Init_paintbrush(27, 8, 1,PAINTBRUSH_SHAPE_HORIZONTAL_BAR, NULL);
2572   Init_paintbrush(28, 1, 2,PAINTBRUSH_SHAPE_VERTICAL_BAR, NULL);
2573   Init_paintbrush(29, 1, 3,PAINTBRUSH_SHAPE_VERTICAL_BAR, NULL);
2574   Init_paintbrush(30, 1, 4,PAINTBRUSH_SHAPE_VERTICAL_BAR, NULL);
2575   Init_paintbrush(31, 1, 8,PAINTBRUSH_SHAPE_VERTICAL_BAR, NULL);
2576   Init_paintbrush(32, 3, 3,PAINTBRUSH_SHAPE_CROSS, NULL);
2577   Init_paintbrush(33, 5, 5,PAINTBRUSH_SHAPE_CROSS, NULL);
2578   Init_paintbrush(34, 5, 5,PAINTBRUSH_SHAPE_PLUS, NULL);
2579   Init_paintbrush(35,15,15,PAINTBRUSH_SHAPE_PLUS, NULL);
2580   Init_paintbrush(36, 2, 2,PAINTBRUSH_SHAPE_SLASH, NULL);
2581   Init_paintbrush(37, 4, 4,PAINTBRUSH_SHAPE_SLASH, NULL);
2582   Init_paintbrush(38, 8, 8,PAINTBRUSH_SHAPE_SLASH, NULL);
2583   Init_paintbrush(39, 2, 2,PAINTBRUSH_SHAPE_ANTISLASH, NULL);
2584   Init_paintbrush(40, 4, 4,PAINTBRUSH_SHAPE_ANTISLASH, NULL);
2585   Init_paintbrush(41, 8, 8,PAINTBRUSH_SHAPE_ANTISLASH, NULL);
2586 
2587   Init_paintbrush(42, 4, 4,PAINTBRUSH_SHAPE_RANDOM, "\x20\x81");
2588   Init_paintbrush(43, 8, 8,PAINTBRUSH_SHAPE_RANDOM, "\x44\x00\x11\x00\x88\x01\x40\x08");
2589   Init_paintbrush(44,13,13,PAINTBRUSH_SHAPE_RANDOM, "\x08\x00\x08\x90\x00\x10\x42\x10\x02\x06\x02\x02\x04\x02\x08\x42\x10\x44\x00\x00\x44\x00");
2590 
2591   Init_paintbrush(45, 3, 3,PAINTBRUSH_SHAPE_MISC, "\x7f\x00");
2592   Init_paintbrush(46, 3, 3,PAINTBRUSH_SHAPE_MISC, "\xdd\x80");
2593   Init_paintbrush(47, 7, 7,PAINTBRUSH_SHAPE_MISC, "\x06\x30\x82\x04\x10\x20\x00");
2594 
2595   for (index=0;index<NB_PAINTBRUSH_SPRITES;index++)
2596   {
2597     Paintbrush[index].Offset_X=(Paintbrush[index].Width>>1);
2598     Paintbrush[index].Offset_Y=(Paintbrush[index].Height>>1);
2599   }
2600 }
2601