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 /// @file engine.c: Window engine and interface management
21 #include <string.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24
25 #ifdef _MSC_VER
26 #include <stdio.h>
27 #define strdup _strdup
28 #if _MSC_VER < 1900
29 #define snprintf _snprintf
30 #endif
31 #endif
32
33 #include "const.h"
34 #include "struct.h"
35 #include "global.h"
36 #include "graph.h"
37 #include "misc.h"
38 #include "osdep.h"
39 #include "special.h"
40 #include "buttons.h"
41 #include "operatio.h"
42 #include "shade.h"
43 #include "errors.h"
44 #include "screen.h"
45 #include "windows.h"
46 #include "brush.h"
47 #include "input.h"
48 #include "engine.h"
49 #include "pages.h"
50 #include "layers.h"
51 #include "factory.h"
52 #include "loadsave.h"
53 #include "io.h"
54 #include "pxsimple.h"
55 #include "oldies.h"
56 #include "palette.h"
57 #include "unicode.h"
58
59 #if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__) || defined(__SWITCH__)
60 // We don't want to underline the keyboard shortcuts as there is no keyboard
61 #define NO_KEYBOARD
62 #endif
63
64
65 // we need this as global
66 short Old_MX = -1;
67 short Old_MY = -1;
68
69 //---------- Annuler les effets des modes de dessin (sauf la grille) ---------
70
71 // Variables mémorisants les anciens effets
72
73 byte Shade_mode_before_cancel;
74 byte Quick_shade_mode_before_cancel;
75 byte Stencil_mode_before_cancel;
76 byte Sieve_mode_before_cancel;
77 byte Colorize_mode_before_cancel;
78 byte Smooth_mode_before_cancel;
79 byte Tiling_mode_before_cancel;
80 Func_effect Effect_function_before_cancel;
81
82 ///This table holds pointers to the saved window backgrounds. We can have up to 8 windows open at a time.
83 static byte* Window_background[8];
84
85 ///Save a screen block (usually before erasing it with a new window or a dropdown menu)
Save_background(byte ** buffer,int x_pos,int y_pos,int width,int height)86 static void Save_background(byte **buffer, int x_pos, int y_pos, int width, int height)
87 {
88 int index;
89 if(*buffer != NULL)
90 {
91 GFX2_Log(GFX2_WARNING, "%s() WARNING : buffer already allocated !!!\n", __func__);
92 free(*buffer);
93 }
94 *buffer=(byte *) malloc(width*Menu_factor_X*height*Menu_factor_Y*Pixel_width);
95 if(*buffer==NULL)
96 {
97 Error(0);
98 return;
99 }
100 for (index=0; index<(height*Menu_factor_Y); index++)
101 Read_line(x_pos,y_pos+index,width*Menu_factor_X,(*buffer)+((int)index*width*Menu_factor_X*Pixel_width));
102 }
103
104 ///Restores a screen block
Restore_background(byte ** buffer,int x_pos,int y_pos,int width,int height)105 static void Restore_background(byte **buffer, int x_pos, int y_pos, int width, int height)
106 {
107 int index;
108 if(*buffer==NULL) return;
109 for (index=0; index<height*Menu_factor_Y; index++)
110 Display_line_fast(x_pos,y_pos+index,width*Menu_factor_X,*buffer+((int)index*width*Menu_factor_X*Pixel_width));
111 free(*buffer);
112 *buffer = NULL;
113 }
114
115 ///Draw a pixel in a saved screen block (when you sort colors in the palette, for example)
Pixel_background(int x_pos,int y_pos,byte color)116 void Pixel_background(int x_pos, int y_pos, byte color)
117 {
118 int x_repetition=Pixel_width;
119 while (x_repetition--)
120 (Window_background[0][x_pos*Pixel_width+x_repetition+y_pos*Window_width*Pixel_width*Menu_factor_X])=color;
121 }
122
123
124 ///Guess the number of the button that was just clicked
Button_under_mouse(void)125 int Button_under_mouse(void)
126 {
127 int btn_number;
128 short x_pos;
129 short y_pos;
130 byte current_menu;
131 byte first_button;
132
133 x_pos = Mouse_X / Menu_factor_X;
134
135 // Find in which menubar we are
136 for (current_menu = 0; current_menu < MENUBAR_COUNT; current_menu ++)
137 {
138 if (Menu_bars[current_menu].Visible)
139 {
140 if (Mouse_Y >= Menu_Y+Menu_factor_Y*(Menu_bars[current_menu].Top) &&
141 Mouse_Y < Menu_Y+Menu_factor_Y*(Menu_bars[current_menu].Top + Menu_bars[current_menu].Height))
142 break;
143 }
144 }
145 if (current_menu==MENUBAR_COUNT)
146 return -1;
147
148 y_pos=(Mouse_Y - Menu_Y)/Menu_factor_Y - Menu_bars[current_menu].Top;
149
150 if (current_menu == 0) first_button = 0;
151 else first_button = Menu_bars[current_menu - 1].Last_button_index + 1;
152
153 for (btn_number=first_button;btn_number<=Menu_bars[current_menu].Last_button_index;btn_number++)
154 {
155 switch(Buttons_Pool[btn_number].Shape)
156 {
157 case BUTTON_SHAPE_NO_FRAME :
158 case BUTTON_SHAPE_RECTANGLE :
159
160 if ((x_pos>=Buttons_Pool[btn_number].X_offset) &&
161 (y_pos>=Buttons_Pool[btn_number].Y_offset) &&
162 (x_pos<=Buttons_Pool[btn_number].X_offset+Buttons_Pool[btn_number].Width) &&
163 (y_pos<=Buttons_Pool[btn_number].Y_offset+Buttons_Pool[btn_number].Height))
164 return btn_number;
165 break;
166
167 case BUTTON_SHAPE_TRIANGLE_TOP_LEFT:
168 if ((x_pos>=Buttons_Pool[btn_number].X_offset) &&
169 (y_pos>=Buttons_Pool[btn_number].Y_offset) &&
170 (x_pos+y_pos-(short)Buttons_Pool[btn_number].Y_offset-(short)Buttons_Pool[btn_number].X_offset<=Buttons_Pool[btn_number].Width))
171 return btn_number;
172 break;
173
174 case BUTTON_SHAPE_TRIANGLE_BOTTOM_RIGHT:
175 if ((x_pos<=Buttons_Pool[btn_number].X_offset+Buttons_Pool[btn_number].Width) &&
176 (y_pos<=Buttons_Pool[btn_number].Y_offset+Buttons_Pool[btn_number].Height) &&
177 (x_pos+y_pos-(short)Buttons_Pool[btn_number].Y_offset-(short)Buttons_Pool[btn_number].X_offset>=Buttons_Pool[btn_number].Width))
178 return btn_number;
179 break;
180 }
181 }
182 return -1;
183 }
184
185
186 ///Draw a menu button, selected or not
Draw_menu_button(byte btn_number,byte pressed)187 void Draw_menu_button(byte btn_number,byte pressed)
188 {
189 word start_x;
190 word start_y;
191 word width;
192 word height;
193 byte * bitmap;
194 word bitmap_width;
195 word x_pos;
196 word y_pos;
197 byte current_menu;
198 byte color;
199 signed char icon;
200
201 // Find in which menu the button is
202 for (current_menu = 0; current_menu < MENUBAR_COUNT; current_menu++)
203 {
204 // We found the right bar !
205 if (Menu_bars[current_menu].Last_button_index >= btn_number &&
206 (current_menu==0 || Menu_bars[current_menu -1].Last_button_index < btn_number))
207 {
208 break;
209 }
210 }
211
212 start_x = Buttons_Pool[btn_number].X_offset;
213 start_y = Buttons_Pool[btn_number].Y_offset;
214 width = Buttons_Pool[btn_number].Width+1;
215 height = Buttons_Pool[btn_number].Height+1;
216 icon = Buttons_Pool[btn_number].Icon;
217
218 if (icon==-1)
219 {
220 // Standard button
221 bitmap_width = Menu_bars[current_menu].Skin_width;
222 bitmap=&(Menu_bars[current_menu].Skin[pressed][start_y*Menu_bars[current_menu].Skin_width+start_x]);
223 }
224 else
225 {
226 // From Menu_buttons
227 bitmap_width = MENU_SPRITE_WIDTH;
228 bitmap=Gfx->Menu_sprite[pressed][(byte)icon][0];
229 // For bottom right: offset +1,+1
230 if (Buttons_Pool[btn_number].Shape==BUTTON_SHAPE_TRIANGLE_BOTTOM_RIGHT)
231 bitmap += MENU_SPRITE_WIDTH+1;
232 }
233
234 switch(Buttons_Pool[btn_number].Shape)
235 {
236 case BUTTON_SHAPE_NO_FRAME :
237 break;
238 case BUTTON_SHAPE_RECTANGLE :
239 for (y_pos=0;y_pos<height;y_pos++)
240 for (x_pos=0;x_pos<width;x_pos++)
241 {
242 color=bitmap[x_pos+y_pos*bitmap_width];
243 Pixel_in_menu_and_skin(current_menu, start_x+x_pos, start_y+y_pos, color);
244 }
245 break;
246 case BUTTON_SHAPE_TRIANGLE_TOP_LEFT:
247 for (y_pos=0;y_pos<15;y_pos++)
248 for (x_pos=0;x_pos<15-y_pos;x_pos++)
249 {
250 color=bitmap[x_pos+y_pos*bitmap_width];
251 Pixel_in_menu_and_skin(current_menu, start_x+x_pos, start_y+y_pos, color);
252 }
253 break;
254 case BUTTON_SHAPE_TRIANGLE_BOTTOM_RIGHT:
255 for (y_pos=0;y_pos<15;y_pos++)
256 for (x_pos=14-y_pos;x_pos<15;x_pos++)
257 {
258 color=bitmap[(x_pos)+(y_pos)*bitmap_width];
259 Pixel_in_menu_and_skin(current_menu, start_x+x_pos, start_y+y_pos, color);
260 }
261 break;
262 }
263 // Special: Show specific shape
264 if (btn_number==BUTTON_PAINTBRUSHES
265 && Paintbrush_shape!=PAINTBRUSH_SHAPE_COLOR_BRUSH
266 && Paintbrush_shape!=PAINTBRUSH_SHAPE_MONO_BRUSH)
267 {
268 short x_pos,y_pos;
269 short start_x;
270 short menu_x_pos,menu_y_pos;
271 short menu_start_x;
272
273 // Print paintbrush shape
274 menu_start_x=8-Paintbrush_offset_X;
275 if (menu_start_x<1)
276 {
277 start_x=Paintbrush_offset_X-7;
278 menu_start_x=1;
279 }
280 else
281 start_x=0;
282
283 menu_y_pos=9-Paintbrush_offset_Y;
284 if (menu_y_pos<2)
285 {
286 y_pos=Paintbrush_offset_Y-7;
287 menu_y_pos=2;
288 }
289 else
290 y_pos=0;
291
292 for (;((y_pos<Paintbrush_height) && (menu_y_pos<16));menu_y_pos++,y_pos++)
293 for (menu_x_pos=menu_start_x,x_pos=start_x;((x_pos<Paintbrush_width) && (menu_x_pos<15));menu_x_pos++,x_pos++)
294 {
295 if (Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos])
296 Pixel_in_menu_and_skin(MENUBAR_TOOLS, menu_x_pos, menu_y_pos, MC_Black);
297 }
298 }
299
300 if (Menu_is_visible && Menu_bars[current_menu].Visible)
301 Update_rect(Menu_factor_X*(Buttons_Pool[btn_number].X_offset),
302 (Buttons_Pool[btn_number].Y_offset+Menu_bars[current_menu].Top)*Menu_factor_Y+Menu_Y,
303 width*Menu_factor_X,height*Menu_factor_Y);
304
305 /*
306 switch (pressed)
307 {
308 default:
309 case BUTTON_RELEASED:
310 color_top_left=MC_White;
311 color_bottom_right=MC_Dark;
312 color_diagonal=MC_Light;
313 break;
314
315 case BUTTON_PRESSED:
316 color_top_left=MC_Dark;
317 color_bottom_right=MC_Black;
318 color_diagonal=MC_Black;
319 break;
320 }
321
322 switch(Buttons_Pool[btn_number].Shape)
323 {
324 case BUTTON_SHAPE_NO_FRAME :
325 break;
326 case BUTTON_SHAPE_RECTANGLE :
327 // On colorie le point haut droit
328 Pixel_in_menu_and_skin(current_menu, end_x, start_y, color_diagonal);
329 // On colorie le point bas gauche
330 Pixel_in_menu_and_skin(current_menu, start_x, end_y, color_diagonal);
331 // On colorie la partie haute
332 for (x_pos=start_x;x_pos<=end_x-1;x_pos++)
333 {
334 Pixel_in_menu_and_skin(current_menu, x_pos, start_y, color_top_left);
335 }
336 for (y_pos=start_y+1;y_pos<=end_y-1;y_pos++)
337 {
338 // On colorie la partie gauche
339 Pixel_in_menu_and_skin(current_menu, start_x, y_pos, color_top_left);
340 // On colorie la partie droite
341 Pixel_in_menu_and_skin(current_menu, end_x, y_pos, color_bottom_right);
342 }
343 // On colorie la partie basse
344 for (x_pos=start_x+1;x_pos<=end_x;x_pos++)
345 {
346 Pixel_in_menu_and_skin(current_menu, x_pos, end_y, color_bottom_right);
347 }
348 break;
349 case BUTTON_SHAPE_TRIANGLE_TOP_LEFT:
350 // On colorie le point haut droit
351 Pixel_in_menu_and_skin(current_menu, end_x, start_y, color_top_left);
352 // On colorie le point bas gauche
353 Pixel_in_menu_and_skin(current_menu, start_x, end_y, color_top_left);
354 // On colorie le coin haut gauche
355 for (x_pos=0;x_pos<Buttons_Pool[btn_number].Width;x_pos++)
356 {
357 Pixel_in_menu_and_skin(current_menu, start_x+x_pos, start_y, color_top_left);
358 Pixel_in_menu_and_skin(current_menu, start_x, start_y+x_pos, color_top_left);
359 }
360 // On colorie la diagonale
361 for (x_pos=1;x_pos<Buttons_Pool[btn_number].Width;x_pos++)
362 {
363 Pixel_in_menu_and_skin(current_menu, start_x+x_pos, end_y-x_pos, color_bottom_right);
364 }
365 break;
366 case BUTTON_SHAPE_TRIANGLE_BOTTOM_RIGHT:
367 // On colorie le point haut droit
368 Pixel_in_menu_and_skin(current_menu, end_x, start_y, color_diagonal);
369 // On colorie le point bas gauche
370 Pixel_in_menu_and_skin(current_menu, start_x, end_y, color_diagonal);
371 // On colorie la diagonale
372 for (x_pos=1;x_pos<Buttons_Pool[btn_number].Width;x_pos++)
373 {
374 Pixel_in_menu_and_skin(current_menu, start_x+x_pos, end_y-x_pos, color_top_left);
375 }
376 // On colorie le coin bas droite
377 for (x_pos=0;x_pos<Buttons_Pool[btn_number].Width;x_pos++)
378 {
379 Pixel_in_menu_and_skin(current_menu, end_x-x_pos, end_y, color_bottom_right);
380 Pixel_in_menu_and_skin(current_menu, end_x, end_y-x_pos, color_bottom_right);
381 }
382 }
383 if (Menu_is_visible && Menu_bars[current_menu].Visible)
384 {
385 Update_rect(
386 start_x*Menu_factor_X,
387 (start_y+Menu_bars[current_menu].Top)*Menu_factor_Y + Menu_Y,
388 (end_x+1-start_x)*Menu_factor_X,
389 (end_y+1-start_y)*Menu_factor_Y);
390 }
391 */
392 }
393
394
395 ///Deselect a button
Unselect_button(int btn_number)396 void Unselect_button(int btn_number)
397 {
398 if (btn_number < 0 || btn_number >= NB_BUTTONS)
399 return;
400 if (Buttons_Pool[btn_number].Pressed)
401 {
402 // On considère que le bouton est relâché
403 Buttons_Pool[btn_number].Pressed=BUTTON_RELEASED;
404 // On affiche le cadre autour du bouton de façon à ce qu'il paraisse relâché
405 Draw_menu_button(btn_number,BUTTON_RELEASED);
406 // On appelle le désenclenchement particulier au bouton:
407 Buttons_Pool[btn_number].Unselect_action(btn_number);
408 }
409 }
410
411
412 ///Select a button and disable all his family (for example, selecting "freehand" unselect "curves", "lines", ...)
Select_button(int btn_number,byte click)413 void Select_button(int btn_number,byte click)
414 {
415 int family;
416 int b;
417 int icon;
418
419 Hide_cursor();
420
421 // Certains boutons ont deux icones
422 icon=-1;
423 switch(btn_number)
424 {
425 case BUTTON_POLYGONS:
426 case BUTTON_POLYFILL:
427 icon=MENU_SPRITE_POLYFORM;
428 break;
429 case BUTTON_FLOODFILL:
430 icon=MENU_SPRITE_REPLACE;
431 break;
432 }
433 if (icon!=-1)
434 {
435 // This changes the sprite number of both halves of a split button
436 Display_sprite_in_menu(btn_number,click==RIGHT_SIDE?icon:-1);
437
438 // Redraw the other half if Unselect_button() won't do it.
439 if (Buttons_Pool[btn_number].Shape==BUTTON_SHAPE_TRIANGLE_TOP_LEFT &&
440 !Buttons_Pool[btn_number+1].Pressed)
441 Draw_menu_button(btn_number+1, BUTTON_RELEASED);
442 else if (Buttons_Pool[btn_number].Shape==BUTTON_SHAPE_TRIANGLE_BOTTOM_RIGHT &&
443 !Buttons_Pool[btn_number-1].Pressed)
444 Draw_menu_button(btn_number-1, BUTTON_RELEASED);
445 }
446
447 // On note déjà la famille du bouton (La "Famiglia" c'est sacré)
448 family=Buttons_Pool[btn_number].Family;
449
450 switch (family)
451 {
452 case FAMILY_TOOLBAR: // On ne fait rien (on préserve les interruptions)
453 break;
454
455 case FAMILY_INTERRUPTION: // Petit cas spécial dans la famille "Interruption":
456 if ((btn_number!=BUTTON_MAGNIFIER) || (!Main.magnifier_mode))
457 // Pour chaque bouton:
458 for (b=0; b<NB_BUTTONS; b++)
459 // S'il est de la même famille
460 if (
461 (b!=btn_number) &&
462 (Buttons_Pool[b].Family==FAMILY_INTERRUPTION) &&
463 ( (b!=BUTTON_MAGNIFIER) ||
464 ((b==BUTTON_MAGNIFIER) && (!Main.magnifier_mode)) )
465 )
466 // Alors on désenclenche le bouton
467 Unselect_button(b);
468 break;
469
470 default:
471 // On désenclenche D'ABORD les interruptions
472 // Pour chaque bouton:
473 for (b=0; b<NB_BUTTONS; b++)
474 // S'il est de la famille interruption
475 if ( (b!=btn_number)
476 && (Buttons_Pool[b].Family==FAMILY_INTERRUPTION)
477 // Et que ce n'est pas la loupe, ou alors qu'on n'est pas en mode loupe
478 && (!(Main.magnifier_mode && (b==BUTTON_MAGNIFIER))) )
479 // Alors on désenclenche le bouton
480 Unselect_button(b);
481 // Right-clicking on Adjust opens a menu, so in this case we skip
482 // the unselection of all "Tool" buttons.
483 if (btn_number==BUTTON_ADJUST && click==RIGHT_SIDE)
484 break;
485 // Same case with the Grad. Rectangle button.
486 if (btn_number==BUTTON_GRADRECT && click==RIGHT_SIDE)
487 break;
488 // Pour chaque bouton:
489 for (b=0; b<NB_BUTTONS; b++)
490 // S'il est de la même famille
491 if ( (b!=btn_number)
492 && (Buttons_Pool[b].Family==family) )
493 // Alors on désenclenche le bouton
494 Unselect_button(b);
495 }
496
497 // On considère que le bouton est enfoncé
498 Buttons_Pool[btn_number].Pressed=BUTTON_PRESSED;
499
500 // On affiche le cadre autour du bouton de façon à ce qu'il paraisse enfoncé
501 Draw_menu_button(btn_number, BUTTON_PRESSED);
502
503 Display_cursor();
504
505 if ((click==1 && !Buttons_Pool[btn_number].Left_instant)
506 ||(click!=1 && !Buttons_Pool[btn_number].Right_instant))
507 {
508 // On attend ensuite que l'utilisateur lâche son bouton:
509 Wait_end_of_click();
510 }
511
512 // Puis on se contente d'appeler l'action correspondant au bouton:
513 if (click==1)
514 Buttons_Pool[btn_number].Left_action(btn_number);
515 else
516 Buttons_Pool[btn_number].Right_action(btn_number);
517 }
518
519
520 ///Moves the splitbar between zoom and standard views
Move_separator(void)521 void Move_separator(void)
522 {
523 short old_main_separator_position=Main.separator_position;
524 short old_x_zoom=Main.X_zoom;
525 short offset=Main.X_zoom-Mouse_X;
526 byte old_cursor_shape=Cursor_shape;
527 short old_mouse_x=-1;
528
529 // Afficher la barre en XOR
530 Hide_cursor();
531 Windows_open=1;
532 Cursor_shape=CURSOR_SHAPE_HORIZONTAL;
533 Vertical_XOR_line(Main.separator_position,0,Menu_Y);
534 Vertical_XOR_line(Main.X_zoom-1,0,Menu_Y);
535 Display_cursor();
536 Update_rect(Main.separator_position,0,abs(Main.separator_position-Main.X_zoom)+1,Menu_Y);
537
538 while (Mouse_K)
539 {
540 if (Mouse_X!=old_mouse_x)
541 {
542 old_mouse_x=Mouse_X;
543 Main.separator_proportion=(float)(Mouse_X+offset)/Screen_width;
544 Compute_separator_data();
545
546 if (Main.X_zoom!=old_x_zoom)
547 {
548 Hide_cursor();
549
550 // Effacer la barre en XOR
551 Vertical_XOR_line(old_main_separator_position,0,Menu_Y);
552 Vertical_XOR_line(old_x_zoom-1,0,Menu_Y);
553
554 Update_rect(old_main_separator_position,0,abs(old_main_separator_position-old_x_zoom)+1,Menu_Y);
555
556 old_main_separator_position=Main.separator_position;
557 old_x_zoom=Main.X_zoom;
558
559 // Rafficher la barre en XOR
560 Vertical_XOR_line(Main.separator_position,0,Menu_Y);
561 Vertical_XOR_line(Main.X_zoom-1,0,Menu_Y);
562
563 Update_rect(Main.separator_position,0,abs(Main.separator_position-Main.X_zoom)+1,Menu_Y);
564
565 Display_cursor();
566 }
567 }
568 Get_input(20);
569 }
570
571 // Effacer la barre en XOR
572 Hide_cursor();
573 Vertical_XOR_line(Main.separator_position,0,Menu_Y);
574 Vertical_XOR_line(Main.X_zoom-1,0,Menu_Y);
575 Windows_open=0;
576 Cursor_shape=old_cursor_shape;
577 Compute_magnifier_data();
578 Position_screen_according_to_zoom();
579 Compute_limits();
580 Display_all_screen();
581 Display_cursor();
582 }
583
584 ///
585 /// Updates the status bar line with a color number.
586 /// Used when hovering the menu palette.
Status_print_palette_color(byte color)587 void Status_print_palette_color(byte color)
588 {
589 char str[25];
590 int i;
591
592 i = snprintf(str, sizeof(str), "%s%d (%d,%d,%d)",
593 Buttons_Pool[BUTTON_CHOOSE_COL].Tooltip, color,
594 Encode_component(Main.palette[color].R),
595 Encode_component(Main.palette[color].G),
596 Encode_component(Main.palette[color].B));
597 // Pad spaces
598 while(i<24)
599 str[i++]=' ';
600 str[24]='\0';
601
602 Print_in_menu(str,0);
603 }
604
605 /// activate layer preview
Layer_preview_on(int * preview_is_visible)606 static void Layer_preview_on(int * preview_is_visible)
607 {
608 int x,y;
609 short layer;
610 short layercount = Main.backups->Pages->Nb_layers;
611 int previewW, previewH;
612
613 if (! *preview_is_visible && layercount>1)
614 {
615 previewW = Min(Main.image_width/Menu_factor_X, Layer_button_width);
616 previewH = previewW * Main.image_height / Main.image_width * Menu_factor_X / Menu_factor_Y;
617 if (previewH > Screen_height/4)
618 {
619 previewH = Screen_height/4;
620 previewW = Main.image_width * previewH / Main.image_height * Menu_factor_Y / Menu_factor_X;
621 }
622
623 Open_popup((Buttons_Pool[BUTTON_LAYER_SELECT].X_offset + 2) * Menu_factor_X,
624 Menu_Y - previewH * Menu_factor_Y,
625 Buttons_Pool[BUTTON_LAYER_SELECT].Width, previewH);
626 *preview_is_visible = 1;
627
628 // Make the system think the menu is visible (Open_popup hides it)
629 // so Button_under_mouse still works
630 Menu_is_visible = Menu_is_visible_before_window;
631 Menu_Y = Menu_Y_before_window;
632
633 Window_rectangle(0, 0, Window_width, Window_height, MC_Dark);
634
635 for(layer = 0; layer < layercount; ++layer)
636 {
637 int offset;
638 // Stop if the window is too small to show the
639 // layer button (ex: 320x200 can only display 12 layers)
640 if (layer * Layer_button_width + previewW > Window_width)
641 break;
642
643 offset = (Layer_button_width - previewW) / 2;
644 for (y = 0; y < previewH*Pixel_height*Menu_factor_Y-1; y++)
645 for (x = 0; x < previewW*Pixel_width*Menu_factor_X-1; x++)
646 {
647 int imgx = x * Main.image_width / (previewW*Pixel_width*Menu_factor_X-1);
648 int imgy = y * Main.image_height / (previewH*Pixel_height*Menu_factor_Y-1);
649 // Use Pixel_simple() in order to get highest resolution
650 Pixel_simple(x + ((layer*Layer_button_width+offset)*Menu_factor_X + Window_pos_X) * Pixel_width,
651 y + Window_pos_Y*Pixel_height + 1,
652 Read_pixel_from_layer(layer, imgx, imgy) );
653 }
654 }
655 Update_window_area(0, 0, Window_width, Window_height);
656 }
657 }
658
Layer_preview_off(int * preview_is_visible)659 void Layer_preview_off(int * preview_is_visible)
660 {
661 if (*preview_is_visible)
662 {
663 int x = Mouse_K;
664 Close_popup();
665 Display_cursor();
666 Mouse_K = x; // Close_popup waits for end of click and resets Mouse_K...
667 *preview_is_visible = 0;
668 }
669 }
670
671 ///Main handler for everything. This is the main loop of the program
Main_handler(void)672 void Main_handler(void)
673 {
674 static byte temp_color;
675 int button_index; // Numéro de bouton de menu en cours
676 int prev_button_number=0; // Numéro de bouton de menu sur lequel on était précédemment
677 byte blink; // L'opération demande un effacement du curseur
678 int key_index; // index du tableau de touches spéciales correspondant à la touche enfoncée
679 byte temp;
680 byte effect_modified;
681 byte action;
682 dword key_pressed;
683
684 int preview_is_visible=0;
685 // This is used for the layer preview
686
687 do
688 {
689 // Resize requested
690 if (Resize_width || Resize_height)
691 {
692 if (Window_state == GFX2_WINDOW_STANDARD)
693 {
694 Default_window_width = Resize_width;
695 Default_window_height = Resize_height;
696 }
697
698 Hide_cursor();
699 Init_mode_video(Resize_width, Resize_height, 0, Pixel_ratio);
700 // Reset the variables that indicate a resize was requested.
701 Display_menu();
702 Reposition_palette();
703 Display_all_screen();
704 Display_cursor();
705 }
706 else if (Drop_file_name)
707 {
708 // A file was dragged into Grafx2's window
709 if (Main.image_is_modified && !Confirmation_box("Discard unsaved changes ?"))
710 {
711 // do nothing
712 }
713 else
714 {
715 T_IO_Context context;
716 char* flimit;
717 byte old_cursor_shape;
718
719 flimit = Find_last_separator(Drop_file_name);
720 if (flimit != NULL)
721 {
722 *(flimit++) = '\0';
723
724 Upload_infos_page(&Main);
725
726 Hide_cursor();
727 old_cursor_shape=Cursor_shape;
728 Cursor_shape=CURSOR_SHAPE_HOURGLASS;
729 Display_cursor();
730
731 Init_context_layered_image(&context, flimit, Drop_file_name);
732 if (Drop_file_name_unicode != NULL)
733 {
734 word * file_name_unicode = Find_last_separator_unicode(Drop_file_name_unicode);
735 if (file_name_unicode != NULL)
736 context.File_name_unicode = Unicode_strdup(file_name_unicode + 1);
737 else
738 context.File_name_unicode = Unicode_strdup(Drop_file_name_unicode);
739 }
740 Load_image(&context);
741 if (File_error!=1)
742 {
743 Compute_limits();
744 Compute_paintbrush_coordinates();
745 Redraw_layered_image();
746 End_of_modification();
747 Main.image_is_modified=0;
748 }
749 Destroy_context(&context);
750
751 Compute_optimal_menu_colors(Main.palette);
752 Check_menu_mode();
753 Display_menu();
754 if (Config.Display_image_limits)
755 Display_image_limits();
756
757 Hide_cursor();
758 Cursor_shape=old_cursor_shape;
759 Display_all_screen();
760 Display_cursor();
761 }
762 }
763 free(Drop_file_name);
764 Drop_file_name=NULL;
765 free(Drop_file_name_unicode);
766 Drop_file_name_unicode=NULL;
767 }
768
769 if(Get_input(0))
770 {
771 action = 0;
772
773 // Inhibit all keys if a drawing operation is in progress.
774 // We make an exception for the freehand operations, but these will
775 // only accept a very limited number of shortcuts.
776 if (Operation_stack_size!=0 && !Allow_color_change_during_operation)
777 Key=0;
778
779 // Evenement de fermeture
780 if (Quit_is_required)
781 {
782 Quit_is_required=0;
783 Button_Quit(BUTTON_QUIT);
784 }
785
786 if (Pan_shortcut_pressed && Current_operation!=OPERATION_PAN_VIEW && Operation_stack_size==0)
787 {
788 Hide_cursor();
789 Start_operation_stack(OPERATION_PAN_VIEW);
790 Display_cursor();
791 action++;
792 }
793 else if (Key == SHORTCUT_PASTE) /// @todo create a SPECIAL_ACTIONS for Copy and Paste ?
794 {
795 // simulate loading of Brush
796 T_IO_Context brush_context;
797 Init_context_brush(&brush_context, NULL, NULL);
798 brush_context.Format = FORMAT_CLIPBOARD;
799 Load_image(&brush_context);
800 if (File_error == 0)
801 {
802 free(Brush_filename);
803 Brush_filename = strdup("NO_NAME.GIF");
804 free(Brush_filename_unicode);
805 Brush_filename_unicode = NULL;
806 Brush_fileformat = FORMAT_GIF;
807
808 Tiling_offset_X=0;
809 Tiling_offset_Y=0;
810
811 Brush_offset_X=(Brush_width>>1);
812 Brush_offset_Y=(Brush_height>>1);
813
814 Select_button(BUTTON_DRAW,LEFT_SIDE);
815 if (Config.Auto_discontinuous)
816 {
817 // On se place en mode Dessin discontinu à la main
818 while (Current_operation!=OPERATION_DISCONTINUOUS_DRAW)
819 Select_button(BUTTON_DRAW,RIGHT_SIDE);
820 }
821 Hide_cursor();
822 // On passe en brosse couleur:
823 Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
824 }
825 Destroy_context(&brush_context);
826 }
827 else if (Key == SHORTCUT_COPY)
828 {
829 if (Paintbrush_shape == PAINTBRUSH_SHAPE_COLOR_BRUSH && Brush != NULL)
830 {
831 // simulate saving of Brush
832 T_IO_Context brush_context;
833 Init_context_brush(&brush_context, NULL, NULL);
834 brush_context.Format = FORMAT_CLIPBOARD;
835 Save_image(&brush_context);
836 Destroy_context(&brush_context);
837 }
838 else
839 {
840 // save whole image to clipboard
841 T_IO_Context image_context;
842 Init_context_layered_image(&image_context, NULL, NULL);
843 image_context.Format = FORMAT_CLIPBOARD;
844 Save_image(&image_context);
845 Destroy_context(&image_context);
846 }
847 }
848 else if (Key)
849 {
850 effect_modified = 0;
851
852 for (key_index=SPECIAL_CLICK_RIGHT+1;key_index<NB_SPECIAL_SHORTCUTS;key_index++)
853 {
854 if (Is_shortcut(Key,key_index))
855 {
856 Layer_preview_off(&preview_is_visible);
857
858 // Special keys (functions not hooked to a UI button)
859 switch(key_index)
860 {
861 case SPECIAL_NEXT_FORECOLOR : // Next foreground color
862 Special_next_forecolor();
863 action++;
864 break;
865 case SPECIAL_PREVIOUS_FORECOLOR : // Previous foreground color
866 Special_previous_forecolor();
867 action++;
868 break;
869 case SPECIAL_NEXT_BACKCOLOR : // Next background color
870 Special_next_backcolor();
871 action++;
872 break;
873 case SPECIAL_PREVIOUS_BACKCOLOR : // Previous background color
874 Special_previous_backcolor();
875 action++;
876 break;
877 case SPECIAL_SMALLER_PAINTBRUSH: // Rétrécir le pinceau
878 Smaller_paintbrush();
879 action++;
880 break;
881 case SPECIAL_BIGGER_PAINTBRUSH: // Grossir le pinceau
882 Bigger_paintbrush();
883 action++;
884 break;
885 case SPECIAL_NEXT_USER_FORECOLOR : // Next user-defined foreground color
886 Special_next_user_forecolor();
887 action++;
888 break;
889 case SPECIAL_PREVIOUS_USER_FORECOLOR : // Previous user-defined foreground color
890 Special_previous_user_forecolor();
891 action++;
892 break;
893 case SPECIAL_NEXT_USER_BACKCOLOR : // Next user-defined background color
894 Special_next_user_backcolor();
895 action++;
896 break;
897 case SPECIAL_PREVIOUS_USER_BACKCOLOR : // Previous user-defined background color
898 Special_previous_user_backcolor();
899 action++;
900 break;
901 }
902
903 // Other shortcuts are forbidden while an operation is in progress
904 if (Operation_stack_size!=0)
905 continue;
906
907 switch (key_index)
908 {
909 case SPECIAL_SCROLL_UP : // Scroll up
910 if (Main.magnifier_mode)
911 Scroll_magnifier(0,-(Main.magnifier_height>>2));
912 else
913 Scroll_screen(0,-(Screen_height>>3));
914 action++;
915 break;
916 case SPECIAL_SCROLL_DOWN : // Scroll down
917 if (Main.magnifier_mode)
918 Scroll_magnifier(0,(Main.magnifier_height>>2));
919 else
920 Scroll_screen(0,(Screen_height>>3));
921 action++;
922 break;
923 case SPECIAL_SCROLL_LEFT : // Scroll left
924 if (Main.magnifier_mode)
925 Scroll_magnifier(-(Main.magnifier_width>>2),0);
926 else
927 Scroll_screen(-(Screen_width>>3),0);
928 action++;
929 break;
930 case SPECIAL_SCROLL_RIGHT : // Scroll right
931 if (Main.magnifier_mode)
932 Scroll_magnifier((Main.magnifier_width>>2),0);
933 else
934 Scroll_screen((Screen_width>>3),0);
935 action++;
936 break;
937 case SPECIAL_SCROLL_UP_FAST : // Scroll up faster
938 if (Main.magnifier_mode)
939 Scroll_magnifier(0,-(Main.magnifier_height>>1));
940 else
941 Scroll_screen(0,-(Screen_height>>2));
942 action++;
943 break;
944 case SPECIAL_SCROLL_DOWN_FAST : // Scroll down faster
945 if (Main.magnifier_mode)
946 Scroll_magnifier(0,(Main.magnifier_height>>1));
947 else
948 Scroll_screen(0,(Screen_height>>2));
949 action++;
950 break;
951 case SPECIAL_SCROLL_LEFT_FAST : // Scroll left faster
952 if (Main.magnifier_mode)
953 Scroll_magnifier(-(Main.magnifier_width>>1),0);
954 else
955 Scroll_screen(-(Screen_width>>2),0);
956 action++;
957 break;
958 case SPECIAL_SCROLL_RIGHT_FAST : // Scroll right faster
959 if (Main.magnifier_mode)
960 Scroll_magnifier((Main.magnifier_width>>1),0);
961 else
962 Scroll_screen((Screen_width>>2),0);
963 action++;
964 break;
965 case SPECIAL_SCROLL_UP_SLOW : // Scroll up slower
966 if (Main.magnifier_mode)
967 Scroll_magnifier(0,-1);
968 else
969 Scroll_screen(0,-1);
970 action++;
971 break;
972 case SPECIAL_SCROLL_DOWN_SLOW : // Scroll down slower
973 if (Main.magnifier_mode)
974 Scroll_magnifier(0,1);
975 else
976 Scroll_screen(0,1);
977 action++;
978 break;
979 case SPECIAL_SCROLL_LEFT_SLOW : // Scroll left slower
980 if (Main.magnifier_mode)
981 Scroll_magnifier(-1,0);
982 else
983 Scroll_screen(-1,0);
984 action++;
985 break;
986 case SPECIAL_SCROLL_RIGHT_SLOW : // Scroll right slower
987 if (Main.magnifier_mode)
988 Scroll_magnifier(1,0);
989 else
990 Scroll_screen(1,0);
991 action++;
992 break;
993 case SPECIAL_SHOW_HIDE_CURSOR : // Show / Hide cursor
994 Hide_cursor();
995 Cursor_hidden=!Cursor_hidden;
996 Display_cursor();
997 action++;
998 break;
999 case SPECIAL_DOT_PAINTBRUSH : // Paintbrush = "."
1000 Hide_cursor();
1001 Paintbrush_shape=PAINTBRUSH_SHAPE_ROUND;
1002 Set_paintbrush_size(1,1);
1003 Change_paintbrush_shape(PAINTBRUSH_SHAPE_ROUND);
1004 Display_cursor();
1005 action++;
1006 break;
1007 case SPECIAL_CONTINUOUS_DRAW : // Continuous freehand drawing
1008 Select_button(BUTTON_DRAW,LEFT_SIDE);
1009 // ATTENTION CE TRUC EST MOCHE ET VA MERDER SI ON SE MET A UTILISER DES BOUTONS POPUPS
1010 while (Current_operation!=OPERATION_CONTINUOUS_DRAW)
1011 Select_button(BUTTON_DRAW,RIGHT_SIDE);
1012 action++;
1013 break;
1014 case SPECIAL_FLIP_X : // Flip X
1015 Hide_cursor();
1016 Flip_X_lowlevel(Brush_original_pixels, Brush_width, Brush_height);
1017 // Remap according to the last used remap table
1018 Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
1019 Display_cursor();
1020 action++;
1021 break;
1022 case SPECIAL_FLIP_Y : // Flip Y
1023 Hide_cursor();
1024 Flip_Y_lowlevel(Brush_original_pixels, Brush_width, Brush_height);
1025 // Remap according to the last used remap table
1026 Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
1027 Display_cursor();
1028 action++;
1029 break;
1030 case SPECIAL_ROTATE_90 : // 90° brush rotation
1031 Hide_cursor();
1032 Rotate_90_deg();
1033 Display_cursor();
1034 action++;
1035 break;
1036 case SPECIAL_ROTATE_180 : // 180° brush rotation
1037 Hide_cursor();
1038 Rotate_180_deg_lowlevel(Brush_original_pixels, Brush_width, Brush_height);
1039 // Remap according to the last used remap table
1040 Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
1041 Brush_offset_X=(Brush_width>>1);
1042 Brush_offset_Y=(Brush_height>>1);
1043 Display_cursor();
1044 action++;
1045 break;
1046 case SPECIAL_STRETCH : // Stretch brush
1047 Hide_cursor();
1048 Start_operation_stack(OPERATION_STRETCH_BRUSH);
1049 Display_cursor();
1050 action++;
1051 break;
1052 case SPECIAL_DISTORT : // Distort brush
1053 Hide_cursor();
1054 Start_operation_stack(OPERATION_DISTORT_BRUSH);
1055 Display_cursor();
1056 action++;
1057 break;
1058 case SPECIAL_ROTATE_ANY_ANGLE : // Rotate brush by any angle
1059 Hide_cursor();
1060 Start_operation_stack(OPERATION_ROTATE_BRUSH);
1061 Display_cursor();
1062 action++;
1063 break;
1064 case SPECIAL_BRUSH_DOUBLE:
1065 if (Paintbrush_shape==PAINTBRUSH_SHAPE_COLOR_BRUSH
1066 || Paintbrush_shape==PAINTBRUSH_SHAPE_MONO_BRUSH)
1067 {
1068 Hide_cursor();
1069 Stretch_brush(1,1,Brush_width*2,Brush_height*2);
1070 Display_cursor();
1071 }
1072 action++;
1073 break;
1074 case SPECIAL_BRUSH_DOUBLE_WIDTH:
1075 if (Paintbrush_shape==PAINTBRUSH_SHAPE_COLOR_BRUSH
1076 || Paintbrush_shape==PAINTBRUSH_SHAPE_MONO_BRUSH)
1077 {
1078 Hide_cursor();
1079 Stretch_brush(1,1,Brush_width*2,Brush_height);
1080 Display_cursor();
1081 }
1082 action++;
1083 break;
1084 case SPECIAL_BRUSH_DOUBLE_HEIGHT:
1085 if (Paintbrush_shape==PAINTBRUSH_SHAPE_COLOR_BRUSH
1086 || Paintbrush_shape==PAINTBRUSH_SHAPE_MONO_BRUSH)
1087 {
1088 Hide_cursor();
1089 Stretch_brush(1,1,Brush_width,Brush_height*2);
1090 Display_cursor();
1091 }
1092 action++;
1093 break;
1094 case SPECIAL_BRUSH_HALVE:
1095 if (Paintbrush_shape==PAINTBRUSH_SHAPE_COLOR_BRUSH
1096 || Paintbrush_shape==PAINTBRUSH_SHAPE_MONO_BRUSH)
1097 {
1098 Hide_cursor();
1099 Stretch_brush(1,1,Brush_width/2,Brush_height/2);
1100 Display_cursor();
1101 }
1102 action++;
1103 break;
1104 case SPECIAL_OUTLINE : // Outline brush
1105 Hide_cursor();
1106 Outline_brush();
1107 Display_cursor();
1108 action++;
1109 break;
1110 case SPECIAL_NIBBLE : // Nibble brush
1111 Hide_cursor();
1112 Nibble_brush();
1113 Display_cursor();
1114 action++;
1115 break;
1116 case SPECIAL_GET_BRUSH_COLORS : // Get colors from brush
1117 Get_colors_from_brush();
1118 action++;
1119 break;
1120 case SPECIAL_RECOLORIZE_BRUSH : // Recolorize brush
1121 Hide_cursor();
1122 Remap_brush();
1123 Display_cursor();
1124 action++;
1125 break;
1126 case SPECIAL_LOAD_BRUSH :
1127 Load_picture(CONTEXT_BRUSH);
1128 action++;
1129 break;
1130 case SPECIAL_SAVE_BRUSH :
1131 Save_picture(CONTEXT_BRUSH);
1132 action++;
1133 break;
1134 case SPECIAL_ZOOM_IN : // Zoom in
1135 Zoom(+1);
1136 action++;
1137 break;
1138 case SPECIAL_ZOOM_IN_MORE :
1139 Zoom(+3);
1140 action++;
1141 break;
1142 case SPECIAL_ZOOM_OUT : // Zoom out
1143 Zoom(-1);
1144 action++;
1145 break;
1146 case SPECIAL_ZOOM_OUT_MORE :
1147 Zoom(-3);
1148 action++;
1149 break;
1150
1151 case SPECIAL_CENTER_ATTACHMENT : // Center brush attachment
1152 Hide_cursor();
1153 Brush_offset_X=(Brush_width>>1);
1154 Brush_offset_Y=(Brush_height>>1);
1155 Display_cursor();
1156 action++;
1157 break;
1158 case SPECIAL_TOP_LEFT_ATTACHMENT : // Top-left brush attachment
1159 Hide_cursor();
1160 Brush_offset_X=0;
1161 Brush_offset_Y=0;
1162 Display_cursor();
1163 action++;
1164 break;
1165 case SPECIAL_TOP_RIGHT_ATTACHMENT : // Top-right brush attachment
1166 Hide_cursor();
1167 Brush_offset_X=(Brush_width-1);
1168 Brush_offset_Y=0;
1169 Display_cursor();
1170 action++;
1171 break;
1172 case SPECIAL_BOTTOM_LEFT_ATTACHMENT : // Bottom-left brush attachment
1173 Hide_cursor();
1174 Brush_offset_X=0;
1175 Brush_offset_Y=(Brush_height-1);
1176 Display_cursor();
1177 action++;
1178 break;
1179 case SPECIAL_BOTTOM_RIGHT_ATTACHMENT : // Bottom right brush attachment
1180 Hide_cursor();
1181 Brush_offset_X=(Brush_width-1);
1182 Brush_offset_Y=(Brush_height-1);
1183 Display_cursor();
1184 action++;
1185 break;
1186 case SPECIAL_EXCLUDE_COLORS_MENU : // Exclude colors menu
1187 Menu_tag_colors("Tag colors to exclude",Exclude_color,&temp,1, NULL, SPECIAL_EXCLUDE_COLORS_MENU);
1188 action++;
1189 break;
1190 case SPECIAL_INVERT_SIEVE :
1191 Invert_trame();
1192 action++;
1193 break;
1194 case SPECIAL_SHADE_MODE :
1195 Button_Shade_mode();
1196 effect_modified = 1;
1197 action++;
1198 break;
1199 case SPECIAL_SHADE_MENU :
1200 Button_Shade_menu();
1201 effect_modified = 1;
1202 action++;
1203 break;
1204 case SPECIAL_QUICK_SHADE_MODE :
1205 Button_Quick_shade_mode();
1206 effect_modified = 1;
1207 action++;
1208 break;
1209 case SPECIAL_QUICK_SHADE_MENU :
1210 Button_Quick_shade_menu();
1211 effect_modified = 1;
1212 action++;
1213 break;
1214 case SPECIAL_STENCIL_MODE :
1215 Button_Stencil_mode();
1216 effect_modified = 1;
1217 action++;
1218 break;
1219 case SPECIAL_STENCIL_MENU :
1220 Button_Stencil_menu();
1221 effect_modified = 1;
1222 action++;
1223 break;
1224 case SPECIAL_MASK_MODE :
1225 Button_Mask_mode();
1226 effect_modified = 1;
1227 action++;
1228 break;
1229 case SPECIAL_MASK_MENU :
1230 Button_Mask_menu();
1231 effect_modified = 1;
1232 action++;
1233 break;
1234 case SPECIAL_GRID_MODE :
1235 Button_Snap_mode();
1236 effect_modified = 1;
1237 action++;
1238 break;
1239 case SPECIAL_GRID_MENU :
1240 Button_Grid_menu();
1241 effect_modified = 1;
1242 action++;
1243 break;
1244 case SPECIAL_SHOW_GRID :
1245 Button_Show_grid();
1246 effect_modified = 1;
1247 action++;
1248 break;
1249 case SPECIAL_SIEVE_MODE :
1250 Button_Sieve_mode();
1251 effect_modified = 1;
1252 action++;
1253 break;
1254 case SPECIAL_SIEVE_MENU :
1255 Button_Sieve_menu();
1256 effect_modified = 1;
1257 action++;
1258 break;
1259 case SPECIAL_COLORIZE_MODE :
1260 Button_Colorize_mode();
1261 effect_modified = 1;
1262 action++;
1263 break;
1264 case SPECIAL_COLORIZE_MENU :
1265 Button_Colorize_menu();
1266 effect_modified = 1;
1267 action++;
1268 break;
1269 case SPECIAL_SMOOTH_MODE :
1270 Button_Smooth_mode();
1271 effect_modified = 1;
1272 action++;
1273 break;
1274 case SPECIAL_SMOOTH_MENU :
1275 Button_Smooth_menu();
1276 effect_modified = 1;
1277 action++;
1278 break;
1279 case SPECIAL_SMEAR_MODE :
1280 Button_Smear_mode();
1281 effect_modified = 1;
1282 action++;
1283 break;
1284 case SPECIAL_TILING_MODE :
1285 Button_Tiling_mode();
1286 effect_modified = 1;
1287 action++;
1288 break;
1289 case SPECIAL_TILING_MENU :
1290 effect_modified = 1;
1291 Button_Tiling_menu();
1292 action++;
1293 break;
1294 case SPECIAL_TILEMAP_MODE :
1295 Button_Tilemap_mode();
1296 effect_modified = 1;
1297 action++;
1298 break;
1299 case SPECIAL_TILEMAP_MENU :
1300 effect_modified = 1;
1301 Button_Tilemap_menu();
1302 action++;
1303 break;
1304 case SPECIAL_EFFECTS_OFF :
1305 Effects_off();
1306 effect_modified = 1;
1307 action++;
1308 break;
1309 case SPECIAL_TRANSPARENCY_1 :
1310 Transparency_set(1);
1311 effect_modified = 1;
1312 action++;
1313 break;
1314 case SPECIAL_TRANSPARENCY_2 :
1315 Transparency_set(2);
1316 effect_modified = 1;
1317 action++;
1318 break;
1319 case SPECIAL_TRANSPARENCY_3 :
1320 Transparency_set(3);
1321 effect_modified = 1;
1322 action++;
1323 break;
1324 case SPECIAL_TRANSPARENCY_4 :
1325 Transparency_set(4);
1326 effect_modified = 1;
1327 action++;
1328 break;
1329 case SPECIAL_TRANSPARENCY_5 :
1330 Transparency_set(5);
1331 effect_modified = 1;
1332 action++;
1333 break;
1334 case SPECIAL_TRANSPARENCY_6 :
1335 Transparency_set(6);
1336 effect_modified = 1;
1337 action++;
1338 break;
1339 case SPECIAL_TRANSPARENCY_7 :
1340 Transparency_set(7);
1341 effect_modified = 1;
1342 action++;
1343 break;
1344 case SPECIAL_TRANSPARENCY_8 :
1345 Transparency_set(8);
1346 effect_modified = 1;
1347 action++;
1348 break;
1349 case SPECIAL_TRANSPARENCY_9 :
1350 Transparency_set(9);
1351 effect_modified = 1;
1352 action++;
1353 break;
1354 case SPECIAL_TRANSPARENCY_0 :
1355 Transparency_set(0);
1356 effect_modified = 1;
1357 action++;
1358 break;
1359 case SPECIAL_ZOOM_1 :
1360 Zoom_set(-1);
1361 action++;
1362 break;
1363 case SPECIAL_ZOOM_2 :
1364 Zoom_set(0);
1365 action++;
1366 break;
1367 case SPECIAL_ZOOM_3 :
1368 Zoom_set(1);
1369 action++;
1370 break;
1371 case SPECIAL_ZOOM_4 :
1372 Zoom_set(2);
1373 action++;
1374 break;
1375 case SPECIAL_ZOOM_5 :
1376 Zoom_set(3);
1377 action++;
1378 break;
1379 case SPECIAL_ZOOM_6 :
1380 Zoom_set(4);
1381 action++;
1382 break;
1383 case SPECIAL_ZOOM_8 :
1384 Zoom_set(5);
1385 action++;
1386 break;
1387 case SPECIAL_ZOOM_10 :
1388 Zoom_set(6);
1389 action++;
1390 break;
1391 case SPECIAL_ZOOM_12 :
1392 Zoom_set(7);
1393 action++;
1394 break;
1395 case SPECIAL_ZOOM_14 :
1396 Zoom_set(8);
1397 action++;
1398 break;
1399 case SPECIAL_ZOOM_16 :
1400 Zoom_set(9);
1401 action++;
1402 break;
1403 case SPECIAL_ZOOM_18 :
1404 Zoom_set(10);
1405 action++;
1406 break;
1407 case SPECIAL_ZOOM_20 :
1408 Zoom_set(11);
1409 action++;
1410 break;
1411 case SPECIAL_LAYER1_SELECT:
1412 case SPECIAL_LAYER2_SELECT:
1413 case SPECIAL_LAYER3_SELECT:
1414 case SPECIAL_LAYER4_SELECT:
1415 case SPECIAL_LAYER5_SELECT:
1416 case SPECIAL_LAYER6_SELECT:
1417 case SPECIAL_LAYER7_SELECT:
1418 case SPECIAL_LAYER8_SELECT:
1419 Layer_activate((key_index-SPECIAL_LAYER1_SELECT)/2, LEFT_SIDE);
1420 action++;
1421 break;
1422 case SPECIAL_LAYER1_TOGGLE:
1423 case SPECIAL_LAYER2_TOGGLE:
1424 case SPECIAL_LAYER3_TOGGLE:
1425 case SPECIAL_LAYER4_TOGGLE:
1426 case SPECIAL_LAYER5_TOGGLE:
1427 case SPECIAL_LAYER6_TOGGLE:
1428 case SPECIAL_LAYER7_TOGGLE:
1429 case SPECIAL_LAYER8_TOGGLE:
1430 Layer_activate((key_index-SPECIAL_LAYER1_TOGGLE)/2, RIGHT_SIDE);
1431 action++;
1432 break;
1433
1434 case SPECIAL_REPEAT_SCRIPT:
1435 #ifdef __ENABLE_LUA__
1436 Repeat_script();
1437 action++;
1438 #endif
1439 break;
1440 case SPECIAL_RUN_SCRIPT_1:
1441 case SPECIAL_RUN_SCRIPT_2:
1442 case SPECIAL_RUN_SCRIPT_3:
1443 case SPECIAL_RUN_SCRIPT_4:
1444 case SPECIAL_RUN_SCRIPT_5:
1445 case SPECIAL_RUN_SCRIPT_6:
1446 case SPECIAL_RUN_SCRIPT_7:
1447 case SPECIAL_RUN_SCRIPT_8:
1448 case SPECIAL_RUN_SCRIPT_9:
1449 case SPECIAL_RUN_SCRIPT_10:
1450 #ifdef __ENABLE_LUA__
1451 Run_numbered_script(key_index-SPECIAL_RUN_SCRIPT_1);
1452 action++;
1453 #endif
1454 break;
1455 case SPECIAL_CYCLE_MODE:
1456 Cycling_mode= !Cycling_mode;
1457 // Restore palette
1458 if (!Cycling_mode)
1459 Set_palette(Main.palette);
1460 action++;
1461 break;
1462 case SPECIAL_HOLD_PAN:
1463 // already handled by Pan_shortcut_pressed
1464 break;
1465 }
1466 }
1467 } // End of special keys
1468
1469
1470 // Shortcut for clicks of Menu buttons.
1471 // Disable all of them when an operation is in progress
1472 if (Operation_stack_size==0)
1473 {
1474 // Some functions open windows that clear the Key variable,
1475 // so we need to use a temporary replacement.
1476 key_pressed = Key;
1477 for (button_index=0;button_index<NB_BUTTONS;button_index++)
1478 {
1479 if (Is_shortcut(key_pressed,0x100+button_index))
1480 {
1481 Layer_preview_off(&preview_is_visible);
1482 Select_button(button_index,LEFT_SIDE);
1483 prev_button_number=-1;
1484 action++;
1485 }
1486 else if (Is_shortcut(key_pressed,0x200+button_index))
1487 {
1488 Layer_preview_off(&preview_is_visible);
1489 Select_button(button_index,RIGHT_SIDE);
1490 prev_button_number=-1;
1491 action++;
1492 }
1493 }
1494 }
1495
1496 // Si on a modifié un effet, il faut rafficher le bouton des effets en
1497 // conséquence.
1498 if (effect_modified)
1499 {
1500 Hide_cursor();
1501 Draw_menu_button(BUTTON_EFFECTS, Any_effect_active());
1502 Display_cursor();
1503 }
1504 }
1505 if (action)
1506 Key=0;
1507 }
1508 else
1509 {
1510 #if defined(USE_SDL) || defined(USE_SDL2)
1511 // Removed all SDL_Delay() timing here: relying on Get_input()
1512 SDL_Delay(10);
1513 #endif
1514 }
1515
1516 // Gestion de la souris
1517
1518 Cursor_in_menu=(Mouse_Y>=Menu_Y) ||
1519 ( (Main.magnifier_mode) && (Mouse_X>=Main.separator_position) &&
1520 (Mouse_X<Main.X_zoom) );
1521
1522 if (Cursor_in_menu)
1523 {
1524 // Le curseur se trouve dans le menu
1525
1526 // On cherche sur quel bouton du menu se trouve la souris:
1527 button_index=Button_under_mouse();
1528
1529 // Si le curseur vient de changer de zone
1530 if ( (button_index!=prev_button_number)
1531 || (!Cursor_in_menu_previous)
1532 || (prev_button_number==BUTTON_CHOOSE_COL) )
1533 {
1534 // Si le curseur n'est pas sur un bouton
1535 if (button_index==-1)
1536 {
1537 if (Menu_is_visible)
1538 {
1539 // On nettoie les coordonnées
1540 Hide_cursor();
1541
1542 /*if (Gfx->Hover_effect && prev_button_number > -1 && !Buttons_Pool[prev_button_number].Pressed)
1543 Draw_menu_button(prev_button_number, BUTTON_RELEASED);
1544 */
1545 Block(18*Menu_factor_X,Menu_status_Y,192*Menu_factor_X,Menu_factor_Y<<3,MC_Light);
1546 Update_rect(18*Menu_factor_X,Menu_status_Y,192*Menu_factor_X,Menu_factor_Y<<3);
1547 Display_cursor();
1548 }
1549 }
1550 else
1551 {
1552 if ( (prev_button_number!=BUTTON_CHOOSE_COL)
1553 || (temp_color!=First_color_in_palette)
1554 || (Old_MX!=Mouse_X) || (Old_MY!=Mouse_Y) )
1555 {
1556 // Le curseur est sur un nouveau bouton
1557 if (button_index!=BUTTON_CHOOSE_COL)
1558 {
1559 Hide_cursor();
1560
1561 /*if (Gfx->Hover_effect && prev_button_number > -1 && !Buttons_Pool[prev_button_number].Pressed)
1562 Draw_menu_button(prev_button_number, BUTTON_RELEASED);
1563 */
1564
1565 Print_in_menu(Buttons_Pool[button_index].Tooltip,0);
1566
1567 /*if (Gfx->Hover_effect && !Buttons_Pool[button_index].Pressed)
1568 Draw_menu_button(button_index, BUTTON_HIGHLIGHTED);
1569 */
1570
1571 Display_cursor();
1572 }
1573 else
1574 { // Le curseur est-il sur une couleur de la palette?
1575 int color;
1576 if ((color=Pick_color_in_palette())!=-1)
1577 {
1578 Hide_cursor();
1579 Status_print_palette_color(color);
1580 Display_cursor();
1581 }
1582 else
1583 {
1584 if ( (Old_MX!=Mouse_X) || (Old_MY!=Mouse_Y) )
1585 {
1586 Hide_cursor();
1587 Block(18*Menu_factor_X,Menu_status_Y,192*Menu_factor_X,Menu_factor_Y<<3,MC_Light);
1588 Update_rect(18*Menu_factor_X,Menu_status_Y,192*Menu_factor_X,8*Menu_factor_Y);
1589 Display_cursor();
1590 }
1591 }
1592 }
1593 }
1594 }
1595 }
1596
1597 prev_button_number=button_index;
1598
1599 // Gestion des clicks
1600 if (Mouse_K)
1601 {
1602 if (Mouse_Y>=Menu_Y)
1603 {
1604 if (button_index>=0)
1605 {
1606 Layer_preview_off(&preview_is_visible);
1607 Select_button(button_index,Mouse_K);
1608 prev_button_number=-1;
1609 }
1610 }
1611 else
1612 if (Main.magnifier_mode) Move_separator();
1613 }
1614
1615 if (button_index == BUTTON_LAYER_SELECT)
1616 Layer_preview_on(&preview_is_visible);
1617 else
1618 Layer_preview_off(&preview_is_visible);
1619
1620
1621 }
1622 else // if (!Cursor_in_menu)
1623 {
1624 Layer_preview_off(&preview_is_visible);
1625 }
1626
1627 // we need to refresh that one as we may come from a sub window
1628 Cursor_in_menu=(Mouse_Y>=Menu_Y) ||
1629 ( (Main.magnifier_mode) && (Mouse_X>=Main.separator_position) &&
1630 (Mouse_X<Main.X_zoom) );
1631
1632
1633 // Le curseur se trouve dans l'image
1634 if ( (!Cursor_in_menu) && (Menu_is_visible) && (Old_MY != Mouse_Y || Old_MX != Mouse_X || Key || Mouse_K)) // On ne met les coordonnées à jour que si l'utilisateur a fait un truc
1635 {
1636 if(Cursor_in_menu_previous)
1637 {
1638 Hide_cursor();
1639 /*if (Gfx->Hover_effect && prev_button_number > -1 && !Buttons_Pool[prev_button_number].Pressed)
1640 Draw_menu_button(prev_button_number, BUTTON_RELEASED);
1641 */
1642 if ( (Current_operation!=OPERATION_COLORPICK) && (Current_operation!=OPERATION_REPLACE) )
1643 {
1644 Print_in_menu("X: Y: ",0);
1645 }
1646 else
1647 {
1648 Print_in_menu("X: Y: ( )",0);
1649 }
1650
1651 Display_cursor();
1652
1653 Cursor_in_menu_previous = 0;
1654 }
1655 }
1656
1657 if(Cursor_in_menu)
1658 {
1659 Cursor_in_menu_previous = 1;
1660 }
1661 else
1662 {
1663 blink=Operation[Current_operation][Mouse_K_unique][Operation_stack_size].Hide_cursor;
1664
1665 if (blink) Hide_cursor();
1666
1667 Operation[Current_operation][Mouse_K_unique][Operation_stack_size].Action();
1668
1669 if (blink) Display_cursor();
1670 }
1671 Old_MX=Mouse_X;
1672 Old_MY=Mouse_Y;
1673 }
1674 while (!Quitting);
1675 }
1676
1677
1678
1679
1680
1681 //////////////////////////////////////////////////////////////////////////////
1682 // différentes fonctions d'affichage utilisées dans les fenêtres //
1683 //////////////////////////////////////////////////////////////////////////////
1684
1685 //----------------------- Tracer une fenêtre d'options -----------------------
1686
1687 /**
1688 * Open a GUI window
1689 *
1690 * @param width window width (max 320)
1691 * @param height window height (max 200)
1692 * @param title window title
1693 *
1694 * The mouse must be shown before calling this function. The mouse is hidden
1695 * when the function returns.
1696 *
1697 * The function Close_window() must be called afterward.
1698 */
Open_window(word width,word height,const char * title)1699 void Open_window(word width, word height, const char * title)
1700 {
1701 size_t title_length;
1702
1703 Hide_cursor();
1704
1705 /*if (Windows_open == 0 && Gfx->Hover_effect)
1706 {
1707 if (Cursor_in_menu)
1708 {
1709 int button_index=Button_under_mouse();
1710 if (button_index > -1 && !Buttons_Pool[button_index].Pressed)
1711 Draw_menu_button(button_index, BUTTON_RELEASED);
1712 }
1713 }*/
1714
1715 Windows_open++;
1716
1717 // Limit the window size to 320x200
1718 if (width > 320 || height > 200)
1719 GFX2_Log(GFX2_WARNING, "Open_window(%d, %d, \"%s\") maximum size for windows is 320x200 !\n", width, height, title);
1720 if (width > 320)
1721 width = 320;
1722 if (height > 200)
1723 height = 200;
1724
1725 Window_width=width;
1726 Window_height=height;
1727
1728 // Positionnement de la fenêtre
1729 Window_pos_X=(Screen_width-(width*Menu_factor_X))>>1;
1730
1731 Window_pos_Y=(Screen_height-(height*Menu_factor_Y))>>1;
1732
1733 Window_draggable=1;
1734
1735 // Sauvegarde de ce que la fenêtre remplace
1736 Save_background(&(Window_background[Windows_open-1]), Window_pos_X, Window_pos_Y, width, height);
1737
1738 // Fenêtre grise
1739 Window_rectangle(2,2,width-4,height-4,MC_Window);
1740
1741 // -- Frame de la fenêtre ----- --- -- - -
1742
1743 // Frame noir puis en relief
1744 Window_display_frame_mono(0,0,width,height,MC_Black);
1745 Window_display_frame_out(1,1,width-2,height-2);
1746
1747 // Barre sous le titre
1748 Window_rectangle(3,3,width-6,10,MC_White);
1749 Window_rectangle(2,12,width-4,1,MC_Dark);
1750
1751 title_length = strlen(title);
1752 if (title_length+2 > (size_t)(width/8))
1753 title_length = width/8-2;
1754 Print_in_window_limited((width-(title_length<<3))>>1,4,title,title_length,MC_Black,MC_White);
1755
1756 if (Windows_open == 1)
1757 {
1758 Menu_is_visible_before_window=Menu_is_visible;
1759 Menu_is_visible=0;
1760 Menu_Y_before_window=Menu_Y;
1761 Menu_Y=Screen_height;
1762 Cursor_shape_before_window=Cursor_shape;
1763 Cursor_shape=CURSOR_SHAPE_ARROW;
1764 Paintbrush_hidden_before_window=Paintbrush_hidden;
1765 Paintbrush_hidden=1;
1766 if (Allow_colorcycling)
1767 {
1768 Allow_colorcycling=0;
1769 // Restore palette
1770 Set_palette(Main.palette);
1771 }
1772 Allow_drag_and_drop(0);
1773 }
1774
1775 // Initialisation des listes de boutons de la fenêtre
1776 Window_normal_button_list =NULL;
1777 Window_palette_button_list =NULL;
1778 Window_scroller_button_list=NULL;
1779 Window_special_button_list =NULL;
1780 Window_dropdown_button_list=NULL;
1781 Window_nb_buttons =0;
1782
1783 }
1784
1785 //----------------------- Fermer une fenêtre d'options -----------------------
1786
1787 /**
1788 * Close a window previously open with Open_window()
1789 *
1790 * The mouse must be shown when this functions is called.
1791 * It is hidden when the function returns.
1792 */
Close_window(void)1793 void Close_window(void)
1794 {
1795 T_Normal_button * temp1;
1796 T_Palette_button * temp2;
1797 T_Scroller_button * temp3;
1798 T_Special_button * temp4;
1799 T_Dropdown_button * temp5;
1800 T_List_button * temp6;
1801
1802 Hide_cursor();
1803
1804 while (Window_normal_button_list)
1805 {
1806 temp1=Window_normal_button_list->Next;
1807 free(Window_normal_button_list);
1808 Window_normal_button_list=temp1;
1809 }
1810 while (Window_palette_button_list)
1811 {
1812 temp2=Window_palette_button_list->Next;
1813 free(Window_palette_button_list);
1814 Window_palette_button_list=temp2;
1815 }
1816 while (Window_scroller_button_list)
1817 {
1818 temp3=Window_scroller_button_list->Next;
1819 free(Window_scroller_button_list);
1820 Window_scroller_button_list=temp3;
1821 }
1822 while (Window_special_button_list)
1823 {
1824 temp4=Window_special_button_list->Next;
1825 free(Window_special_button_list);
1826 Window_special_button_list=temp4;
1827 }
1828 while (Window_dropdown_button_list)
1829 {
1830 temp5=Window_dropdown_button_list->Next;
1831 Window_dropdown_clear_items(Window_dropdown_button_list);
1832 free(Window_dropdown_button_list);
1833 Window_dropdown_button_list=temp5;
1834 }
1835 while (Window_list_button_list)
1836 {
1837 temp6=Window_list_button_list->Next;
1838 free(Window_list_button_list);
1839 Window_list_button_list=temp6;
1840 }
1841
1842 if (Windows_open != 1)
1843 {
1844 // Restore de ce que la fenêtre cachait
1845 Restore_background(&Window_background[Windows_open-1], Window_pos_X, Window_pos_Y, Window_width, Window_height);
1846 Update_window_area(0,0,Window_width,Window_height);
1847 Windows_open--;
1848 }
1849 else
1850 {
1851 free(Window_background[Windows_open-1]);
1852 Window_background[Windows_open-1]=NULL;
1853 Windows_open--;
1854
1855 Paintbrush_hidden=Paintbrush_hidden_before_window;
1856
1857 Compute_paintbrush_coordinates();
1858
1859 Menu_Y=Menu_Y_before_window;
1860 Menu_is_visible=Menu_is_visible_before_window;
1861 Cursor_shape=Cursor_shape_before_window;
1862
1863 Check_menu_mode();
1864 Display_all_screen();
1865 Display_menu();
1866 Allow_colorcycling=1;
1867 Allow_drag_and_drop(1);
1868 }
1869
1870 Key=0;
1871 Mouse_K=0;
1872
1873 Old_MX = -1;
1874 Old_MY = -1;
1875
1876 }
1877
1878
1879 //---------------- Dessiner un bouton normal dans une fenêtre ----------------
1880 // undersc_letter is 0 for no underscore, 1-indexed array index otherwise
Window_draw_normal_bouton(word x_pos,word y_pos,word width,word height,const char * title,byte undersc_letter,byte clickable)1881 void Window_draw_normal_bouton(word x_pos,word y_pos,word width,word height,
1882 const char * title,byte undersc_letter,byte clickable)
1883 {
1884 byte title_color;
1885 word text_x_pos,text_y_pos;
1886
1887 if (clickable)
1888 {
1889 Window_display_frame_out(x_pos,y_pos,width,height);
1890 Window_display_frame_generic(x_pos-1,y_pos-1,width+2,height+2,MC_Black,MC_Black,MC_Dark,MC_Dark,MC_Dark);
1891 title_color=MC_Black;
1892 }
1893 else
1894 {
1895 Window_display_frame_out(x_pos,y_pos,width,height);
1896 Window_display_frame_mono(x_pos-1,y_pos-1,width+2,height+2,MC_Light);
1897 title_color=MC_Dark;
1898 }
1899
1900 text_x_pos=x_pos+( (width-(strlen(title)<<3)+1) >>1 );
1901 text_y_pos=y_pos+((height-7)>>1);
1902 Print_in_window(text_x_pos,text_y_pos,title,title_color,MC_Light);
1903
1904 #if !defined(NO_KEYBOARD)
1905 if (undersc_letter)
1906 Window_rectangle(text_x_pos+((undersc_letter-1)<<3),
1907 text_y_pos+8,8,1,MC_Dark);
1908 #else
1909 (void)undersc_letter;
1910 #endif
1911 }
1912
1913
1914 // -- Button normal enfoncé dans la fenêtre --
Window_select_normal_button(word x_pos,word y_pos,word width,word height)1915 void Window_select_normal_button(word x_pos,word y_pos,word width,word height)
1916 {
1917 Window_display_frame_generic(x_pos,y_pos,width,height,MC_Dark,MC_Black,MC_Dark,MC_Dark,MC_Black);
1918 Update_window_area(x_pos, y_pos, width, height);
1919 }
1920
1921 // -- Button normal désenfoncé dans la fenêtre --
Window_unselect_normal_button(word x_pos,word y_pos,word width,word height)1922 void Window_unselect_normal_button(word x_pos,word y_pos,word width,word height)
1923 {
1924 Window_display_frame_out(x_pos,y_pos,width,height);
1925 Update_window_area(x_pos, y_pos, width, height);
1926 }
1927
1928
1929 //--------------- Dessiner un bouton palette dans une fenêtre ----------------
Window_draw_palette_bouton(word x_pos,word y_pos)1930 void Window_draw_palette_bouton(word x_pos,word y_pos)
1931 {
1932 word color;
1933
1934 for (color=0; color<=255; color++)
1935 Window_rectangle( ((color >> 4)*10)+x_pos+6,((color & 15)*5)+y_pos+3,5,5,color);
1936
1937 Window_display_frame(x_pos,y_pos,164,86);
1938 }
1939
1940
1941 // -------------------- Effacer les TAGs sur les palette ---------------------
1942 // Cette fonct° ne sert plus que lorsqu'on efface les tags dans le menu Spray.
Window_clear_tags(void)1943 void Window_clear_tags(void)
1944 {
1945 word origin_x;
1946 word origin_y;
1947 word x_pos;
1948 word window_x_pos;
1949 //word window_y_pos;
1950
1951 origin_x=Window_palette_button_list->Pos_X+3;
1952 origin_y=Window_palette_button_list->Pos_Y+3;
1953 for (x_pos=0,window_x_pos=origin_x;x_pos<16;x_pos++,window_x_pos+=10)
1954 Window_rectangle(window_x_pos,origin_y,3,80,MC_Light);
1955 Update_window_area(origin_x,origin_y,160,80);
1956 }
1957
1958
1959 // ---- Tracer les TAGs sur les palettes du menu Palette ou du menu Shade ----
Tag_color_range(byte start,byte end)1960 void Tag_color_range(byte start,byte end)
1961 {
1962 word origin_x;
1963 word origin_y;
1964 //word x_pos;
1965 word y_pos;
1966 //word window_x_pos;
1967 word window_y_pos;
1968 word index;
1969
1970 // On efface les anciens TAGs
1971 for (index=0;index<=start;index++)
1972 Window_rectangle(Window_palette_button_list->Pos_X+3+((index>>4)*10),
1973 Window_palette_button_list->Pos_Y+3+((index&15)* 5),
1974 3,5,MC_Light);
1975
1976 for (index=end;index<256;index++)
1977 Window_rectangle(Window_palette_button_list->Pos_X+3+((index>>4)*10),
1978 Window_palette_button_list->Pos_Y+3+((index&15)* 5),
1979 3,5,MC_Light);
1980
1981 // On affiche le 1er TAG
1982 origin_x=(Window_palette_button_list->Pos_X+3)+(start>>4)*10;
1983 origin_y=(Window_palette_button_list->Pos_Y+3)+(start&15)* 5;
1984 for (y_pos=0,window_y_pos=origin_y ;y_pos<5;y_pos++,window_y_pos++)
1985 Pixel_in_window(origin_x ,window_y_pos,MC_Black);
1986 for (y_pos=0,window_y_pos=origin_y+1;y_pos<3;y_pos++,window_y_pos++)
1987 Pixel_in_window(origin_x+1,window_y_pos,MC_Black);
1988 Pixel_in_window(origin_x+2,origin_y+2,MC_Black);
1989
1990 if (start!=end)
1991 {
1992 // On complète le 1er TAG
1993 Pixel_in_window(origin_x+1,origin_y+4,MC_Black);
1994
1995 // On affiche le 2ème TAG
1996 origin_x=(Window_palette_button_list->Pos_X+3)+(end>>4)*10;
1997 origin_y=(Window_palette_button_list->Pos_Y+3)+(end&15)* 5;
1998 for (y_pos=0,window_y_pos=origin_y; y_pos<5; y_pos++,window_y_pos++)
1999 Pixel_in_window(origin_x ,window_y_pos,MC_Black);
2000 for (y_pos=0,window_y_pos=origin_y; y_pos<4; y_pos++,window_y_pos++)
2001 Pixel_in_window(origin_x+1,window_y_pos,MC_Black);
2002 Pixel_in_window(origin_x+2,origin_y+2,MC_Black);
2003
2004 // On TAG toutes les couleurs intermédiaires
2005 for (index=start+1;index<end;index++)
2006 {
2007 Window_rectangle(Window_palette_button_list->Pos_X+3+((index>>4)*10),
2008 Window_palette_button_list->Pos_Y+3+((index&15)* 5),
2009 2,5,MC_Black);
2010 // On efface l'éventuelle pointe d'une ancienne extrémité de l'intervalle
2011 Pixel_in_window(Window_palette_button_list->Pos_X+5+((index>>4)*10),
2012 Window_palette_button_list->Pos_Y+5+((index&15)* 5),
2013 MC_Light);
2014 }
2015
2016
2017 }
2018
2019 Update_window_area(Window_palette_button_list->Pos_X+3,Window_palette_button_list->Pos_Y+3,12*16,5*16);
2020
2021 }
2022
2023
2024 //------------------ Dessiner un scroller dans une fenêtre -------------------
2025
Compute_slider_cursor_length(T_Scroller_button * button)2026 void Compute_slider_cursor_length(T_Scroller_button * button)
2027 {
2028 if (button->Nb_elements>button->Nb_visibles)
2029 {
2030 button->Cursor_length=(button->Nb_visibles*(button->Length-24))/button->Nb_elements;
2031 if (!(button->Cursor_length))
2032 button->Cursor_length=1;
2033 }
2034 else
2035 {
2036 button->Cursor_length=button->Length-24;
2037 }
2038 }
2039
Window_draw_slider(T_Scroller_button * button)2040 void Window_draw_slider(T_Scroller_button * button)
2041 {
2042 word slider_position;
2043
2044 if (button->Is_horizontal)
2045 {
2046 slider_position=button->Pos_X+12;
2047
2048 Window_rectangle(slider_position,
2049 button->Pos_Y,
2050 button->Length-24,11,MC_Black/*MC_Dark*/);
2051
2052 if (button->Nb_elements > button->Nb_visibles)
2053 {
2054 int pos = ( (button->Length - 24 - button->Cursor_length) * button->Position
2055 + (button->Nb_elements - button->Nb_visibles) / 2)
2056 / (button->Nb_elements - button->Nb_visibles);
2057 if ((pos + button->Cursor_length) > (button->Length - 24))
2058 pos = button->Length - 24 - button->Cursor_length;
2059 slider_position += pos;
2060 }
2061
2062 Window_rectangle(slider_position,
2063 button->Pos_Y,
2064 button->Cursor_length,11,MC_OnBlack/*MC_White*/);
2065
2066 Update_window_area(button->Pos_X,
2067 button->Pos_Y,
2068 button->Length,11);
2069 }
2070 else
2071 {
2072 slider_position=button->Pos_Y+12;
2073
2074 Window_rectangle(button->Pos_X,
2075 slider_position,
2076 11,button->Length-24,MC_Black/*MC_Dark*/);
2077
2078 if (button->Nb_elements > button->Nb_visibles)
2079 {
2080 int pos = ( (button->Length - 24 - button->Cursor_length) * button->Position
2081 + (button->Nb_elements - button->Nb_visibles) / 2)
2082 / (button->Nb_elements - button->Nb_visibles);
2083 if ((pos + button->Cursor_length) > (button->Length - 24))
2084 pos = button->Length - 24 - button->Cursor_length;
2085 slider_position += pos;
2086 }
2087
2088 Window_rectangle(button->Pos_X,
2089 slider_position,
2090 11,button->Cursor_length,MC_OnBlack/*MC_White*/);
2091
2092 Update_window_area(button->Pos_X,
2093 button->Pos_Y,
2094 11,button->Length);
2095 }
2096 }
2097
Window_draw_scroller_button(T_Scroller_button * button)2098 void Window_draw_scroller_button(T_Scroller_button * button)
2099 {
2100 if (button->Is_horizontal)
2101 {
2102 Window_display_frame_generic(button->Pos_X-1,button->Pos_Y-1,button->Length+2,13,MC_Black,MC_Black,MC_Dark,MC_Dark,MC_Dark);
2103 Window_display_frame_mono(button->Pos_X+11,button->Pos_Y-1,button->Length-22,13,MC_Black);
2104 Window_display_frame_out(button->Pos_X,button->Pos_Y,11,11);
2105 Window_display_frame_out(button->Pos_X+button->Length-11,button->Pos_Y,11,11);
2106 Print_in_window(button->Pos_X+2,button->Pos_Y+2,"\033",MC_Black,MC_Light);
2107 Print_in_window(button->Pos_X+button->Length-9,button->Pos_Y+2,"\032",MC_Black,MC_Light);
2108 }
2109 else
2110 {
2111 Window_display_frame_generic(button->Pos_X-1,button->Pos_Y-1,13,button->Length+2,MC_Black,MC_Black,MC_Dark,MC_Dark,MC_Dark);
2112 Window_display_frame_mono(button->Pos_X-1,button->Pos_Y+11,13,button->Length-22,MC_Black);
2113 Window_display_frame_out(button->Pos_X,button->Pos_Y,11,11);
2114 Window_display_frame_out(button->Pos_X,button->Pos_Y+button->Length-11,11,11);
2115 Print_in_window(button->Pos_X+2,button->Pos_Y+2,"\030",MC_Black,MC_Light);
2116 Print_in_window(button->Pos_X+2,button->Pos_Y+button->Length-9,"\031",MC_Black,MC_Light);
2117 }
2118 Window_draw_slider(button);
2119 }
2120
2121
2122 //--------------- Dessiner une zone de saisie dans une fenêtre ---------------
2123
Window_draw_input_bouton(word x_pos,word y_pos,word width_in_characters)2124 void Window_draw_input_bouton(word x_pos,word y_pos,word width_in_characters)
2125 {
2126 Window_display_frame_in(x_pos,y_pos,(width_in_characters<<3)+3,11);
2127 }
2128
2129
2130 //------------ Modifier le contenu (caption) d'une zone de saisie ------------
2131
Window_input_content(T_Special_button * button,const char * content)2132 void Window_input_content(T_Special_button * button, const char * content)
2133 {
2134 Print_in_window_limited(button->Pos_X+2,button->Pos_Y+2,content,button->Width/8,MC_Black,MC_Light);
2135 }
2136
2137 //------------ Effacer le contenu (caption) d'une zone de saisie ------------
2138
Window_clear_input_button(T_Special_button * button)2139 void Window_clear_input_button(T_Special_button * button)
2140 {
2141 Window_rectangle(button->Pos_X+2,button->Pos_Y+2,(button->Width/8)*8,8,MC_Light);
2142 Update_window_area(button->Pos_X+2,button->Pos_Y+2,button->Width/8*8,8);
2143 }
2144
2145
2146 //------ Rajout d'un bouton à la liste de ceux présents dans la fenêtre ------
2147 // undersc_letter is 0 for no underscore, 1-indexed array index otherwise
Window_set_normal_button(word x_pos,word y_pos,word width,word height,const char * title,byte undersc_letter,byte clickable,word shortcut)2148 T_Normal_button * Window_set_normal_button(word x_pos, word y_pos,
2149 word width, word height,
2150 const char * title, byte undersc_letter,
2151 byte clickable, word shortcut)
2152 {
2153 T_Normal_button * temp=NULL;
2154
2155 Window_nb_buttons++;
2156
2157 if (clickable)
2158 {
2159 temp=(T_Normal_button *)malloc(sizeof(T_Normal_button));
2160 temp->Number =Window_nb_buttons;
2161 temp->Pos_X =x_pos;
2162 temp->Pos_Y =y_pos;
2163 temp->Width =width;
2164 temp->Height =height;
2165 temp->Clickable=clickable;
2166 temp->Shortcut =shortcut;
2167 temp->Repeatable=0;
2168
2169 temp->Next=Window_normal_button_list;
2170 Window_normal_button_list=temp;
2171 }
2172
2173 Window_draw_normal_bouton(x_pos,y_pos,width,height,title,undersc_letter,clickable);
2174 return temp;
2175 }
2176 //------ Rajout d'un bouton à la liste de ceux présents dans la fenêtre ------
2177 // undersc_letter is 0 for no underscore, 1-indexed array index otherwise
Window_set_repeatable_button(word x_pos,word y_pos,word width,word height,const char * title,byte undersc_letter,byte clickable,word shortcut)2178 T_Normal_button * Window_set_repeatable_button(word x_pos, word y_pos,
2179 word width, word height,
2180 const char * title, byte undersc_letter,
2181 byte clickable, word shortcut)
2182 {
2183 T_Normal_button * temp=NULL;
2184
2185 Window_nb_buttons++;
2186
2187 if (clickable)
2188 {
2189 temp=(T_Normal_button *)malloc(sizeof(T_Normal_button));
2190 temp->Number =Window_nb_buttons;
2191 temp->Pos_X =x_pos;
2192 temp->Pos_Y =y_pos;
2193 temp->Width =width;
2194 temp->Height =height;
2195 temp->Shortcut=shortcut;
2196 temp->Repeatable=1;
2197
2198 temp->Next=Window_normal_button_list;
2199 Window_normal_button_list=temp;
2200 }
2201
2202 Window_draw_normal_bouton(x_pos,y_pos,width,height,title,undersc_letter,clickable);
2203 return temp;
2204 }
2205
Window_set_palette_button(word x_pos,word y_pos)2206 T_Palette_button * Window_set_palette_button(word x_pos, word y_pos)
2207 {
2208 T_Palette_button * temp;
2209
2210 temp=(T_Palette_button *)malloc(sizeof(T_Palette_button));
2211 temp->Number =++Window_nb_buttons;
2212 temp->Pos_X =x_pos;
2213 temp->Pos_Y =y_pos;
2214
2215 temp->Next=Window_palette_button_list;
2216 Window_palette_button_list=temp;
2217
2218 Window_draw_palette_bouton(x_pos,y_pos);
2219 return temp;
2220 }
2221
2222
Window_set_scroller_button(word x_pos,word y_pos,word height,word nb_elements,word nb_elements_visible,word initial_position)2223 T_Scroller_button * Window_set_scroller_button(word x_pos, word y_pos,
2224 word height,
2225 word nb_elements,
2226 word nb_elements_visible,
2227 word initial_position)
2228 {
2229 T_Scroller_button * temp;
2230
2231 temp=(T_Scroller_button *)malloc(sizeof(T_Scroller_button));
2232 temp->Number =++Window_nb_buttons;
2233 temp->Is_horizontal =0;
2234 temp->Pos_X =x_pos;
2235 temp->Pos_Y =y_pos;
2236 temp->Length =height;
2237 temp->Nb_elements =nb_elements;
2238 temp->Nb_visibles =nb_elements_visible;
2239 temp->Position =initial_position;
2240 Compute_slider_cursor_length(temp);
2241
2242 temp->Next=Window_scroller_button_list;
2243 Window_scroller_button_list=temp;
2244
2245 Window_draw_scroller_button(temp);
2246 return temp;
2247 }
2248
Window_set_horizontal_scroller_button(word x_pos,word y_pos,word width,word nb_elements,word nb_elements_visible,word initial_position)2249 T_Scroller_button * Window_set_horizontal_scroller_button(word x_pos, word y_pos,
2250 word width,
2251 word nb_elements,
2252 word nb_elements_visible,
2253 word initial_position)
2254 {
2255 T_Scroller_button * temp;
2256
2257 temp=(T_Scroller_button *)malloc(sizeof(T_Scroller_button));
2258 temp->Number =++Window_nb_buttons;
2259 temp->Is_horizontal =1;
2260 temp->Pos_X =x_pos;
2261 temp->Pos_Y =y_pos;
2262 temp->Length =width;
2263 temp->Nb_elements =nb_elements;
2264 temp->Nb_visibles =nb_elements_visible;
2265 temp->Position =initial_position;
2266 Compute_slider_cursor_length(temp);
2267
2268 temp->Next=Window_scroller_button_list;
2269 Window_scroller_button_list=temp;
2270
2271 Window_draw_scroller_button(temp);
2272 return temp;
2273 }
2274
Window_set_special_button(word x_pos,word y_pos,word width,word height,word shortcut)2275 T_Special_button * Window_set_special_button(word x_pos,word y_pos,word width,word height, word shortcut)
2276 {
2277 T_Special_button * temp;
2278
2279 temp=(T_Special_button *)malloc(sizeof(T_Special_button));
2280 temp->Number =++Window_nb_buttons;
2281 temp->Pos_X =x_pos;
2282 temp->Pos_Y =y_pos;
2283 temp->Width =width;
2284 temp->Height =height;
2285 temp->Shortcut =shortcut;
2286
2287 temp->Next=Window_special_button_list;
2288 Window_special_button_list=temp;
2289 return temp;
2290 }
2291
2292
Window_set_input_button_s(word x_pos,word y_pos,word width_in_characters,word shortcut)2293 T_Special_button * Window_set_input_button_s(word x_pos,word y_pos,word width_in_characters, word shortcut)
2294 {
2295 T_Special_button *temp;
2296 temp=Window_set_special_button(x_pos,y_pos,(width_in_characters<<3)+3,11,shortcut);
2297 Window_draw_input_bouton(x_pos,y_pos,width_in_characters);
2298 return temp;
2299 }
2300
Window_set_input_button(word x_pos,word y_pos,word width_in_characters)2301 T_Special_button * Window_set_input_button(word x_pos,word y_pos,word width_in_characters)
2302 {
2303 return Window_set_input_button_s(x_pos, y_pos, width_in_characters, 0);
2304 }
2305
Window_set_dropdown_button(word x_pos,word y_pos,word width,word height,word dropdown_width,const char * label,byte display_choice,byte display_centered,byte display_arrow,byte active_button,byte bottom_up)2306 T_Dropdown_button * Window_set_dropdown_button(word x_pos,word y_pos,word width,word height,word dropdown_width,const char *label,byte display_choice,byte display_centered,byte display_arrow,byte active_button, byte bottom_up)
2307 {
2308 T_Dropdown_button *temp;
2309
2310 temp=(T_Dropdown_button *)malloc(sizeof(T_Dropdown_button));
2311 temp->Number =++Window_nb_buttons;
2312 temp->Pos_X =x_pos;
2313 temp->Pos_Y =y_pos;
2314 temp->Width =width;
2315 temp->Height =height;
2316 temp->Display_choice =display_choice;
2317 temp->First_item=NULL;
2318 temp->Dropdown_width=dropdown_width?dropdown_width:width;
2319 temp->Display_centered=display_centered;
2320 temp->Display_arrow=display_arrow;
2321 temp->Active_button=active_button;
2322 temp->Bottom_up=bottom_up;
2323
2324 temp->Next=Window_dropdown_button_list;
2325 Window_dropdown_button_list=temp;
2326 Window_draw_normal_bouton(x_pos,y_pos,width,height,"",0,1);
2327 if (label && label[0])
2328 Print_in_window(temp->Pos_X+2,temp->Pos_Y+(temp->Height-7)/2,label,MC_Black,MC_Light);
2329 if (display_arrow)
2330 Window_display_icon_sprite(temp->Pos_X+temp->Width-10,temp->Pos_Y+(temp->Height-7)/2,ICON_DROPDOWN);
2331
2332 return temp;
2333 }
2334
2335 // Ajoute un choix à une dropdown. Le libellé est seulement référencé,
2336 // il doit pointer sur une zone qui doit être encore valide à la fermeture
2337 // de la fenêtre (comprise).
Window_dropdown_add_item(T_Dropdown_button * dropdown,word btn_number,const char * label)2338 void Window_dropdown_add_item(T_Dropdown_button * dropdown, word btn_number, const char *label)
2339 {
2340 T_Dropdown_choice *temp;
2341 T_Dropdown_choice *last;
2342
2343 temp=(T_Dropdown_choice *)malloc(sizeof(T_Dropdown_choice));
2344 temp->Number =btn_number;
2345 temp->Label=label;
2346 temp->Next=NULL;
2347
2348 last=dropdown->First_item;
2349 if (last)
2350 {
2351 // On cherche le dernier élément
2352 for (;last->Next;last=last->Next)
2353 ;
2354 last->Next=temp;
2355 }
2356 else
2357 {
2358 dropdown->First_item=temp;
2359 }
2360 }
2361
2362 // ------------- Suppression de tous les choix d'une dropdown ---------
Window_dropdown_clear_items(T_Dropdown_button * dropdown)2363 void Window_dropdown_clear_items(T_Dropdown_button * dropdown)
2364 {
2365 T_Dropdown_choice * next_choice;
2366 while (dropdown->First_item)
2367 {
2368 next_choice=dropdown->First_item->Next;
2369 free(dropdown->First_item);
2370 dropdown->First_item=next_choice;
2371 }
2372 }
2373
2374 //----------------------- Create a List control -----------------------
2375 // These controls are special. They work over two controls previously created:
2376 // - entry_button is the textual area where the list values will be printed.
2377 // - scroller is a scroller button attached to it
2378
Window_set_list_button(T_Special_button * entry_button,T_Scroller_button * scroller,Func_draw_list_item draw_list_item,byte color_index)2379 T_List_button * Window_set_list_button(T_Special_button * entry_button, T_Scroller_button * scroller, Func_draw_list_item draw_list_item, byte color_index)
2380 {
2381 T_List_button *temp;
2382
2383 temp=(T_List_button *)malloc(sizeof(T_List_button));
2384 temp->Number =++Window_nb_buttons;
2385 temp->List_start = 0;
2386 temp->Cursor_position = 0;
2387 temp->Entry_button = entry_button;
2388 temp->Scroller = scroller;
2389 temp->Draw_list_item = draw_list_item;
2390 temp->Color_index = color_index;
2391
2392 temp->Next=Window_list_button_list;
2393 Window_list_button_list=temp;
2394 return temp;
2395 }
2396
Window_redraw_list(T_List_button * list)2397 void Window_redraw_list(T_List_button * list)
2398 {
2399 int i;
2400
2401 for (i=Min(list->Scroller->Nb_visibles-1, list->Scroller->Nb_elements-1); i>=0; i--)
2402 {
2403 list->Draw_list_item(
2404 list->Entry_button->Pos_X,
2405 list->Entry_button->Pos_Y + i * 8,
2406 list->List_start + i,
2407 i == list->Cursor_position);
2408 }
2409 // Remaining rectangle under list
2410 i=list->Scroller->Nb_visibles-list->Scroller->Nb_elements;
2411 if (i>0)
2412 {
2413 byte color;
2414 color = list->Color_index == 0 ? MC_Black :
2415 (list->Color_index == 1 ? MC_Dark :
2416 (list->Color_index == 2 ? MC_Light : MC_White));
2417
2418 Window_rectangle(
2419 list->Entry_button->Pos_X,
2420 list->Entry_button->Pos_Y+list->Scroller->Nb_elements*8,
2421 list->Entry_button->Width,
2422 i*8,
2423 color);
2424 }
2425 }
2426
2427 //----------------------- Ouverture d'un pop-up -----------------------
2428
2429 /**
2430 * Open a popup window
2431 *
2432 * @param x_pos left position
2433 * @param y_pos top position
2434 * @param width width of the popup (max 320)
2435 * @param height height of the popup (max 200)
2436 *
2437 * The mouse cursor must be shown when calling this function. When the
2438 * function returns it is hidden.
2439 *
2440 * Popup windows are managed as sub-windows. They have their own
2441 * event loop, widget can be added inside, etc.
2442 * The differences with plain windows are almost only graphical :
2443 * - Possibility of fixing position (x_pos, y_pos)
2444 * - No title
2445 * - No 3D border, but a flat white border.
2446 */
Open_popup(word x_pos,word y_pos,word width,word height)2447 void Open_popup(word x_pos, word y_pos, word width,word height)
2448 {
2449 Windows_open++;
2450
2451 if (height*Menu_factor_Y > Screen_height)
2452 height = Screen_height/Menu_factor_Y;
2453 if (y_pos + height*Menu_factor_Y > Screen_height) // fix dropdown that would get bellow the screen
2454 y_pos = Screen_height - height*Menu_factor_Y;
2455 if (x_pos + width*Menu_factor_X > Screen_width)
2456 x_pos = Screen_width - width*Menu_factor_X;
2457
2458 Window_width=width;
2459 Window_height=height;
2460 Window_pos_X=x_pos;
2461 Window_pos_Y=y_pos;
2462 Window_draggable=0;
2463
2464 // Sauvegarde de ce que la fenêtre remplace
2465 Save_background(&(Window_background[Windows_open-1]), Window_pos_X, Window_pos_Y, width, height);
2466
2467 /*
2468 // Fenêtre grise
2469 Window_rectangle(1,1,width-2,height-2,MC_Light);
2470
2471 // Frame noir puis en relief
2472 Window_display_frame_mono(0,0,width,height,MC_White);
2473 */
2474 if (Windows_open == 1)
2475 {
2476 Menu_is_visible_before_window=Menu_is_visible;
2477 Menu_is_visible=0;
2478 Menu_Y_before_window=Menu_Y;
2479 Menu_Y=Screen_height;
2480 Cursor_shape_before_window=Cursor_shape;
2481 Cursor_shape=CURSOR_SHAPE_ARROW;
2482 Paintbrush_hidden_before_window=Paintbrush_hidden;
2483 Paintbrush_hidden=1;
2484 }
2485
2486 // Initialisation des listes de boutons de la fenêtre
2487 Window_normal_button_list =NULL;
2488 Window_palette_button_list =NULL;
2489 Window_scroller_button_list=NULL;
2490 Window_special_button_list =NULL;
2491 Window_dropdown_button_list =NULL;
2492 Window_nb_buttons =0;
2493
2494 }
2495
2496 //----------------------- Fermer une fenêtre d'options -----------------------
2497
Close_popup(void)2498 void Close_popup(void)
2499 // Lors de l'appel à cette procedure, la souris doit être affichée.
2500 // En sortie de cette procedure, la souris est effacée.
2501 {
2502 T_Normal_button * temp1;
2503 T_Palette_button * temp2;
2504 T_Scroller_button * temp3;
2505 T_Special_button * temp4;
2506 T_Dropdown_button * temp5;
2507 T_List_button * temp6;
2508
2509 Hide_cursor();
2510
2511 while (Window_normal_button_list)
2512 {
2513 temp1=Window_normal_button_list->Next;
2514 free(Window_normal_button_list);
2515 Window_normal_button_list=temp1;
2516 }
2517 while (Window_palette_button_list)
2518 {
2519 temp2=Window_palette_button_list->Next;
2520 free(Window_palette_button_list);
2521 Window_palette_button_list=temp2;
2522 }
2523 while (Window_scroller_button_list)
2524 {
2525 temp3=Window_scroller_button_list->Next;
2526 free(Window_scroller_button_list);
2527 Window_scroller_button_list=temp3;
2528 }
2529 while (Window_special_button_list)
2530 {
2531 temp4=Window_special_button_list->Next;
2532 free(Window_special_button_list);
2533 Window_special_button_list=temp4;
2534 }
2535 while (Window_dropdown_button_list)
2536 {
2537 Window_dropdown_clear_items(Window_dropdown_button_list);
2538 temp5=Window_dropdown_button_list->Next;
2539 free(Window_dropdown_button_list);
2540 Window_dropdown_button_list=temp5;
2541 }
2542 while (Window_list_button_list)
2543 {
2544 temp6=Window_list_button_list->Next;
2545 free(Window_list_button_list);
2546 Window_list_button_list=temp6;
2547 }
2548
2549 if (Windows_open != 1)
2550 {
2551 // Restore de ce que la fenêtre cachait
2552 Restore_background(&Window_background[Windows_open-1], Window_pos_X, Window_pos_Y, Window_width, Window_height);
2553 Update_window_area(0,0,Window_width,Window_height);
2554 Windows_open--;
2555 }
2556 else
2557 {
2558 free(Window_background[Windows_open-1]);
2559 Window_background[Windows_open-1] = NULL;
2560 Windows_open--;
2561
2562 Paintbrush_hidden=Paintbrush_hidden_before_window;
2563
2564 Compute_paintbrush_coordinates();
2565
2566 Menu_Y=Menu_Y_before_window;
2567 Menu_is_visible=Menu_is_visible_before_window;
2568 Cursor_shape=Cursor_shape_before_window;
2569
2570 Display_all_screen();
2571 Display_menu();
2572 }
2573
2574 Key=0;
2575 Mouse_K=0;
2576
2577 Old_MX = -1;
2578 Old_MY = -1;
2579
2580
2581 }
2582 //////////////////////////////////////////////////////////////////////////////
2583 // //
2584 // Mini-MOTEUR utilisé dans les fenêtres (menus des boutons...) //
2585 // //
2586 //////////////////////////////////////////////////////////////////////////////
2587
2588
2589 // -- Indique si on a cliqué dans une zone définie par deux points extremes --
Window_click_in_rectangle(short start_x,short start_y,short end_x,short end_y)2590 byte Window_click_in_rectangle(short start_x,short start_y,short end_x,short end_y)
2591 {
2592 short x_pos,y_pos;
2593
2594 x_pos=((short)Mouse_X-Window_pos_X)/Menu_factor_X;
2595 y_pos=((short)Mouse_Y-Window_pos_Y)/Menu_factor_Y;
2596
2597 return ((x_pos>=start_x) &&
2598 (y_pos>=start_y) &&
2599 (x_pos<=end_x) &&
2600 (y_pos<=end_y));
2601 }
2602
2603
2604 // --- Attend que l'on clique dans la palette pour renvoyer la couleur choisie
2605 // ou bien renvoie -1 si on a annulé l'action pas click-droit ou Escape ------
Wait_click_in_palette(T_Palette_button * button)2606 short Wait_click_in_palette(T_Palette_button * button)
2607 {
2608 short start_x=button->Pos_X+5;
2609 short start_y=button->Pos_Y+3;
2610 short end_x =button->Pos_X+160;
2611 short end_y =button->Pos_Y+82;
2612 byte selected_color;
2613 byte old_hide_cursor;
2614 byte old_main_magnifier_mode;
2615
2616 Hide_cursor();
2617 old_hide_cursor=Cursor_hidden;
2618 old_main_magnifier_mode=Main.magnifier_mode;
2619 Main.magnifier_mode=0;
2620 Cursor_hidden=0;
2621 Cursor_shape=CURSOR_SHAPE_TARGET;
2622 Display_cursor();
2623
2624 for (;;)
2625 {
2626 while (Get_input(20))
2627 ;
2628
2629 if (Mouse_K==LEFT_SIDE)
2630 {
2631 if (Window_click_in_rectangle(start_x,start_y,end_x,end_y))
2632 {
2633 Hide_cursor();
2634 selected_color=(((Mouse_X-Window_pos_X)/Menu_factor_X)-(button->Pos_X+2)) / 10 * 16 +
2635 (((Mouse_Y-Window_pos_Y)/Menu_factor_Y)-(button->Pos_Y+3)) / 5;
2636 Cursor_shape=CURSOR_SHAPE_ARROW;
2637 Cursor_hidden=old_hide_cursor;
2638 Main.magnifier_mode=old_main_magnifier_mode;
2639 Display_cursor();
2640 return selected_color;
2641 }
2642 if ((Mouse_X<Window_pos_X) || (Mouse_Y<Window_pos_Y) ||
2643 (Mouse_X>=Window_pos_X+(Window_width*Menu_factor_X)) ||
2644 (Mouse_Y>=Window_pos_Y+(Window_height*Menu_factor_Y)) )
2645 {
2646 Hide_cursor();
2647 selected_color=Read_pixel(Mouse_X,Mouse_Y);
2648 Cursor_shape=CURSOR_SHAPE_ARROW;
2649 Cursor_hidden=old_hide_cursor;
2650 Main.magnifier_mode=old_main_magnifier_mode;
2651 Display_cursor();
2652 return selected_color;
2653 }
2654 }
2655
2656 if ((Mouse_K==RIGHT_SIDE) || (Key==KEY_ESC))
2657 {
2658 Hide_cursor();
2659 Cursor_shape=CURSOR_SHAPE_ARROW;
2660 Cursor_hidden=old_hide_cursor;
2661 Main.magnifier_mode=old_main_magnifier_mode;
2662 Display_cursor();
2663 return -1;
2664 }
2665 }
2666 }
2667
2668
2669
2670 // -------------- Récupération d'une couleur derrière un menu ----------------
Get_color_behind_window(byte * color,byte * click)2671 void Get_color_behind_window(byte * color, byte * click)
2672 {
2673 short old_x=-1;
2674 short old_y=-1;
2675 short index;
2676 short a,b,c,d; // Variables temporaires et multitâches...
2677 byte * buffer = NULL;
2678 char str[25];
2679 byte cursor_was_hidden;
2680
2681
2682 Hide_cursor();
2683
2684 cursor_was_hidden=Cursor_hidden;
2685 Cursor_hidden=0;
2686
2687 Save_background(&buffer,Window_pos_X,Window_pos_Y,Window_width,Window_height);
2688 a=Menu_Y;
2689 Menu_Y=Menu_Y_before_window;
2690 b=Menu_is_visible;
2691 Menu_is_visible=Menu_is_visible_before_window;
2692 Display_all_screen();
2693 Display_menu();
2694 Menu_Y=a;
2695 Menu_is_visible=b;
2696
2697 Cursor_shape=CURSOR_SHAPE_COLORPICKER;
2698 b=Paintbrush_hidden;
2699 Paintbrush_hidden=1;
2700 c=-1; // color pointée: au début aucune, comme ça on initialise tout
2701 if (Menu_is_visible_before_window)
2702 Print_in_menu(Buttons_Pool[BUTTON_CHOOSE_COL].Tooltip,0);
2703
2704 Display_cursor();
2705
2706 do
2707 {
2708 Get_input(20);
2709
2710 if ((Mouse_X!=old_x) || (Mouse_Y!=old_y))
2711 {
2712 Hide_cursor();
2713 a=Read_pixel(Mouse_X,Mouse_Y);
2714 if (a!=c)
2715 {
2716 c=a; // Mise à jour de la couleur pointée
2717 if (Menu_is_visible_before_window)
2718 {
2719 d = snprintf(str, sizeof(str), "%d", a); // position of the space to color
2720 index = snprintf(str+d, sizeof(str)-d, " (%d,%d,%d)",
2721 Main.palette[a].R, Main.palette[a].G, Main.palette[a].B);
2722 index += d;
2723 a=24-d;
2724 while (index<a)
2725 str[index++]=' ';
2726 str[a]=0;
2727 Print_in_menu(str,strlen(Buttons_Pool[BUTTON_CHOOSE_COL].Tooltip));
2728
2729 Print_general((26+((d+strlen(Buttons_Pool[BUTTON_CHOOSE_COL].Tooltip))<<3))*Menu_factor_X,
2730 Menu_status_Y," ",0,c);
2731 }
2732 }
2733 Display_cursor();
2734 }
2735
2736 old_x=Mouse_X;
2737 old_y=Mouse_Y;
2738 } while (!(Mouse_K || (Key==KEY_ESC)));
2739
2740 if (Mouse_K)
2741 {
2742 Hide_cursor();
2743 *click=Mouse_K;
2744 *color=Read_pixel(Mouse_X,Mouse_Y);
2745 }
2746 else
2747 {
2748 *click=0;
2749 Hide_cursor();
2750 }
2751
2752 Restore_background(&buffer,Window_pos_X,Window_pos_Y,Window_width,Window_height);
2753 Update_window_area(0, 0, Window_width, Window_height);
2754 Cursor_shape=CURSOR_SHAPE_ARROW;
2755 Paintbrush_hidden=b;
2756 Cursor_hidden=cursor_was_hidden;
2757 Display_cursor();
2758 }
2759
2760
2761
2762 // ------------ Opération de déplacement de la fenêtre à l'écran -------------
Move_window(short dx,short dy)2763 void Move_window(short dx, short dy)
2764 {
2765 short new_x=Mouse_X-dx;
2766 short new_y=Mouse_Y-dy;
2767 short old_x;
2768 short old_y;
2769 short width=Window_width*Menu_factor_X;
2770 short height=Window_height*Menu_factor_Y;
2771 short a;
2772 byte b;
2773 byte *buffer=NULL;
2774
2775 Hide_cursor();
2776
2777 Horizontal_XOR_line(new_x,new_y,width);
2778 Vertical_XOR_line(new_x,new_y+1,height-2);
2779 Vertical_XOR_line(new_x+width-1,new_y+1,height-2);
2780 Horizontal_XOR_line(new_x,new_y+height-1,width);
2781 Update_rect(new_x,new_y,width,height);
2782 Cursor_shape=CURSOR_SHAPE_MULTIDIRECTIONAL;
2783 Display_cursor();
2784
2785 while (Mouse_K)
2786 {
2787 old_x=new_x;
2788 old_y=new_y;
2789
2790 do
2791 {
2792 Get_input(20);
2793 } while(Mouse_K && new_x==Mouse_X-dx && new_y==Mouse_Y-dy);
2794
2795 new_x=Mouse_X-dx;
2796
2797 if (new_x<0)
2798 {
2799 new_x=0;
2800 dx = Mouse_X;
2801 }
2802 if (new_x>Screen_width-width)
2803 {
2804 new_x=Screen_width-width;
2805 dx = Mouse_X - new_x;
2806 }
2807
2808 new_y=Mouse_Y-dy;
2809
2810 if (new_y<0)
2811 {
2812 new_y=0;
2813 dy = Mouse_Y;
2814 }
2815 if (new_y>Screen_height-height)
2816 {
2817 new_y=Screen_height-height;
2818 dy = Mouse_Y - new_y;
2819 }
2820
2821 if ((new_x!=old_x) || (new_y!=old_y))
2822 {
2823 Hide_cursor();
2824
2825 Horizontal_XOR_line(old_x,old_y,width);
2826 Vertical_XOR_line(old_x,old_y+1,height-2);
2827 Vertical_XOR_line(old_x+width-1,old_y+1,height-2);
2828 Horizontal_XOR_line(old_x,old_y+height-1,width);
2829
2830 Horizontal_XOR_line(new_x,new_y,width);
2831 Vertical_XOR_line(new_x,new_y+1,height-2);
2832 Vertical_XOR_line(new_x+width-1,new_y+1,height-2);
2833 Horizontal_XOR_line(new_x,new_y+height-1,width);
2834
2835 Display_cursor();
2836 Update_rect(old_x,old_y,width,height);
2837 Update_rect(new_x,new_y,width,height);
2838 }
2839 }
2840
2841 Hide_cursor();
2842 Horizontal_XOR_line(new_x,new_y,width);
2843 Vertical_XOR_line(new_x,new_y+1,height-2);
2844 Vertical_XOR_line(new_x+width-1,new_y+1,height-2);
2845 Horizontal_XOR_line(new_x,new_y+height-1,width);
2846
2847 if ((new_x!=Window_pos_X)
2848 || (new_y!=Window_pos_Y))
2849 {
2850 a=Menu_Y;
2851 Menu_Y=Menu_Y_before_window;
2852 b=Menu_is_visible;
2853 Menu_is_visible=Menu_is_visible_before_window;
2854 //Display_all_screen();
2855 //Display_menu();
2856 Menu_Y=a;
2857 Menu_is_visible=b;
2858
2859 // Sauvegarde du contenu actuel de la fenêtre
2860 Save_background(&buffer, Window_pos_X, Window_pos_Y, Window_width, Window_height);
2861
2862 // Restore de ce que la fenêtre cachait
2863 Restore_background(&Window_background[Windows_open-1], Window_pos_X, Window_pos_Y, Window_width, Window_height);
2864
2865 // Sauvegarde de ce que la fenêtre remplace
2866 Save_background(&(Window_background[Windows_open-1]), new_x, new_y, Window_width, Window_height);
2867
2868 // Raffichage de la fenêtre
2869 Restore_background(&buffer, new_x, new_y, Window_width, Window_height);
2870
2871 // Mise à jour du rectangle englobant
2872 Update_rect(
2873 (new_x>Window_pos_X)?Window_pos_X:new_x,
2874 (new_y>Window_pos_Y)?Window_pos_Y:new_y,
2875 ((new_x>Window_pos_X)?(new_x-Window_pos_X):(Window_pos_X-new_x)) + Window_width*Menu_factor_X,
2876 ((new_y>Window_pos_Y)?(new_y-Window_pos_Y):(Window_pos_Y-new_y)) + Window_height*Menu_factor_Y);
2877 Window_pos_X=new_x;
2878 Window_pos_Y=new_y;
2879
2880 }
2881 else
2882 {
2883 // Update pour effacer le rectangle XOR
2884 Update_window_area(0, 0, Window_width, Window_height);
2885 }
2886 Cursor_shape=CURSOR_SHAPE_ARROW;
2887 Display_cursor();
2888
2889 }
2890
2891 ///
2892 /// Displays a dropped-down menu and handles the UI logic until the user
2893 /// releases a mouse button.
2894 /// This function then clears the dropdown and returns the selected item,
2895 /// or NULL if the user wasn't highlighting an item when he closed.
Dropdown_activate(T_Dropdown_button * button,short off_x,short off_y)2896 T_Dropdown_choice * Dropdown_activate(T_Dropdown_button *button, short off_x, short off_y)
2897 {
2898 short nb_choices;
2899 short choice_index;
2900 short selected_index;
2901 short old_selected_index;
2902 short box_width, box_height;
2903 short x, y;
2904 short item_width;
2905 T_Dropdown_choice *item;
2906
2907 // Taille de l'ombre portée (en plus des dimensions normales)
2908 #define SHADOW_RIGHT 3
2909 #define SHADOW_BOTTOM 4
2910
2911
2912 // Comptage des items pour calculer la taille
2913 nb_choices=0;
2914 for (item=button->First_item; item!=NULL; item=item->Next)
2915 {
2916 nb_choices++;
2917 }
2918 box_height = 3+nb_choices*8+1;
2919 box_width = item_width = button->Dropdown_width;
2920 if ((box_height+SHADOW_BOTTOM)*Menu_factor_Y >= Screen_height)
2921 {
2922 // Overflow : split to 2 columns
2923 box_width = 2*item_width - 5;
2924 box_height = 3+((nb_choices+1)/2)*8+1;
2925 }
2926
2927 // Open a new stacked "window" to serve as drawing area.
2928 Open_popup(
2929 off_x+(button->Pos_X)*Menu_factor_X,
2930 off_y+(button->Pos_Y+(button->Bottom_up?-box_height:button->Height))*Menu_factor_Y,
2931 box_width+SHADOW_RIGHT,
2932 box_height+SHADOW_BOTTOM);
2933
2934 // Dessin de la boite
2935
2936 // Bord gauche
2937 Window_rectangle(0,0,1,box_height,MC_Black);
2938 // Frame fonce et blanc
2939 Window_display_frame_out(1,0,box_width-1,box_height);
2940 // Ombre portée
2941 if (SHADOW_BOTTOM)
2942 {
2943 Window_rectangle(SHADOW_RIGHT,
2944 box_height,
2945 box_width,
2946 SHADOW_BOTTOM,
2947 MC_Black);
2948 Window_rectangle(0,
2949 box_height,
2950 SHADOW_RIGHT,
2951 1,
2952 MC_Black);
2953 }
2954 if (SHADOW_RIGHT)
2955 {
2956 Window_rectangle(box_width,
2957 SHADOW_BOTTOM,
2958 SHADOW_RIGHT,
2959 box_height-SHADOW_BOTTOM,
2960 MC_Black);
2961 Window_rectangle(box_width,
2962 1,
2963 1,
2964 SHADOW_BOTTOM,
2965 MC_Black);
2966 }
2967
2968 selected_index=-1;
2969 while (1)
2970 {
2971 old_selected_index = selected_index;
2972 // Fenêtre grise
2973 Window_rectangle(2, 1, box_width - 3, box_height - 2, MC_Light);
2974 x = 3;
2975 y = 2;
2976 // Affichage des items
2977 for(item = button->First_item, choice_index = 0; item != NULL; item = item->Next, choice_index++)
2978 {
2979 byte color_1;
2980 byte color_2;
2981 if (choice_index == selected_index)
2982 {
2983 color_1 = MC_White;
2984 color_2 = MC_Dark;
2985 Window_rectangle(x, y, item_width - 5, 8, MC_Dark);
2986 }
2987 else
2988 {
2989 color_1 = MC_Black;
2990 color_2 = MC_Light;
2991 }
2992 Print_in_window(x, y, item->Label, color_1, color_2);
2993 y += 8;
2994 if ((y+7) >= box_height)
2995 {
2996 y = 2;
2997 x += item_width - 5;
2998 }
2999 }
3000 Update_window_area(0, 0, Window_width, Window_height);
3001 Display_cursor();
3002
3003 do
3004 {
3005 // Attente
3006 Get_input(20);
3007 // Mise à jour du survol
3008 if (Window_click_in_rectangle(2,2,box_width-2,box_height-3))
3009 {
3010 selected_index = ((Mouse_Y-Window_pos_Y)/Menu_factor_Y-2) >> 3;
3011 if (((Mouse_X-Window_pos_X)/Menu_factor_X-2) > item_width)
3012 selected_index += (nb_choices + 1) / 2;
3013 if (selected_index != old_selected_index)
3014 GFX2_Log(GFX2_DEBUG, "x=%d y=%d index=%d\n",
3015 ((Mouse_X-Window_pos_X)/Menu_factor_X-2),
3016 ((Mouse_Y-Window_pos_Y)/Menu_factor_Y-2),
3017 selected_index);
3018 }
3019 else
3020 selected_index = -1;
3021
3022 } while (Mouse_K && selected_index==old_selected_index);
3023
3024 if (!Mouse_K)
3025 break;
3026 Hide_cursor();
3027 }
3028
3029 Close_popup();
3030
3031 if (selected_index>=0 && selected_index<nb_choices)
3032 {
3033 for(item=button->First_item; selected_index; item=item->Next,selected_index--)
3034 ;
3035 return item;
3036 }
3037 return NULL;
3038 }
3039
3040 // Gestion des dropdown
Window_dropdown_on_click(T_Dropdown_button * button)3041 short Window_dropdown_on_click(T_Dropdown_button *button)
3042 {
3043 T_Dropdown_choice * item;
3044
3045 // Highlight the button
3046 Hide_cursor();
3047 Window_select_normal_button(button->Pos_X,button->Pos_Y,button->Width,button->Height);
3048
3049 // Handle the dropdown's logic
3050 item = Dropdown_activate(button, Window_pos_X, Window_pos_Y);
3051
3052 // Unhighlight the button
3053 Window_unselect_normal_button(button->Pos_X,button->Pos_Y,button->Width,button->Height);
3054 Display_cursor();
3055
3056 if (item == NULL)
3057 {
3058 Window_attribute2=-1;
3059 return 0;
3060 }
3061
3062 if (button->Display_choice)
3063 {
3064 // Automatically update the label of the dropdown list.
3065 int text_length = (button->Width-4-(button->Display_arrow?8:0))/8;
3066 // Clear original label area
3067 Window_rectangle(button->Pos_X+2,button->Pos_Y+(button->Height-7)/2,text_length*8,8,MC_Light);
3068 Print_in_window_limited(button->Pos_X+2,button->Pos_Y+(button->Height-7)/2,item->Label,text_length ,MC_Black,MC_Light);
3069 }
3070
3071 Window_attribute2=item->Number;
3072 return button->Number;
3073
3074 }
3075
3076 // --- Fonction de clic sur un bouton a peu près ordinaire:
3077 // Attend que l'on relache le bouton, et renvoie le numero du bouton si on
3078 // est resté dessus, 0 si on a annulé en sortant du bouton.
Window_normal_button_onclick(word x_pos,word y_pos,word width,word height,short btn_number)3079 short Window_normal_button_onclick(word x_pos, word y_pos, word width, word height, short btn_number)
3080 {
3081 while(1)
3082 {
3083 Hide_cursor();
3084 Window_select_normal_button(x_pos,y_pos,width,height);
3085 Display_cursor();
3086 while (Window_click_in_rectangle(x_pos,y_pos,x_pos+width-1,y_pos+height-1))
3087 {
3088 Get_input(20);
3089 if (!Mouse_K)
3090 {
3091 Hide_cursor();
3092 Window_unselect_normal_button(x_pos,y_pos,width,height);
3093 Display_cursor();
3094 return btn_number;
3095 }
3096 }
3097 Hide_cursor();
3098 Window_unselect_normal_button(x_pos,y_pos,width,height);
3099 Display_cursor();
3100 while (!(Window_click_in_rectangle(x_pos,y_pos,x_pos+width-1,y_pos+height-1)))
3101 {
3102 Get_input(20);
3103 if (!Mouse_K)
3104 return 0;
3105 }
3106 }
3107 }
3108
3109 // --- Returns the number of the clicked button (-1:out of the window, 0:none) ---
Window_get_clicked_button(void)3110 short Window_get_clicked_button(void)
3111 {
3112 T_Normal_button * temp1;
3113 T_Palette_button * temp2;
3114 T_Scroller_button * temp3;
3115 T_Special_button * temp4;
3116 T_Dropdown_button * temp5;
3117
3118 Window_attribute1=Mouse_K;
3119
3120 // Test click on normal buttons
3121 for (temp1=Window_normal_button_list; temp1; temp1=temp1->Next)
3122 {
3123 if ((Input_sticky_control == 0 || Input_sticky_control == temp1->Number)
3124 && Window_click_in_rectangle(temp1->Pos_X,temp1->Pos_Y,temp1->Pos_X+temp1->Width-1,temp1->Pos_Y+temp1->Height-1))
3125 {
3126 Input_sticky_control = temp1->Number;
3127 if (temp1->Repeatable)
3128 {
3129 Hide_cursor();
3130 Window_select_normal_button(temp1->Pos_X,temp1->Pos_Y,temp1->Width,temp1->Height);
3131 Display_cursor();
3132 Delay_with_active_mouse((Mouse_K==1)? Config.Delay_left_click_on_slider : Config.Delay_right_click_on_slider);
3133 Hide_cursor();
3134 Window_unselect_normal_button(temp1->Pos_X,temp1->Pos_Y,temp1->Width,temp1->Height);
3135 Display_cursor();
3136 return temp1->Number;
3137 }
3138 return Window_normal_button_onclick(temp1->Pos_X,temp1->Pos_Y,temp1->Width,temp1->Height,temp1->Number);
3139 }
3140 }
3141
3142 // Test click on "Palette" buttons
3143 for (temp2=Window_palette_button_list; temp2; temp2=temp2->Next)
3144 {
3145 if ((Input_sticky_control == 0 || Input_sticky_control == temp2->Number)
3146 && Window_click_in_rectangle(temp2->Pos_X+5,temp2->Pos_Y+3,temp2->Pos_X+160,temp2->Pos_Y+82))
3147 {
3148 Input_sticky_control = temp2->Number;
3149 // We store the clicked color in Attribute2
3150 Window_attribute2 = (((Mouse_X-Window_pos_X)/Menu_factor_X)-(temp2->Pos_X+2)) / 10 * 16 +
3151 (((Mouse_Y-Window_pos_Y)/Menu_factor_Y)-(temp2->Pos_Y+3)) / 5;
3152 return temp2->Number;
3153 }
3154 }
3155
3156 // Test click on slider/scroller bars
3157 for (temp3=Window_scroller_button_list; temp3; temp3=temp3->Next)
3158 {
3159 // Button Up arrow
3160 if ((Input_sticky_control == 0 || Input_sticky_control == (temp3->Number|1024))
3161 && Window_click_in_rectangle(temp3->Pos_X,temp3->Pos_Y,temp3->Pos_X+10,temp3->Pos_Y+10))
3162 {
3163 Input_sticky_control = temp3->Number | 1024;
3164 Hide_cursor();
3165 Window_select_normal_button(temp3->Pos_X,temp3->Pos_Y,11,11);
3166
3167 if (temp3->Position)
3168 {
3169 temp3->Position--;
3170 Window_attribute1=1;
3171 Window_attribute2=temp3->Position;
3172 Window_draw_slider(temp3);
3173 }
3174 else
3175 Window_attribute1=0;
3176
3177 Display_cursor();
3178
3179 Delay_with_active_mouse((Mouse_K==1)? Config.Delay_left_click_on_slider : Config.Delay_right_click_on_slider);
3180
3181 Hide_cursor();
3182 Window_unselect_normal_button(temp3->Pos_X,temp3->Pos_Y,11,11);
3183 Display_cursor();
3184
3185 return (Window_attribute1)? temp3->Number : 0;
3186 }
3187
3188 // Button Down arrow
3189 if ((Input_sticky_control == 0 || Input_sticky_control == (temp3->Number|2048))
3190 && ((temp3->Is_horizontal && Window_click_in_rectangle(temp3->Pos_X+temp3->Length-11,temp3->Pos_Y,temp3->Pos_X+temp3->Length-1,temp3->Pos_Y+10))
3191 || (!temp3->Is_horizontal && Window_click_in_rectangle(temp3->Pos_X,temp3->Pos_Y+temp3->Length-11,temp3->Pos_X+10,temp3->Pos_Y+temp3->Length-1))))
3192 {
3193 Input_sticky_control = temp3->Number | 2048;
3194 Hide_cursor();
3195 if (temp3->Is_horizontal)
3196 Window_select_normal_button(temp3->Pos_X+temp3->Length-11,temp3->Pos_Y,11,11);
3197 else
3198 Window_select_normal_button(temp3->Pos_X,temp3->Pos_Y+temp3->Length-11,11,11);
3199
3200 if (temp3->Position+temp3->Nb_visibles<temp3->Nb_elements)
3201 {
3202 temp3->Position++;
3203 Window_attribute1=2;
3204 Window_attribute2=temp3->Position;
3205 Window_draw_slider(temp3);
3206 }
3207 else
3208 Window_attribute1=0;
3209
3210 Display_cursor();
3211
3212 Delay_with_active_mouse((Mouse_K==1)? Config.Delay_left_click_on_slider : Config.Delay_right_click_on_slider);
3213
3214 Hide_cursor();
3215 if (temp3->Is_horizontal)
3216 Window_unselect_normal_button(temp3->Pos_X+temp3->Length-11,temp3->Pos_Y,11,11);
3217 else
3218 Window_unselect_normal_button(temp3->Pos_X,temp3->Pos_Y+temp3->Length-11,11,11);
3219 Display_cursor();
3220
3221 return (Window_attribute1)? temp3->Number : 0;
3222 }
3223 // Middle slider
3224 if ((Input_sticky_control == temp3->Number) || (Input_sticky_control==0 &&
3225 ((!temp3->Is_horizontal && Window_click_in_rectangle(temp3->Pos_X,temp3->Pos_Y+12,temp3->Pos_X+10,temp3->Pos_Y+temp3->Length-13))
3226 ||(temp3->Is_horizontal && Window_click_in_rectangle(temp3->Pos_X+12,temp3->Pos_Y,temp3->Pos_X+temp3->Length-13,temp3->Pos_Y+10)))))
3227 {
3228 Input_sticky_control = temp3->Number;
3229 if (temp3->Nb_elements>temp3->Nb_visibles)
3230 {
3231 // If there is enough room to make the cursor move:
3232 long mouse_pos;
3233 long origin;
3234
3235 // Window_attribute2 receives the position of the cursor.
3236 if (temp3->Is_horizontal)
3237 mouse_pos =(Mouse_X-Window_pos_X) / Menu_factor_X - (temp3->Pos_X+12);
3238 else
3239 mouse_pos =(Mouse_Y-Window_pos_Y) / Menu_factor_Y - (temp3->Pos_Y+12);
3240
3241 // The following formula is wicked. The issue is that you want two
3242 // different behaviors:
3243 // *) If the range is bigger than the pixel precision, the last pixel
3244 // should map to max value, exactly.
3245 // *) Otherwise, the possible cursor positions are separated by
3246 // at least one full pixel, so we should find the valid position
3247 // closest to the center of the mouse cursor position pixel.
3248
3249 origin = (temp3->Nb_visibles-1)*(temp3->Length-24)/temp3->Nb_elements/2;
3250 Window_attribute2 = (mouse_pos - origin) * (temp3->Nb_elements-(temp3->Cursor_length>1?0:1)) / (temp3->Length-24-1);
3251
3252 if (Window_attribute2<0)
3253 Window_attribute2=0;
3254 else if (Window_attribute2+temp3->Nb_visibles>temp3->Nb_elements)
3255 Window_attribute2=temp3->Nb_elements-temp3->Nb_visibles;
3256
3257 // If the cursor moved
3258
3259 if (temp3->Position!=Window_attribute2)
3260 {
3261 temp3->Position=Window_attribute2;
3262 Window_attribute1=3;
3263 Hide_cursor();
3264 Window_draw_slider(temp3);
3265 Display_cursor();
3266 }
3267 else
3268 // If the cursor moved
3269 Window_attribute1=0;
3270 }
3271 else
3272 // If there's not enough room to make the cursor move:
3273 Window_attribute1=0;
3274
3275 return (Window_attribute1)? temp3->Number : 0;
3276 }
3277 }
3278
3279 // Test click on a special button
3280 for (temp4=Window_special_button_list; temp4; temp4=temp4->Next)
3281 {
3282 if ((Input_sticky_control == 0 || Input_sticky_control == temp4->Number)
3283 && Window_click_in_rectangle(temp4->Pos_X,temp4->Pos_Y,temp4->Pos_X+temp4->Width-1,temp4->Pos_Y+temp4->Height-1))
3284 {
3285 Input_sticky_control = temp4->Number;
3286 return temp4->Number;
3287 }
3288 }
3289
3290 // Test click on a dropdown box
3291 for (temp5=Window_dropdown_button_list; temp5; temp5=temp5->Next)
3292 {
3293 if ((Input_sticky_control == 0 || Input_sticky_control == temp5->Number)
3294 && Window_click_in_rectangle(temp5->Pos_X,temp5->Pos_Y,temp5->Pos_X+temp5->Width-1,temp5->Pos_Y+temp5->Height-1))
3295 {
3296 Input_sticky_control = temp5->Number;
3297 if (Mouse_K & temp5->Active_button)
3298 return Window_dropdown_on_click(temp5);
3299 else
3300 {
3301 Window_attribute2=-1;
3302 return Window_normal_button_onclick(temp5->Pos_X,temp5->Pos_Y,temp5->Width,temp5->Height,temp5->Number);
3303 }
3304 }
3305 }
3306
3307 return 0;
3308 }
3309
3310
Window_get_button_shortcut(void)3311 short Window_get_button_shortcut(void)
3312 {
3313 T_Normal_button * temp;
3314 T_Special_button * temp2;
3315
3316 if (Key & GFX2_MOD_SHIFT)
3317 Window_attribute1=RIGHT_SIDE;
3318 else
3319 Window_attribute1=LEFT_SIDE;
3320
3321 // On fait une première recherche
3322 temp=Window_normal_button_list;
3323 while (temp!=NULL)
3324 {
3325 if (temp->Shortcut==Key)
3326 {
3327 Hide_cursor();
3328 Window_select_normal_button(temp->Pos_X,temp->Pos_Y,temp->Width,temp->Height);
3329 Display_cursor();
3330
3331 Delay_with_active_mouse(Config.Delay_right_click_on_slider);
3332
3333 Hide_cursor();
3334 Window_unselect_normal_button(temp->Pos_X,temp->Pos_Y,temp->Width,temp->Height);
3335 Display_cursor();
3336
3337 return temp->Number;
3338 }
3339 temp=temp->Next;
3340 }
3341
3342 // Scan for shortcut in special button list
3343 temp2=Window_special_button_list;
3344 while (temp2!=NULL)
3345 {
3346 if (temp2->Shortcut==Key)
3347 {
3348 return temp2->Number;
3349 }
3350 temp2=temp2->Next;
3351 }
3352
3353 // Si la recherche n'a pas été fructueuse ET que l'utilisateur appuyait sur
3354 // <Shift>, on regarde si un bouton ne pourrait pas réagir comme si <Shift>
3355 // n'était pas appuyé.
3356 if (Window_attribute1==RIGHT_SIDE)
3357 {
3358 temp=Window_normal_button_list;
3359 while (temp!=NULL)
3360 {
3361 if (temp->Shortcut==(Key&0x0FFF))
3362 return temp->Number;
3363 temp=temp->Next;
3364 }
3365 }
3366
3367 // Handle arrow keys, end/home, and mouse wheel that have
3368 // a certain behavior if a list control is present.
3369 if (Window_list_button_list)
3370 {
3371 T_List_button *list = Window_list_button_list;
3372 // If there's more than one of such control, only capture
3373 // events if the mouse cursor is over it.
3374 if (list->Next)
3375 {
3376 // to do
3377 }
3378
3379
3380
3381
3382
3383
3384 }
3385 return 0;
3386 }
3387
Window_clicked_button(void)3388 short Window_clicked_button(void)
3389 {
3390 short Button;
3391 byte old_mouse_k;
3392
3393 old_mouse_k=Mouse_K;
3394 Get_input(20);
3395 // Handle clicks
3396 if (Mouse_K)
3397 {
3398 if ((Mouse_X<Window_pos_X) || (Mouse_Y<Window_pos_Y)
3399 || (Mouse_X>=Window_pos_X+(Window_width*Menu_factor_X))
3400 || (Mouse_Y>=Window_pos_Y+(Window_height*Menu_factor_Y)))
3401 {
3402 if (Input_sticky_control == 0 || Input_sticky_control == -1)
3403 {
3404 Input_sticky_control = -1;
3405 return -1;
3406 }
3407 else
3408 {
3409 return 0;
3410 }
3411 }
3412
3413 if (!Input_sticky_control && Window_draggable && Mouse_Y < Window_pos_Y+(12*Menu_factor_Y))
3414 {
3415 Move_window(Mouse_X-Window_pos_X,Mouse_Y-Window_pos_Y);
3416 }
3417 else
3418 {
3419 short clicked_button;
3420 T_List_button * list;
3421 static dword time_last_click = 0;
3422 static int last_list_number = -1;
3423 dword time_now;
3424
3425 // Check which controls was clicked (by rectangular area)
3426 clicked_button = Window_get_clicked_button();
3427
3428 // Check if it's part of a list control
3429 for (list=Window_list_button_list; list!=NULL; list=list->Next)
3430 {
3431 if (list->Entry_button->Number == clicked_button)
3432 {
3433 // Click in the textual part of a list.
3434 short clicked_line;
3435 clicked_line = (((Mouse_Y-Window_pos_Y)/Menu_factor_Y)-list->Entry_button->Pos_Y)>>3;
3436 if (clicked_line >= list->Scroller->Nb_elements) // Below last line
3437 return 0;
3438 time_now = GFX2_GetTicks();
3439 if (clicked_line == list->Cursor_position)
3440 {
3441 // Double click check
3442 if (old_mouse_k==0 && last_list_number==list->Number && time_now - time_last_click < Config.Double_click_speed)
3443 {
3444 time_last_click = time_now;
3445 Input_sticky_control=0;
3446 // Store the selected value as attribute2
3447 Window_attribute2=list->List_start + list->Cursor_position;
3448 // Return the control ID of the "special button" that covers the list.
3449 return list->Entry_button->Number;
3450 }
3451 time_last_click = time_now;
3452 last_list_number=list->Number;
3453 // Already selected : don't activate anything
3454 return 0;
3455 }
3456
3457 Hide_cursor();
3458 // Redraw one item as disabled
3459 if (list->Cursor_position>=0 && list->Cursor_position<list->Scroller->Nb_visibles)
3460 list->Draw_list_item(
3461 list->Entry_button->Pos_X,
3462 list->Entry_button->Pos_Y + list->Cursor_position * 8,
3463 list->List_start + list->Cursor_position,
3464 0);
3465 list->Cursor_position = clicked_line;
3466 // Redraw one item as enabled
3467 if (list->Cursor_position>=0 && list->Cursor_position<list->Scroller->Nb_visibles)
3468 list->Draw_list_item(
3469 list->Entry_button->Pos_X,
3470 list->Entry_button->Pos_Y + list->Cursor_position * 8,
3471 list->List_start + list->Cursor_position,
3472 1);
3473 Display_cursor();
3474
3475 // Store the selected value as attribute2
3476 Window_attribute2=list->List_start + list->Cursor_position;
3477 // Return the control ID of the list.
3478 return list->Number;
3479 }
3480 else if (list->Scroller->Number == clicked_button)
3481 {
3482 // Click in the scroller part of a list
3483 if (list->List_start == list->Scroller->Position)
3484 return 0; // Didn't actually move
3485 // Update scroller indices
3486 list->Cursor_position += list->List_start;
3487 list->List_start = list->Scroller->Position;
3488 list->Cursor_position -= list->List_start;
3489 // Need to redraw all
3490 Hide_cursor();
3491 Window_redraw_list(list);
3492 Display_cursor();
3493 }
3494 }
3495 return clicked_button;
3496 }
3497 }
3498
3499 // Intercept keys
3500 if (Key)
3501 {
3502 T_List_button * list;
3503
3504 Button=Window_get_button_shortcut();
3505 if (Button)
3506 {
3507 Key=0;
3508 return Button;
3509 }
3510 // Check if there's a list control and the keys can control it
3511 for (list=Window_list_button_list; list!=NULL; list=list->Next)
3512 {
3513 // FIXME: Make only one list have the keyboard focus.
3514 if (1)
3515 {
3516 if (Key==KEY_UP && (list->Cursor_position+list->List_start)>0)
3517 {
3518 Key=0;
3519 Hide_cursor();
3520 list->Cursor_position--;
3521 if (list->Cursor_position<0)
3522 {
3523 list->List_start=list->List_start+list->Cursor_position;
3524 list->Cursor_position=0;
3525 // Mise à jour du scroller
3526 list->Scroller->Position=list->List_start;
3527 Window_draw_slider(list->Scroller);
3528 }
3529 Window_redraw_list(list);
3530 Display_cursor();
3531 // Store the selected value as attribute2
3532 Window_attribute2=list->List_start + list->Cursor_position;
3533 // Return the control ID of the list.
3534 return list->Number;
3535 }
3536 if (Key==KEY_DOWN && (list->Cursor_position+list->List_start)<(list->Scroller->Nb_elements-1))
3537 {
3538 Key=0;
3539 Hide_cursor();
3540 list->Cursor_position++;
3541 if (list->Cursor_position>(list->Scroller->Nb_visibles-1))
3542 {
3543 list->List_start=list->List_start+list->Cursor_position-(list->Scroller->Nb_visibles-1);
3544 list->Cursor_position=(list->Scroller->Nb_visibles-1);
3545 // Mise à jour du scroller
3546 list->Scroller->Position=list->List_start;
3547 Window_draw_slider(list->Scroller);
3548 }
3549 Window_redraw_list(list);
3550 Display_cursor();
3551 // Store the selected value as attribute2
3552 Window_attribute2=list->List_start + list->Cursor_position;
3553 // Return the control ID of the list.
3554 return list->Number;
3555 }
3556 if (Key==KEY_HOME && (list->Cursor_position!=0 || list->List_start!=0))
3557 {
3558 Key=0;
3559 Hide_cursor();
3560 list->Cursor_position=0;
3561 list->List_start=0;
3562 // Mise à jour du scroller
3563 list->Scroller->Position=list->List_start;
3564 Window_draw_slider(list->Scroller);
3565 Window_redraw_list(list);
3566 Display_cursor();
3567 // Store the selected value as attribute2
3568 Window_attribute2=list->List_start + list->Cursor_position;
3569 // Return the control ID of the list.
3570 return list->Number;
3571 }
3572 if (Key==KEY_END && (list->Cursor_position+list->List_start)<(list->Scroller->Nb_elements-1))
3573 {
3574 Key=0;
3575 Hide_cursor();
3576 list->Cursor_position=(list->Scroller->Nb_elements-1)-list->List_start;
3577 if (list->Cursor_position>(list->Scroller->Nb_visibles-1))
3578 {
3579 list->List_start=list->List_start+list->Cursor_position-(list->Scroller->Nb_visibles-1);
3580 list->Cursor_position=(list->Scroller->Nb_visibles-1);
3581 // Mise à jour du scroller
3582 list->Scroller->Position=list->List_start;
3583 Window_draw_slider(list->Scroller);
3584 }
3585 Window_redraw_list(list);
3586 Display_cursor();
3587 // Store the selected value as attribute2
3588 Window_attribute2=list->List_start + list->Cursor_position;
3589 // Return the control ID of the list.
3590 return list->Number;
3591 }
3592 if (Key==KEY_PAGEDOWN && (list->Cursor_position+list->List_start)<(list->Scroller->Nb_elements-1))
3593 {
3594 Key=0;
3595 Hide_cursor();
3596 if (list->Scroller->Nb_elements<list->Scroller->Nb_visibles)
3597 {
3598 list->Cursor_position=list->Scroller->Nb_elements-1;
3599 }
3600 else if(list->Cursor_position!=list->Scroller->Nb_visibles-1)
3601 {
3602 list->Cursor_position=list->Scroller->Nb_visibles-1;
3603 }
3604 else
3605 {
3606 list->List_start+=list->Scroller->Nb_visibles;
3607 if (list->List_start+list->Scroller->Nb_visibles>list->Scroller->Nb_elements)
3608 {
3609 list->List_start=list->Scroller->Nb_elements-list->Scroller->Nb_visibles;
3610 }
3611 // Mise à jour du scroller
3612 list->Scroller->Position=list->List_start;
3613 Window_draw_slider(list->Scroller);
3614 }
3615 Window_redraw_list(list);
3616 Display_cursor();
3617 // Store the selected value as attribute2
3618 Window_attribute2=list->List_start + list->Cursor_position;
3619 // Return the control ID of the list.
3620 return list->Number;
3621 }
3622 if (Key==KEY_PAGEUP && (list->Cursor_position+list->List_start)>0)
3623 {
3624 Key=0;
3625 Hide_cursor();
3626 if(list->Cursor_position!=0)
3627 {
3628 list->Cursor_position=0;
3629 }
3630 else
3631 {
3632 list->List_start-=list->Scroller->Nb_visibles;
3633 if (list->List_start<0)
3634 {
3635 list->List_start=0;
3636 }
3637 // Mise à jour du scroller
3638 list->Scroller->Position=list->List_start;
3639 Window_draw_slider(list->Scroller);
3640 }
3641 Window_redraw_list(list);
3642 Display_cursor();
3643 // Store the selected value as attribute2
3644 Window_attribute2=list->List_start + list->Cursor_position;
3645 // Return the control ID of the list.
3646 return list->Number;
3647 }
3648 if (Key == KEY_MOUSEWHEELUP && list->List_start>0)
3649 {
3650 list->Cursor_position+=list->List_start;
3651 if (list->List_start>=3)
3652 list->List_start-=3;
3653 else
3654 list->List_start=0;
3655 list->Cursor_position-=list->List_start;
3656 // On affiche à nouveau la liste
3657 Hide_cursor();
3658 Window_redraw_list(list);
3659 // Mise à jour du scroller
3660 list->Scroller->Position=list->List_start;
3661 Window_draw_slider(list->Scroller);
3662 Display_cursor();
3663 }
3664 if (Key==KEY_MOUSEWHEELDOWN && list->List_start<list->Scroller->Nb_elements-list->Scroller->Nb_visibles)
3665 {
3666 list->Cursor_position+=list->List_start;
3667 list->List_start+=3;
3668 if (list->List_start+list->Scroller->Nb_visibles>list->Scroller->Nb_elements)
3669 {
3670 list->List_start=list->Scroller->Nb_elements-list->Scroller->Nb_visibles;
3671 }
3672 list->Cursor_position-=list->List_start;
3673 // On affiche à nouveau la liste
3674 Hide_cursor();
3675 Window_redraw_list(list);
3676 // Mise à jour du scroller
3677 list->Scroller->Position=list->List_start;
3678 Window_draw_slider(list->Scroller);
3679 Display_cursor();
3680 }
3681
3682 }
3683 }
3684 }
3685
3686 return 0;
3687 }
3688
3689
3690 // Fonction qui sert à remapper les parties sauvegardées derriere les
3691 // fenetres ouvertes. C'est utilisé par exemple par la fenetre de palette
3692 // Qui remappe des couleurs, afin de propager les changements.
Remap_window_backgrounds(const byte * conversion_table,int Min_Y,int Max_Y)3693 void Remap_window_backgrounds(const byte * conversion_table, int Min_Y, int Max_Y)
3694 {
3695 int window_index;
3696 byte* EDI;
3697 int dx,cx;
3698
3699 for (window_index=0; window_index<Windows_open; window_index++)
3700 {
3701 EDI = Window_background[window_index];
3702
3703 // Pour chaque ligne
3704 for(dx=0; dx<Window_stack[window_index].Height*Menu_factor_Y;dx++)
3705 {
3706 if (dx+Window_stack[window_index].Pos_Y>Max_Y)
3707 return;
3708 if (dx+Window_stack[window_index].Pos_Y<Min_Y)
3709 EDI += Window_stack[window_index].Width*Menu_factor_X*Pixel_width;
3710 else
3711 { // Pour chaque pixel
3712 for(cx=Window_stack[window_index].Width*Menu_factor_X*Pixel_width;cx>0;cx--)
3713 {
3714 *EDI = conversion_table[*EDI];
3715 EDI ++;
3716 }
3717 }
3718 }
3719 }
3720 }
3721
Remap_UI_in_window_backgrounds(const byte * conversion_table)3722 void Remap_UI_in_window_backgrounds(const byte * conversion_table)
3723 {
3724 int i, j;
3725 int pos_y;
3726
3727 // all window backgrounds
3728 for (i = 0; i < Windows_open; i++)
3729 {
3730 // remap pixels of background that are either Menu or another window below
3731 byte * p = Window_background[i];
3732 for (pos_y = Window_stack[i].Pos_Y;
3733 pos_y < (Window_stack[i].Pos_Y + Window_stack[i].Height*Menu_factor_Y);
3734 pos_y++)
3735 {
3736 // for each line of the background
3737 int min_x = 0xffff;
3738 int max_x = 0;
3739 if (Menu_is_visible_before_window && pos_y >= Menu_Y_before_window)
3740 {
3741 min_x = 0;
3742 max_x = Screen_width;
3743 }
3744 else for(j = 0; j < i; j++)
3745 {
3746 // check all windows below
3747 if (pos_y < Window_stack[j].Pos_Y
3748 || pos_y >= (Window_stack[j].Pos_Y + Window_stack[j].Height*Menu_factor_Y) )
3749 continue; // this window doesn't occupy this screen row
3750 if (min_x > Window_stack[j].Pos_X)
3751 min_x = Window_stack[j].Pos_X;
3752 if (max_x < (Window_stack[j].Pos_X + Window_stack[j].Width*Menu_factor_X))
3753 max_x = Window_stack[j].Pos_X + Window_stack[j].Width*Menu_factor_X;
3754
3755 }
3756 if (min_x < Window_stack[i].Pos_X)
3757 min_x = Window_stack[i].Pos_X;
3758 if (max_x > Window_stack[i].Pos_X + Window_stack[i].Width*Menu_factor_X)
3759 max_x = Window_stack[i].Pos_X + Window_stack[i].Width*Menu_factor_X;
3760 if (max_x > min_x)
3761 {
3762 int x;
3763 min_x -= Window_stack[i].Pos_X;
3764 max_x -= Window_stack[i].Pos_X;
3765 // do the conversion
3766 for (x = min_x * Pixel_width; x < max_x * Pixel_width; x++)
3767 {
3768 p[x] = conversion_table[p[x]];
3769 }
3770 }
3771 p += Window_stack[i].Width*Menu_factor_X*Pixel_width;
3772 }
3773 }
3774 }
3775
Delay_with_active_mouse(int speed)3776 void Delay_with_active_mouse(int speed)
3777 {
3778 dword end;
3779 byte original_mouse_k = Mouse_K;
3780
3781 end = GFX2_GetTicks()+speed*10;
3782
3783 do
3784 {
3785 Get_input(20);
3786 } while (Mouse_K == original_mouse_k && GFX2_GetTicks()<end);
3787 }
3788
3789 ///
3790 /// Based on which toolbars are visible, updates their offsets and
3791 /// computes ::Menu_height and ::Menu_Y
Compute_menu_offsets(void)3792 void Compute_menu_offsets(void)
3793 {
3794 int i;
3795 int offset;
3796
3797 // Recompute all offsets
3798 offset=0;
3799 Menu_height=0;
3800 for (i = MENUBAR_COUNT-1; i >=0; i--)
3801 {
3802 Menu_bars[i].Top = offset;
3803 if(Menu_bars[i].Visible)
3804 {
3805 offset += Menu_bars[i].Height;
3806 Menu_height += Menu_bars[i].Height;
3807 }
3808 }
3809 // Update global menu coordinates
3810 Menu_Y = Screen_height - Menu_height * Menu_factor_Y;
3811 }
3812
3813 ///
3814 /// Shows or hides a tolbar from the menu.
3815 /// If with_redraw is set to zero, the caller should
3816 /// redraw itself using Display_menu() and Display_all_screen().
Set_bar_visibility(word bar,int visible,int with_redraw)3817 void Set_bar_visibility(word bar, int visible, int with_redraw)
3818 {
3819 if (!visible && Menu_bars[bar].Visible)
3820 {
3821 // Hide it
3822 Menu_bars[bar].Visible=0;
3823
3824 Compute_menu_offsets();
3825
3826 if (Main.magnifier_mode)
3827 {
3828 Compute_magnifier_data();
3829 }
3830
3831 // On repositionne le décalage de l'image pour qu'il n'y ait pas d'in-
3832 // -cohérences lorsqu'on sortira du mode Loupe.
3833 if (Main.offset_Y+Screen_height>Main.image_height)
3834 {
3835 if (Screen_height>Main.image_height)
3836 Main.offset_Y=0;
3837 else
3838 Main.offset_Y=Main.image_height-Screen_height;
3839 }
3840 // On fait pareil pour le brouillon
3841 if (Spare.offset_Y+Screen_height>Spare.image_height)
3842 {
3843 if (Screen_height>Spare.image_height)
3844 Spare.offset_Y=0;
3845 else
3846 Spare.offset_Y=Spare.image_height-Screen_height;
3847 }
3848
3849 Compute_magnifier_data();
3850 if (Main.magnifier_mode)
3851 Position_screen_according_to_zoom();
3852 Compute_limits();
3853 Compute_paintbrush_coordinates();
3854 if (with_redraw)
3855 {
3856 Display_menu();
3857 Display_all_screen();
3858 }
3859 }
3860 else if (visible && !Menu_bars[bar].Visible)
3861 {
3862 // Show it
3863 Menu_bars[bar].Visible = 1;
3864
3865 Compute_menu_offsets();
3866 Compute_magnifier_data();
3867 if (Main.magnifier_mode)
3868 Position_screen_according_to_zoom();
3869 Compute_limits();
3870 Compute_paintbrush_coordinates();
3871 if (with_redraw)
3872 {
3873 Display_menu();
3874 if (Main.magnifier_mode)
3875 Display_all_screen();
3876 }
3877 }
3878 }
3879
3880 ///
3881 /// Checks if the current menu toolbars suit the current image type :
3882 /// layered vs anim. If they don't fit, swap the toolbars and return 1:
3883 /// The caller is then responsible for refreshing the screen by calling
3884 /// Display_menu() and Display_all_screen()
Check_menu_mode(void)3885 int Check_menu_mode(void)
3886 {
3887 if (Main.backups->Pages->Image_mode == IMAGE_MODE_ANIMATION)
3888 {
3889 if (Menu_bars[MENUBAR_LAYERS].Visible)
3890 {
3891 Set_bar_visibility(MENUBAR_LAYERS, 0, 0);
3892 Set_bar_visibility(MENUBAR_ANIMATION, 1, 0);
3893 return 1;
3894 }
3895 }
3896 else
3897 {
3898 if (Menu_bars[MENUBAR_ANIMATION].Visible)
3899 {
3900 Set_bar_visibility(MENUBAR_ANIMATION, 0, 0);
3901 Set_bar_visibility(MENUBAR_LAYERS, 1, 0);
3902 return 1;
3903 }
3904 }
3905 return 0;
3906 }
3907