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, ¤t_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