/* Grafx2 - The Ultimate 256-color bitmap paint program Copyright 2007 Adrien Destugues Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) Grafx2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. Grafx2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Grafx2; if not, see or write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // // Ce fichier contient la gestion du moteur // #include #include #include #include "const.h" #include "struct.h" #include "global.h" #include "graph.h" #include "divers.h" #include "special.h" #include "boutons.h" #include "operatio.h" #include "shade.h" #include "erreurs.h" #include "sdlscreen.h" #include "windows.h" #include "brush.h" #include "input.h" #include "moteur.h" // we need this as global short Old_MX = -1; short Old_MY = -1; //---------- Annuler les effets des modes de dessin (sauf la grille) --------- // Variables mémorisants les anciens effets byte Shade_Mode_avant_annulation; byte Quick_shade_Mode_avant_annulation; byte Stencil_Mode_avant_annulation; byte Trame_Mode_avant_annulation; byte Colorize_Mode_avant_annulation; byte Smooth_Mode_avant_annulation; byte Tiling_Mode_avant_annulation; fonction_effet Fonction_effet_avant_annulation; byte* Fond_fenetre[8]; void Annuler_les_effets(void) { Shade_Mode_avant_annulation=Shade_Mode; Shade_Mode=0; Quick_shade_Mode_avant_annulation=Quick_shade_Mode; Quick_shade_Mode=0; Stencil_Mode_avant_annulation=Stencil_Mode; Stencil_Mode=0; Trame_Mode_avant_annulation=Trame_Mode; Trame_Mode=0; Colorize_Mode_avant_annulation=Colorize_Mode; Colorize_Mode=0; Smooth_Mode_avant_annulation=Smooth_Mode; Smooth_Mode=0; Tiling_Mode_avant_annulation=Tiling_Mode; Tiling_Mode=0; Fonction_effet_avant_annulation=Fonction_effet; Fonction_effet=Aucun_effet; } //----------------- Restaurer les effets des modes de dessin ----------------- void Restaurer_les_effets(void) { Shade_Mode =Shade_Mode_avant_annulation; Quick_shade_Mode=Quick_shade_Mode_avant_annulation; Stencil_Mode =Stencil_Mode_avant_annulation; Trame_Mode =Trame_Mode_avant_annulation; Colorize_Mode =Colorize_Mode_avant_annulation; Smooth_Mode =Smooth_Mode_avant_annulation; Tiling_Mode =Tiling_Mode_avant_annulation; Fonction_effet =Fonction_effet_avant_annulation; } char * TITRE_BOUTON[NB_BOUTONS]= { "Paintbrush choice ", "Adjust picture / Effects", "Freehand draw. / Toggle ", "Splines / Toggle ", "Lines / Toggle ", "Spray / Menu ", "Floodfill / Replace col.", "Polylines / Polyforms ", "Polyfill / Filled Pforms", "Empty rectangles ", "Filled rectangles ", "Empty circles / ellipses", "Filled circles / ellips.", "Grad. rectangles ", "Gradation menu ", "Grad. spheres / ellipses", "Brush grab. / Restore ", "Lasso / Restore brush ", "Brush effects ", "Drawing modes (effects) ", "Text ", "Magnify mode / Menu ", "Pipette / Invert colors ", "Screen size / Safe. res.", "Go / Copy to other page ", "Save as / Save ", "Load / Re-load ", "Settings ", "Clear / with backcolor ", "Help / Statistics ", "Undo / Redo ", "Kill current page ", "Quit ", "Palette editor ", "Scroll pal. left / Fast ", "Scroll pal. right / Fast", "Color #" , "Hide tool bar " }; // Sauvegarde un bloc (généralement l'arrière-plan d'une fenêtre) void Sauve_fond(byte **Buffer, int x_pos, int y_pos, int width, int height) { int Indice; if(*Buffer != NULL) DEBUG("WARNING : Buffer already allocated !!!",0); *Buffer=(byte *) malloc(width*Menu_Facteur_X*height*Menu_Facteur_Y*Pixel_width); for (Indice=0; Indice<(height*Menu_Facteur_Y); Indice++) Lire_ligne(x_pos,y_pos+Indice,width*Menu_Facteur_X,(*Buffer)+((int)Indice*width*Menu_Facteur_X*Pixel_width)); } // Restaure de ce que la fenêtre cachait void Restaure_fond(byte *Buffer, int x_pos, int y_pos, int width, int height) { int Indice; for (Indice=0; Indice=Bouton[btn_number].Decalage_X) && (y_pos>=Bouton[btn_number].Decalage_Y) && (x_pos<=Bouton[btn_number].Decalage_X+Bouton[btn_number].Width) && (y_pos<=Bouton[btn_number].Decalage_Y+Bouton[btn_number].Height)) return btn_number; break; case FORME_BOUTON_TRIANGLE_HAUT_GAUCHE: if ((x_pos>=Bouton[btn_number].Decalage_X) && (y_pos>=Bouton[btn_number].Decalage_Y) && (x_pos+y_pos-(short)Bouton[btn_number].Decalage_Y-(short)Bouton[btn_number].Decalage_X<=Bouton[btn_number].Width)) return btn_number; break; case FORME_BOUTON_TRIANGLE_BAS_DROITE: if ((x_pos<=Bouton[btn_number].Decalage_X+Bouton[btn_number].Width) && (y_pos<=Bouton[btn_number].Decalage_Y+Bouton[btn_number].Height) && (x_pos+y_pos-(short)Bouton[btn_number].Decalage_Y-(short)Bouton[btn_number].Decalage_X>=Bouton[btn_number].Width)) return btn_number; break; } } return -1; } void Tracer_cadre_de_bouton_du_menu(byte btn_number,byte pressed) { byte Couleur_Haut_gauche; byte Couleur_Bas_droite; byte Couleur_Diagonale; word Debut_X; word Debut_Y; word Fin_X; word Fin_Y; word x_pos; word y_pos; Debut_X=Bouton[btn_number].Decalage_X; Debut_Y=Bouton[btn_number].Decalage_Y; Fin_X =Debut_X+Bouton[btn_number].Width; Fin_Y =Debut_Y+Bouton[btn_number].Height; if (!pressed) { Couleur_Haut_gauche=CM_Blanc; Couleur_Bas_droite=CM_Fonce; Couleur_Diagonale=CM_Clair; } else { Couleur_Haut_gauche=CM_Fonce; Couleur_Bas_droite=CM_Noir; Couleur_Diagonale=CM_Fonce; } switch(Bouton[btn_number].Shape) { case FORME_BOUTON_SANS_CADRE : break; case FORME_BOUTON_RECTANGLE : // On colorie le point haut droit Pixel_dans_menu(Fin_X,Debut_Y,Couleur_Diagonale); BLOCK_MENU[Debut_Y][Fin_X]=Couleur_Diagonale; // On colorie le point bas gauche Pixel_dans_menu(Debut_X,Fin_Y,Couleur_Diagonale); BLOCK_MENU[Fin_Y][Debut_X]=Couleur_Diagonale; // On colorie la partie haute for (x_pos=Debut_X;x_pos<=Fin_X-1;x_pos++) { Pixel_dans_menu(x_pos,Debut_Y,Couleur_Haut_gauche); BLOCK_MENU[Debut_Y][x_pos]=Couleur_Haut_gauche; } for (y_pos=Debut_Y+1;y_pos<=Fin_Y-1;y_pos++) { // On colorie la partie gauche Pixel_dans_menu(Debut_X,y_pos,Couleur_Haut_gauche); BLOCK_MENU[y_pos][Debut_X]=Couleur_Haut_gauche; // On colorie la partie droite Pixel_dans_menu(Fin_X,y_pos,Couleur_Bas_droite); BLOCK_MENU[y_pos][Fin_X]=Couleur_Bas_droite; } // On colorie la partie basse for (x_pos=Debut_X+1;x_pos<=Fin_X;x_pos++) { Pixel_dans_menu(x_pos,Fin_Y,Couleur_Bas_droite); BLOCK_MENU[Fin_Y][x_pos]=Couleur_Bas_droite; } break; case FORME_BOUTON_TRIANGLE_HAUT_GAUCHE: // On colorie le point haut droit Pixel_dans_menu(Fin_X,Debut_Y,Couleur_Diagonale); BLOCK_MENU[Debut_Y][Fin_X]=Couleur_Diagonale; // On colorie le point bas gauche Pixel_dans_menu(Debut_X,Fin_Y,Couleur_Diagonale); BLOCK_MENU[Fin_Y][Debut_X]=Couleur_Diagonale; // On colorie le coin haut gauche for (x_pos=0;x_posSPECIAL_CLICK_RIGHT) switch(Indice_Touche) { case SPECIAL_SCROLL_UP : // Scroll up if (Loupe_Mode) Scroller_loupe(0,-(Loupe_Hauteur>>2)); else Scroller_ecran(0,-(Hauteur_ecran>>3)); Touche=0; break; case SPECIAL_SCROLL_DOWN : // Scroll down if (Loupe_Mode) Scroller_loupe(0,(Loupe_Hauteur>>2)); else Scroller_ecran(0,(Hauteur_ecran>>3)); Touche=0; break; case SPECIAL_SCROLL_LEFT : // Scroll left if (Loupe_Mode) Scroller_loupe(-(Loupe_Largeur>>2),0); else Scroller_ecran(-(Largeur_ecran>>3),0); Touche=0; break; case SPECIAL_SCROLL_RIGHT : // Scroll right if (Loupe_Mode) Scroller_loupe((Loupe_Largeur>>2),0); else Scroller_ecran((Largeur_ecran>>3),0); Touche=0; break; case SPECIAL_SCROLL_UP_FAST : // Scroll up faster if (Loupe_Mode) Scroller_loupe(0,-(Loupe_Hauteur>>1)); else Scroller_ecran(0,-(Hauteur_ecran>>2)); Touche=0; break; case SPECIAL_SCROLL_DOWN_FAST : // Scroll down faster if (Loupe_Mode) Scroller_loupe(0,(Loupe_Hauteur>>1)); else Scroller_ecran(0,(Hauteur_ecran>>2)); Touche=0; break; case SPECIAL_SCROLL_LEFT_FAST : // Scroll left faster if (Loupe_Mode) Scroller_loupe(-(Loupe_Largeur>>1),0); else Scroller_ecran(-(Largeur_ecran>>2),0); Touche=0; break; case SPECIAL_SCROLL_RIGHT_FAST : // Scroll right faster if (Loupe_Mode) Scroller_loupe((Loupe_Largeur>>1),0); else Scroller_ecran((Largeur_ecran>>2),0); Touche=0; break; case SPECIAL_SCROLL_UP_SLOW : // Scroll up slower if (Loupe_Mode) Scroller_loupe(0,-1); else Scroller_ecran(0,-1); Touche=0; break; case SPECIAL_SCROLL_DOWN_SLOW : // Scroll down slower if (Loupe_Mode) Scroller_loupe(0,1); else Scroller_ecran(0,1); Touche=0; break; case SPECIAL_SCROLL_LEFT_SLOW : // Scroll left slower if (Loupe_Mode) Scroller_loupe(-1,0); else Scroller_ecran(-1,0); Touche=0; break; case SPECIAL_SCROLL_RIGHT_SLOW : // Scroll right slower if (Loupe_Mode) Scroller_loupe(1,0); else Scroller_ecran(1,0); Touche=0; break; case SPECIAL_NEXT_FORECOLOR : // Next foreground color Special_Next_forecolor(); Touche=0; break; case SPECIAL_PREVIOUS_FORECOLOR : // Previous foreground color Special_Previous_forecolor(); Touche=0; break; case SPECIAL_NEXT_BACKCOLOR : // Next background color Special_Next_backcolor(); Touche=0; break; case SPECIAL_PREVIOUS_BACKCOLOR : // Previous background color Special_Previous_backcolor(); Touche=0; break; case SPECIAL_RETRECIR_PINCEAU: // Rétrécir le pinceau Retrecir_pinceau(); Touche=0; break; case SPECIAL_GROSSIR_PINCEAU: // Grossir le pinceau Grossir_pinceau(); Touche=0; break; case SPECIAL_NEXT_USER_FORECOLOR : // Next user-defined foreground color Message_Non_disponible(); // !!! TEMPORAIRE !!! //Special_Next_user_forecolor(); Touche=0; break; case SPECIAL_PREVIOUS_USER_FORECOLOR : // Previous user-defined foreground color Message_Non_disponible(); // !!! TEMPORAIRE !!! //Special_Previous_user_forecolor(); Touche=0; break; case SPECIAL_NEXT_USER_BACKCOLOR : // Next user-defined background color Message_Non_disponible(); // !!! TEMPORAIRE !!! //Special_Next_user_backcolor(); Touche=0; break; case SPECIAL_PREVIOUS_USER_BACKCOLOR : // Previous user-defined background color Message_Non_disponible(); // !!! TEMPORAIRE !!! //Special_Previous_user_backcolor(); Touche=0; break; case SPECIAL_SHOW_HIDE_CURSOR : // Show / Hide cursor Effacer_curseur(); Cacher_curseur=!Cacher_curseur; Afficher_curseur(); Touche=0; break; case SPECIAL_PINCEAU_POINT : // Paintbrush = "." Effacer_curseur(); Pinceau_Forme=FORME_PINCEAU_ROND; Modifier_pinceau(1,1); Changer_la_forme_du_pinceau(FORME_PINCEAU_ROND); Afficher_curseur(); Touche=0; break; case SPECIAL_DESSIN_CONTINU : // Continuous freehand drawing Enclencher_bouton(BOUTON_DESSIN,A_GAUCHE); // ATTENTION CE TRUC EST MOCHE ET VA MERDER SI ON SE MET A UTILISER DES BOUTONS POPUPS while (Operation_en_cours!=OPERATION_DESSIN_CONTINU) Enclencher_bouton(BOUTON_DESSIN,A_DROITE); Touche=0; break; case SPECIAL_FLIP_X : // Flip X Effacer_curseur(); Flip_X_LOWLEVEL(); Afficher_curseur(); Touche=0; break; case SPECIAL_FLIP_Y : // Flip Y Effacer_curseur(); Flip_Y_LOWLEVEL(); Afficher_curseur(); Touche=0; break; case SPECIAL_ROTATE_90 : // 90° brush rotation Effacer_curseur(); Rotate_90_deg(); Afficher_curseur(); Touche=0; break; case SPECIAL_ROTATE_180 : // 180° brush rotation Effacer_curseur(); if (Brosse_Hauteur&1) { // Brosse de hauteur impaire Flip_X_LOWLEVEL(); Flip_Y_LOWLEVEL(); } else Rotate_180_deg_LOWLEVEL(); Brosse_Decalage_X=(Brosse_Largeur>>1); Brosse_Decalage_Y=(Brosse_Hauteur>>1); Afficher_curseur(); Touche=0; break; case SPECIAL_STRETCH : // Stretch brush Effacer_curseur(); Demarrer_pile_operation(OPERATION_ETIRER_BROSSE); Afficher_curseur(); Touche=0; break; case SPECIAL_DISTORT : // Distort brush Message_Non_disponible(); // !!! TEMPORAIRE !!! Touche=0; break; case SPECIAL_ROTATE_ANY_ANGLE : // Rotate brush by any angle Effacer_curseur(); Demarrer_pile_operation(OPERATION_TOURNER_BROSSE); Afficher_curseur(); Touche=0; break; case SPECIAL_OUTLINE : // Outline brush Effacer_curseur(); Outline_brush(); Afficher_curseur(); Touche=0; break; case SPECIAL_NIBBLE : // Nibble brush Effacer_curseur(); Nibble_brush(); Afficher_curseur(); Touche=0; break; case SPECIAL_GET_BRUSH_COLORS : // Get colors from brush Get_colors_from_brush(); Touche=0; break; case SPECIAL_RECOLORIZE_BRUSH : // Recolorize brush Effacer_curseur(); Remap_brosse(); Afficher_curseur(); Touche=0; break; case SPECIAL_LOAD_BRUSH : Load_picture(0); Touche=0; break; case SPECIAL_SAVE_BRUSH : Save_picture(0); Touche=0; break; case SPECIAL_ZOOM_IN : // Zoom in Zoom(+1); Touche=0; break; case SPECIAL_ZOOM_OUT : // Zoom out Zoom(-1); Touche=0; break; case SPECIAL_CENTER_ATTACHMENT : // Center brush attachment Effacer_curseur(); Brosse_Decalage_X=(Brosse_Largeur>>1); Brosse_Decalage_Y=(Brosse_Hauteur>>1); Afficher_curseur(); Touche=0; break; case SPECIAL_TOP_LEFT_ATTACHMENT : // Top-left brush attachment Effacer_curseur(); Brosse_Decalage_X=0; Brosse_Decalage_Y=0; Afficher_curseur(); Touche=0; break; case SPECIAL_TOP_RIGHT_ATTACHMENT : // Top-right brush attachment Effacer_curseur(); Brosse_Decalage_X=(Brosse_Largeur-1); Brosse_Decalage_Y=0; Afficher_curseur(); Touche=0; break; case SPECIAL_BOTTOM_LEFT_ATTACHMENT : // Bottom-left brush attachment Effacer_curseur(); Brosse_Decalage_X=0; Brosse_Decalage_Y=(Brosse_Hauteur-1); Afficher_curseur(); Touche=0; break; case SPECIAL_BOTTOM_RIGHT_ATTACHMENT : // Bottom right brush attachment Effacer_curseur(); Brosse_Decalage_X=(Brosse_Largeur-1); Brosse_Decalage_Y=(Brosse_Hauteur-1); Afficher_curseur(); Touche=0; break; case SPECIAL_EXCLUDE_COLORS_MENU : // Exclude colors menu Menu_Tag_couleurs("Tag colors to exclude",Exclude_color,&Temp,1, NULL); Touche=0; break; case SPECIAL_INVERT_SIEVE : Inverser_trame(); Touche=0; break; case SPECIAL_SHADE_MODE : Bouton_Shade_Mode(); Touche=0; break; case SPECIAL_SHADE_MENU : Bouton_Shade_Menu(); Touche=0; break; case SPECIAL_QUICK_SHADE_MODE : Bouton_Quick_shade_Mode(); Touche=0; break; case SPECIAL_QUICK_SHADE_MENU : Bouton_Quick_shade_Menu(); Touche=0; break; case SPECIAL_STENCIL_MODE : Bouton_Stencil_Mode(); Touche=0; break; case SPECIAL_STENCIL_MENU : Bouton_Menu_Stencil(); Touche=0; break; case SPECIAL_MASK_MODE : Bouton_Mask_Mode(); Touche=0; break; case SPECIAL_MASK_MENU : Bouton_Mask_Menu(); Touche=0; break; case SPECIAL_GRID_MODE : Bouton_Snap_Mode(); Touche=0; break; case SPECIAL_GRID_MENU : Bouton_Menu_Grille(); Touche=0; break; case SPECIAL_SIEVE_MODE : Bouton_Trame_Mode(); Touche=0; break; case SPECIAL_SIEVE_MENU : Bouton_Trame_Menu(); Touche=0; break; case SPECIAL_COLORIZE_MODE : Bouton_Colorize_Mode(); Touche=0; break; case SPECIAL_COLORIZE_MENU : Bouton_Colorize_Menu(); Touche=0; break; case SPECIAL_SMOOTH_MODE : Bouton_Smooth_Mode(); Touche=0; break; case SPECIAL_SMOOTH_MENU : Bouton_Smooth_Menu(); Touche=0; break; case SPECIAL_SMEAR_MODE : Bouton_Smear_Mode(); Touche=0; break; case SPECIAL_TILING_MODE : Bouton_Tiling_Mode(); Touche=0; break; case SPECIAL_TILING_MENU : Bouton_Tiling_Menu(); Touche=0; break; default : // Gestion des touches de raccourci de bouton: // Pour chaque bouton Bouton_Touche=-1; for (Indice_bouton=0;Indice_bouton=SPECIAL_SHADE_MODE) && (Indice_Touche<=SPECIAL_TILING_MENU)) { Effacer_curseur(); Tracer_cadre_de_bouton_du_menu(BOUTON_EFFETS, (Shade_Mode||Quick_shade_Mode||Colorize_Mode||Smooth_Mode||Tiling_Mode||Smear_Mode||Stencil_Mode||Mask_Mode||Trame_Mode||Snap_Mode)); Afficher_curseur(); } } } else Wait_VBL(); // S'il n'y a pas d'évènement, on ne gère pas tout ça et on attend un peu. La partie en dessous doit être exécutée quand // même pour les trucs asynchrones, par exemple le spray. // Gestion de la souris Curseur_dans_menu=(Mouse_Y>=Menu_Ordonnee) || ( (Loupe_Mode) && (Mouse_X>=Principal_Split) && (Mouse_X=Menu_Ordonnee) { if (Indice_bouton>=0) { Enclencher_bouton(Indice_bouton,Mouse_K); Indice_bouton_precedent=-1; } } else if (Loupe_Mode) Deplacer_Split(); } } // we need to refresh that one as we may come from a sub window Curseur_dans_menu=(Mouse_Y>=Menu_Ordonnee) || ( (Loupe_Mode) && (Mouse_X>=Principal_Split) && (Mouse_X>1; Fenetre_Pos_Y=(Hauteur_ecran-(height*Menu_Facteur_Y))>>1; // Sauvegarde de ce que la fenêtre remplace Sauve_fond(&(Fond_fenetre[Fenetre-1]), Fenetre_Pos_X, Fenetre_Pos_Y, width, height); // Fenêtre grise Block(Fenetre_Pos_X+(Menu_Facteur_X<<1),Fenetre_Pos_Y+(Menu_Facteur_Y<<1),(width-4)*Menu_Facteur_X,(height-4)*Menu_Facteur_Y,CM_Clair); // -- Cadre de la fenêtre ----- --- -- - - // Cadre noir puis en relief Fenetre_Afficher_cadre_mono(0,0,width,height,CM_Noir); Fenetre_Afficher_cadre_bombe(1,1,width-2,height-2); // Barre sous le titre Block(Fenetre_Pos_X+(Menu_Facteur_X<<3),Fenetre_Pos_Y+(11*Menu_Facteur_Y),(width-16)*Menu_Facteur_X,Menu_Facteur_Y,CM_Fonce); Block(Fenetre_Pos_X+(Menu_Facteur_X<<3),Fenetre_Pos_Y+(12*Menu_Facteur_Y),(width-16)*Menu_Facteur_X,Menu_Facteur_Y,CM_Blanc); Print_dans_fenetre((width-(strlen(title)<<3))>>1,3,title,CM_Noir,CM_Clair); if (Fenetre == 1) { Menu_visible_avant_fenetre=Menu_visible; Menu_visible=0; Menu_Ordonnee_avant_fenetre=Menu_Ordonnee; Menu_Ordonnee=Hauteur_ecran; Forme_curseur_avant_fenetre=Forme_curseur; Forme_curseur=FORME_CURSEUR_FLECHE; Cacher_pinceau_avant_fenetre=Cacher_pinceau; Cacher_pinceau=1; } // Initialisation des listes de boutons de la fenêtre Fenetre_Liste_boutons_normal =NULL; Fenetre_Liste_boutons_palette =NULL; Fenetre_Liste_boutons_scroller=NULL; Fenetre_Liste_boutons_special =NULL; Fenetre_Liste_boutons_dropdown=NULL; Nb_boutons_fenetre =0; } //----------------------- Fermer une fenêtre d'options ----------------------- void Fermer_fenetre(void) // Lors de l'appel à cette procedure, la souris doit être affichée. // En sortie de cette procedure, la souris est effacée. { T_Bouton_normal * Temp1; T_Bouton_palette * Temp2; T_Bouton_scroller * Temp3; T_Bouton_special * Temp4; T_Bouton_dropdown * Temp5; Effacer_curseur(); while (Fenetre_Liste_boutons_normal) { Temp1=Fenetre_Liste_boutons_normal->Next; free(Fenetre_Liste_boutons_normal); Fenetre_Liste_boutons_normal=Temp1; } while (Fenetre_Liste_boutons_palette) { Temp2=Fenetre_Liste_boutons_palette->Next; free(Fenetre_Liste_boutons_palette); Fenetre_Liste_boutons_palette=Temp2; } while (Fenetre_Liste_boutons_scroller) { Temp3=Fenetre_Liste_boutons_scroller->Next; free(Fenetre_Liste_boutons_scroller); Fenetre_Liste_boutons_scroller=Temp3; } while (Fenetre_Liste_boutons_special) { Temp4=Fenetre_Liste_boutons_special->Next; free(Fenetre_Liste_boutons_special); Fenetre_Liste_boutons_special=Temp4; } while (Fenetre_Liste_boutons_dropdown) { Temp5=Fenetre_Liste_boutons_dropdown->Next; Fenetre_Dropdown_vider_choix(Fenetre_Liste_boutons_dropdown); free(Fenetre_Liste_boutons_dropdown); Fenetre_Liste_boutons_dropdown=Temp5; } if (Fenetre != 1) { // Restore de ce que la fenêtre cachait Restaure_fond(Fond_fenetre[Fenetre-1], Fenetre_Pos_X, Fenetre_Pos_Y, Fenetre_Largeur, Fenetre_Hauteur); Fond_fenetre[Fenetre-1]=NULL; UpdateRect(Fenetre_Pos_X,Fenetre_Pos_Y,Fenetre_Largeur*Menu_Facteur_X,Fenetre_Hauteur*Menu_Facteur_Y); Fenetre--; } else { free(Fond_fenetre[Fenetre-1]); Fond_fenetre[Fenetre-1]=NULL; Fenetre--; Cacher_pinceau=Cacher_pinceau_avant_fenetre; Calculer_coordonnees_pinceau(); Menu_Ordonnee=Menu_Ordonnee_avant_fenetre; Menu_visible=Menu_visible_avant_fenetre; Forme_curseur=Forme_curseur_avant_fenetre; Afficher_ecran(); Afficher_menu(); } Touche=0; Mouse_K=0; Old_MX = -1; Old_MY = -1; } //---------------- Dessiner un bouton normal dans une fenêtre ---------------- void Fenetre_Dessiner_bouton_normal(word x_pos,word y_pos,word width,word height, char * title,byte Lettre_soulignee,byte clickable) { byte Couleur_titre; word Pos_texte_X,Pos_texte_Y; if (clickable) { Fenetre_Afficher_cadre_bombe(x_pos,y_pos,width,height); Fenetre_Afficher_cadre_general(x_pos-1,y_pos-1,width+2,height+2,CM_Noir,CM_Noir,CM_Fonce,CM_Fonce,CM_Fonce); Couleur_titre=CM_Noir; } else { Fenetre_Afficher_cadre_bombe(x_pos,y_pos,width,height); Fenetre_Afficher_cadre_mono(x_pos-1,y_pos-1,width+2,height+2,CM_Clair); Couleur_titre=CM_Fonce; } Pos_texte_X=x_pos+( (width-(strlen(title)<<3)+1) >>1 ); Pos_texte_Y=y_pos+((height-7)>>1); Print_dans_fenetre(Pos_texte_X,Pos_texte_Y,title,Couleur_titre,CM_Clair); if (Lettre_soulignee) Block(Fenetre_Pos_X+((Pos_texte_X+((Lettre_soulignee-1)<<3))*Menu_Facteur_X), Fenetre_Pos_Y+((Pos_texte_Y+8)*Menu_Facteur_Y), Menu_Facteur_X<<3,Menu_Facteur_Y,CM_Fonce); } // -- Bouton normal enfoncé dans la fenêtre -- void Fenetre_Enfoncer_bouton_normal(word x_pos,word y_pos,word width,word height) { Fenetre_Afficher_cadre_general(x_pos,y_pos,width,height,CM_Fonce,CM_Noir,CM_Fonce,CM_Fonce,CM_Noir); UpdateRect(Fenetre_Pos_X+x_pos*Menu_Facteur_X, Fenetre_Pos_Y+y_pos*Menu_Facteur_Y, width*Menu_Facteur_X, height*Menu_Facteur_Y); } // -- Bouton normal désenfoncé dans la fenêtre -- void Fenetre_Desenfoncer_bouton_normal(word x_pos,word y_pos,word width,word height) { Fenetre_Afficher_cadre_bombe(x_pos,y_pos,width,height); UpdateRect(Fenetre_Pos_X+x_pos*Menu_Facteur_X, Fenetre_Pos_Y+y_pos*Menu_Facteur_Y, width*Menu_Facteur_X, height*Menu_Facteur_Y); } //--------------- Dessiner un bouton palette dans une fenêtre ---------------- void Fenetre_Dessiner_bouton_palette(word x_pos,word y_pos) { word Couleur; for (Couleur=0; Couleur<=255; Couleur++) Block( Fenetre_Pos_X+((((Couleur >> 4)*10)+x_pos+6)*Menu_Facteur_X),Fenetre_Pos_Y+((((Couleur & 15)*5)+y_pos+3)*Menu_Facteur_Y),Menu_Facteur_X*5,Menu_Facteur_Y*5,Couleur); Fenetre_Afficher_cadre(x_pos,y_pos,164,86); } // -------------------- Effacer les TAGs sur les palette --------------------- // Cette fonct° ne sert plus que lorsqu'on efface les tags dans le menu Spray. void Fenetre_Effacer_tags(void) { word Origine_X; word Origine_Y; word x_pos; word Pos_fenetre_X; //word Pos_fenetre_Y; Origine_X=Fenetre_Pos_X+(Fenetre_Liste_boutons_palette->Pos_X+3)*Menu_Facteur_X; Origine_Y=Fenetre_Pos_Y+(Fenetre_Liste_boutons_palette->Pos_Y+3)*Menu_Facteur_Y; for (x_pos=0,Pos_fenetre_X=Origine_X;x_pos<16;x_pos++,Pos_fenetre_X+=(Menu_Facteur_X*10)) Block(Pos_fenetre_X,Origine_Y,Menu_Facteur_X*3,Menu_Facteur_Y*80,CM_Clair); UpdateRect(Origine_X,Origine_Y,ToWinL(160),ToWinH(80)); } // ---- Tracer les TAGs sur les palettes du menu Palette ou du menu Shade ---- void Tagger_intervalle_palette(byte start,byte end) { word Origine_X; word Origine_Y; //word x_pos; word y_pos; //word Pos_fenetre_X; word Pos_fenetre_Y; word Indice; // On efface les anciens TAGs for (Indice=0;Indice<=start;Indice++) Block(Fenetre_Pos_X+(Fenetre_Liste_boutons_palette->Pos_X+3+((Indice>>4)*10))*Menu_Facteur_X, Fenetre_Pos_Y+(Fenetre_Liste_boutons_palette->Pos_Y+3+((Indice&15)* 5))*Menu_Facteur_Y, Menu_Facteur_X*3,Menu_Facteur_Y*5,CM_Clair); for (Indice=end;Indice<256;Indice++) Block(Fenetre_Pos_X+(Fenetre_Liste_boutons_palette->Pos_X+3+((Indice>>4)*10))*Menu_Facteur_X, Fenetre_Pos_Y+(Fenetre_Liste_boutons_palette->Pos_Y+3+((Indice&15)* 5))*Menu_Facteur_Y, Menu_Facteur_X*3,Menu_Facteur_Y*5,CM_Clair); // On affiche le 1er TAG Origine_X=(Fenetre_Liste_boutons_palette->Pos_X+3)+(start>>4)*10; Origine_Y=(Fenetre_Liste_boutons_palette->Pos_Y+3)+(start&15)* 5; for (y_pos=0,Pos_fenetre_Y=Origine_Y ;y_pos<5;y_pos++,Pos_fenetre_Y++) Pixel_dans_fenetre(Origine_X ,Pos_fenetre_Y,CM_Noir); for (y_pos=0,Pos_fenetre_Y=Origine_Y+1;y_pos<3;y_pos++,Pos_fenetre_Y++) Pixel_dans_fenetre(Origine_X+1,Pos_fenetre_Y,CM_Noir); Pixel_dans_fenetre(Origine_X+2,Origine_Y+2,CM_Noir); if (start!=end) { // On complète le 1er TAG Pixel_dans_fenetre(Origine_X+1,Origine_Y+4,CM_Noir); // On affiche le 2ème TAG Origine_X=(Fenetre_Liste_boutons_palette->Pos_X+3)+(end>>4)*10; Origine_Y=(Fenetre_Liste_boutons_palette->Pos_Y+3)+(end&15)* 5; for (y_pos=0,Pos_fenetre_Y=Origine_Y; y_pos<5; y_pos++,Pos_fenetre_Y++) Pixel_dans_fenetre(Origine_X ,Pos_fenetre_Y,CM_Noir); for (y_pos=0,Pos_fenetre_Y=Origine_Y; y_pos<4; y_pos++,Pos_fenetre_Y++) Pixel_dans_fenetre(Origine_X+1,Pos_fenetre_Y,CM_Noir); Pixel_dans_fenetre(Origine_X+2,Origine_Y+2,CM_Noir); // On TAG toutes les couleurs intermédiaires for (Indice=start+1;IndicePos_X+3+((Indice>>4)*10))*Menu_Facteur_X, Fenetre_Pos_Y+(Fenetre_Liste_boutons_palette->Pos_Y+3+((Indice&15)* 5))*Menu_Facteur_Y, Menu_Facteur_X*2,Menu_Facteur_Y*5,CM_Noir); // On efface l'éventuelle pointe d'une ancienne extrémité de l'intervalle Pixel_dans_fenetre(Fenetre_Liste_boutons_palette->Pos_X+5+((Indice>>4)*10), Fenetre_Liste_boutons_palette->Pos_Y+5+((Indice&15)* 5), CM_Clair); } } UpdateRect(ToWinX(Fenetre_Liste_boutons_palette->Pos_X+3),ToWinY(Fenetre_Liste_boutons_palette->Pos_Y+3),ToWinL(12*16),ToWinH(5*16)); } //------------------ Dessiner un scroller dans une fenêtre ------------------- void Calculer_hauteur_curseur_jauge(T_Bouton_scroller * button) { if (button->Nb_elements>button->Nb_visibles) { button->Hauteur_curseur=(button->Nb_visibles*(button->Height-24))/button->Nb_elements; if (!(button->Hauteur_curseur)) button->Hauteur_curseur=1; } else { button->Hauteur_curseur=button->Height-24; } } void Fenetre_Dessiner_jauge(T_Bouton_scroller * button) { word Position_curseur_jauge; Position_curseur_jauge=button->Pos_Y+12; Block(Fenetre_Pos_X+(button->Pos_X*Menu_Facteur_X), Fenetre_Pos_Y+(Position_curseur_jauge*Menu_Facteur_Y), 11*Menu_Facteur_X,(button->Height-24)*Menu_Facteur_Y,CM_Noir/*CM_Fonce*/); if (button->Nb_elements>button->Nb_visibles) Position_curseur_jauge+=Round_div(button->Position*(button->Height-24-button->Hauteur_curseur),button->Nb_elements-button->Nb_visibles); Block(Fenetre_Pos_X+(button->Pos_X*Menu_Facteur_X), Fenetre_Pos_Y+(Position_curseur_jauge*Menu_Facteur_Y), 11*Menu_Facteur_X,button->Hauteur_curseur*Menu_Facteur_Y,CM_Fonce/*CM_Blanc*/); UpdateRect(Fenetre_Pos_X+(button->Pos_X*Menu_Facteur_X), Fenetre_Pos_Y+button->Pos_Y*Menu_Facteur_Y, 11*Menu_Facteur_X,(button->Height)*Menu_Facteur_Y); } void Fenetre_Dessiner_bouton_scroller(T_Bouton_scroller * button) { Fenetre_Afficher_cadre_general(button->Pos_X-1,button->Pos_Y-1,13,button->Height+2,CM_Noir,CM_Noir,CM_Fonce,CM_Fonce,CM_Fonce); Fenetre_Afficher_cadre_mono(button->Pos_X-1,button->Pos_Y+11,13,button->Height-22,CM_Noir); Fenetre_Afficher_cadre_bombe(button->Pos_X,button->Pos_Y,11,11); Fenetre_Afficher_cadre_bombe(button->Pos_X,button->Pos_Y+button->Height-11,11,11); Print_dans_fenetre(button->Pos_X+2,button->Pos_Y+2,"\030",CM_Noir,CM_Clair); Print_dans_fenetre(button->Pos_X+2,button->Pos_Y+button->Height-9,"\031",CM_Noir,CM_Clair); Fenetre_Dessiner_jauge(button); } //--------------- Dessiner une zone de saisie dans une fenêtre --------------- void Fenetre_Dessiner_bouton_saisie(word x_pos,word y_pos,word Largeur_en_caracteres) { Fenetre_Afficher_cadre_creux(x_pos,y_pos,(Largeur_en_caracteres<<3)+3,11); } //------------ Modifier le contenu (caption) d'une zone de saisie ------------ void Fenetre_Contenu_bouton_saisie(T_Bouton_special * button, char * content) { Print_dans_fenetre_limite(button->Pos_X+2,button->Pos_Y+2,content,button->Width/8,CM_Noir,CM_Clair); } //------------ Effacer le contenu (caption) d'une zone de saisie ------------ void Fenetre_Effacer_bouton_saisie(T_Bouton_special * button) { Block((button->Pos_X+2)*Menu_Facteur_X+Fenetre_Pos_X,(button->Pos_Y+2)*Menu_Facteur_Y+Fenetre_Pos_Y,(button->Width/8)*8*Menu_Facteur_X,8*Menu_Facteur_Y,CM_Clair); UpdateRect((button->Pos_X+2)*Menu_Facteur_X+Fenetre_Pos_X,(button->Pos_Y+2)*Menu_Facteur_Y+Fenetre_Pos_Y,button->Width/8*8*Menu_Facteur_X,8*Menu_Facteur_Y); } //------ Rajout d'un bouton à la liste de ceux présents dans la fenêtre ------ T_Bouton_normal * Fenetre_Definir_bouton_normal(word x_pos, word y_pos, word width, word height, char * title, byte Lettre_soulignee, byte clickable, word shortcut) { T_Bouton_normal * Temp=NULL; Nb_boutons_fenetre++; if (clickable) { Temp=(T_Bouton_normal *)malloc(sizeof(T_Bouton_normal)); Temp->Number =Nb_boutons_fenetre; Temp->Pos_X =x_pos; Temp->Pos_Y =y_pos; Temp->Width =width; Temp->Height =height; Temp->Raccourci=shortcut; Temp->Repetable=0; Temp->Next=Fenetre_Liste_boutons_normal; Fenetre_Liste_boutons_normal=Temp; } Fenetre_Dessiner_bouton_normal(x_pos,y_pos,width,height,title,Lettre_soulignee,clickable); return Temp; } //------ Rajout d'un bouton à la liste de ceux présents dans la fenêtre ------ T_Bouton_normal * Fenetre_Definir_bouton_repetable(word x_pos, word y_pos, word width, word height, char * title, byte Lettre_soulignee, byte clickable, word shortcut) { T_Bouton_normal * Temp=NULL; Nb_boutons_fenetre++; if (clickable) { Temp=(T_Bouton_normal *)malloc(sizeof(T_Bouton_normal)); Temp->Number =Nb_boutons_fenetre; Temp->Pos_X =x_pos; Temp->Pos_Y =y_pos; Temp->Width =width; Temp->Height =height; Temp->Raccourci=shortcut; Temp->Repetable=1; Temp->Next=Fenetre_Liste_boutons_normal; Fenetre_Liste_boutons_normal=Temp; } Fenetre_Dessiner_bouton_normal(x_pos,y_pos,width,height,title,Lettre_soulignee,clickable); return Temp; } T_Bouton_palette * Fenetre_Definir_bouton_palette(word x_pos, word y_pos) { T_Bouton_palette * Temp; Temp=(T_Bouton_palette *)malloc(sizeof(T_Bouton_palette)); Temp->Number =++Nb_boutons_fenetre; Temp->Pos_X =x_pos; Temp->Pos_Y =y_pos; Temp->Next=Fenetre_Liste_boutons_palette; Fenetre_Liste_boutons_palette=Temp; Fenetre_Dessiner_bouton_palette(x_pos,y_pos); return Temp; } T_Bouton_scroller * Fenetre_Definir_bouton_scroller(word x_pos, word y_pos, word height, word nb_elements, word nb_elements_visible, word Position_initiale) { T_Bouton_scroller * Temp; Temp=(T_Bouton_scroller *)malloc(sizeof(T_Bouton_scroller)); Temp->Number =++Nb_boutons_fenetre; Temp->Pos_X =x_pos; Temp->Pos_Y =y_pos; Temp->Height =height; Temp->Nb_elements =nb_elements; Temp->Nb_visibles =nb_elements_visible; Temp->Position =Position_initiale; Calculer_hauteur_curseur_jauge(Temp); Temp->Next=Fenetre_Liste_boutons_scroller; Fenetre_Liste_boutons_scroller=Temp; Fenetre_Dessiner_bouton_scroller(Temp); return Temp; } T_Bouton_special * Fenetre_Definir_bouton_special(word x_pos,word y_pos,word width,word height) { T_Bouton_special * Temp; Temp=(T_Bouton_special *)malloc(sizeof(T_Bouton_special)); Temp->Number =++Nb_boutons_fenetre; Temp->Pos_X =x_pos; Temp->Pos_Y =y_pos; Temp->Width =width; Temp->Height =height; Temp->Next=Fenetre_Liste_boutons_special; Fenetre_Liste_boutons_special=Temp; return Temp; } T_Bouton_special * Fenetre_Definir_bouton_saisie(word x_pos,word y_pos,word Largeur_en_caracteres) { T_Bouton_special *Temp; Temp=Fenetre_Definir_bouton_special(x_pos,y_pos,(Largeur_en_caracteres<<3)+3,11); Fenetre_Dessiner_bouton_saisie(x_pos,y_pos,Largeur_en_caracteres); return Temp; } T_Bouton_dropdown * Fenetre_Definir_bouton_dropdown(word x_pos,word y_pos,word width,word height,word dropdown_width,char *label,byte display_choice,byte display_centered,byte display_arrow,byte active_button) { T_Bouton_dropdown *Temp; Temp=(T_Bouton_dropdown *)malloc(sizeof(T_Bouton_dropdown)); Temp->Number =++Nb_boutons_fenetre; Temp->Pos_X =x_pos; Temp->Pos_Y =y_pos; Temp->Width =width; Temp->Height =height; Temp->Affiche_choix =display_choice; Temp->Premier_choix=NULL; Temp->Largeur_choix=dropdown_width?dropdown_width:width; Temp->Affiche_centre=display_centered; Temp->Affiche_fleche=display_arrow; Temp->Bouton_actif=active_button; Temp->Next=Fenetre_Liste_boutons_dropdown; Fenetre_Liste_boutons_dropdown=Temp; Fenetre_Dessiner_bouton_normal(x_pos,y_pos,width,height,"",-1,1); if (label && label[0]) Print_dans_fenetre(Temp->Pos_X+2,Temp->Pos_Y+(Temp->Height-7)/2,label,CM_Noir,CM_Clair); if (display_arrow) Fenetre_Afficher_sprite_drive(Temp->Pos_X+Temp->Width-10,Temp->Pos_Y+(Temp->Height-7)/2,6); return Temp; } // Ajoute un choix à une dropdown. Le libellé est seulement référencé, // il doit pointer sur une zone qui doit être encore valide à la fermeture // de la fenêtre (comprise). void Fenetre_Dropdown_choix(T_Bouton_dropdown * dropdown, word btn_number, const char *label) { T_Dropdown_choix *Temp; T_Dropdown_choix *last; Temp=(T_Dropdown_choix *)malloc(sizeof(T_Dropdown_choix)); Temp->Number =btn_number; Temp->Label=label; Temp->Next=NULL; last=dropdown->Premier_choix; if (last) { // On cherche le dernier élément for (;last->Next;last=last->Next) ; last->Next=Temp; } else { dropdown->Premier_choix=Temp; } } // ------------- Suppression de tous les choix d'une dropdown --------- void Fenetre_Dropdown_vider_choix(T_Bouton_dropdown * dropdown) { T_Dropdown_choix * Choix_suivant; while (dropdown->Premier_choix) { Choix_suivant=dropdown->Premier_choix->Next; free(dropdown->Premier_choix); dropdown->Premier_choix=Choix_suivant; } } //----------------------- Ouverture d'un pop-up ----------------------- void Ouvrir_popup(word x_pos, word y_pos, word width,word height) // Lors de l'appel à cette procédure, la souris doit être affichée. // En sortie de cette procedure, la souris est effacée. // Note : les pop-ups sont gérés comme s'ils étaient des sous-fenêtres, ils ont donc leur propre boucle d'évènements et tout, on peut ajouter des widgets dedans, ... // Les différences sont surtout graphiques : // -Possibilité de préciser la position XY // -Pas de titre // -Pas de cadre en relief mais seulement un plat, et il est blanc au lieu de noir. { Fenetre++; Fenetre_Largeur=width; Fenetre_Hauteur=height; Fenetre_Pos_X=x_pos; Fenetre_Pos_Y=y_pos; // Sauvegarde de ce que la fenêtre remplace Sauve_fond(&(Fond_fenetre[Fenetre-1]), Fenetre_Pos_X, Fenetre_Pos_Y, width, height); /* // Fenêtre grise Block(Fenetre_Pos_X+1*Menu_Facteur_X, Fenetre_Pos_Y+1*Menu_Facteur_Y, (width-2)*Menu_Facteur_X,(height-2)*Menu_Facteur_Y,CM_Clair); // Cadre noir puis en relief Fenetre_Afficher_cadre_mono(0,0,width,height,CM_Blanc); */ if (Fenetre == 1) { Menu_visible_avant_fenetre=Menu_visible; Menu_visible=0; Menu_Ordonnee_avant_fenetre=Menu_Ordonnee; Menu_Ordonnee=Hauteur_ecran; Forme_curseur_avant_fenetre=Forme_curseur; Forme_curseur=FORME_CURSEUR_FLECHE; Cacher_pinceau_avant_fenetre=Cacher_pinceau; Cacher_pinceau=1; } // Initialisation des listes de boutons de la fenêtre Fenetre_Liste_boutons_normal =NULL; Fenetre_Liste_boutons_palette =NULL; Fenetre_Liste_boutons_scroller=NULL; Fenetre_Liste_boutons_special =NULL; Fenetre_Liste_boutons_dropdown =NULL; Nb_boutons_fenetre =0; } //----------------------- Fermer une fenêtre d'options ----------------------- void Fermer_popup(void) // Lors de l'appel à cette procedure, la souris doit être affichée. // En sortie de cette procedure, la souris est effacée. { T_Bouton_normal * Temp1; T_Bouton_palette * Temp2; T_Bouton_scroller * Temp3; T_Bouton_special * Temp4; T_Bouton_dropdown * Temp5; Effacer_curseur(); while (Fenetre_Liste_boutons_normal) { Temp1=Fenetre_Liste_boutons_normal->Next; free(Fenetre_Liste_boutons_normal); Fenetre_Liste_boutons_normal=Temp1; } while (Fenetre_Liste_boutons_palette) { Temp2=Fenetre_Liste_boutons_palette->Next; free(Fenetre_Liste_boutons_palette); Fenetre_Liste_boutons_palette=Temp2; } while (Fenetre_Liste_boutons_scroller) { Temp3=Fenetre_Liste_boutons_scroller->Next; free(Fenetre_Liste_boutons_scroller); Fenetre_Liste_boutons_scroller=Temp3; } while (Fenetre_Liste_boutons_special) { Temp4=Fenetre_Liste_boutons_special->Next; free(Fenetre_Liste_boutons_special); Fenetre_Liste_boutons_special=Temp4; } while (Fenetre_Liste_boutons_dropdown) { Fenetre_Dropdown_vider_choix(Fenetre_Liste_boutons_dropdown); Temp5=Fenetre_Liste_boutons_dropdown->Next; free(Fenetre_Liste_boutons_dropdown); Fenetre_Liste_boutons_dropdown=Temp5; } if (Fenetre != 1) { // Restore de ce que la fenêtre cachait Restaure_fond(Fond_fenetre[Fenetre-1], Fenetre_Pos_X, Fenetre_Pos_Y, Fenetre_Largeur, Fenetre_Hauteur); Fond_fenetre[Fenetre-1]=NULL; UpdateRect(Fenetre_Pos_X,Fenetre_Pos_Y,Fenetre_Largeur*Menu_Facteur_X,Fenetre_Hauteur*Menu_Facteur_Y); Fenetre--; } else { free(Fond_fenetre[Fenetre-1]); Fenetre--; Cacher_pinceau=Cacher_pinceau_avant_fenetre; Calculer_coordonnees_pinceau(); Menu_Ordonnee=Menu_Ordonnee_avant_fenetre; Menu_visible=Menu_visible_avant_fenetre; Forme_curseur=Forme_curseur_avant_fenetre; Afficher_ecran(); Afficher_menu(); } Touche=0; Mouse_K=0; Old_MX = -1; Old_MY = -1; } ////////////////////////////////////////////////////////////////////////////// // // // Mini-MOTEUR utilisé dans les fenêtres (menus des boutons...) // // // ////////////////////////////////////////////////////////////////////////////// // -- Indique si on a cliqué dans une zone définie par deux points extremes -- byte Fenetre_click_dans_zone(short Debut_X,short Debut_Y,short Fin_X,short Fin_Y) { short x_pos,y_pos; x_pos=((short)Mouse_X-Fenetre_Pos_X)/Menu_Facteur_X; y_pos=((short)Mouse_Y-Fenetre_Pos_Y)/Menu_Facteur_Y; return ((x_pos>=Debut_X) && (y_pos>=Debut_Y) && (x_pos<=Fin_X) && (y_pos<=Fin_Y)); } // --- Attend que l'on clique dans la palette pour renvoyer la couleur choisie // ou bien renvoie -1 si on a annulé l'action pas click-droit ou Escape ------ short Attendre_click_dans_palette(T_Bouton_palette * button) { short Debut_X=button->Pos_X+5; short Debut_Y=button->Pos_Y+3; short Fin_X =button->Pos_X+160; short Fin_Y =button->Pos_Y+82; byte Couleur_choisie; byte Ancien_Cacher_curseur; byte Ancien_Loupe_Mode; Effacer_curseur(); Ancien_Cacher_curseur=Cacher_curseur; Ancien_Loupe_Mode=Loupe_Mode; Loupe_Mode=0; Cacher_curseur=0; Forme_curseur=FORME_CURSEUR_CIBLE; Afficher_curseur(); for (;;) { while(!Get_input())Wait_VBL(); if (Mouse_K==A_GAUCHE) { if (Fenetre_click_dans_zone(Debut_X,Debut_Y,Fin_X,Fin_Y)) { Effacer_curseur(); Couleur_choisie=(((Mouse_X-Fenetre_Pos_X)/Menu_Facteur_X)-(button->Pos_X+2)) / 10 * 16 + (((Mouse_Y-Fenetre_Pos_Y)/Menu_Facteur_Y)-(button->Pos_Y+3)) / 5; Forme_curseur=FORME_CURSEUR_FLECHE; Cacher_curseur=Ancien_Cacher_curseur; Loupe_Mode=Ancien_Loupe_Mode; Afficher_curseur(); return Couleur_choisie; } if ((Mouse_X=Fenetre_Pos_X+(Fenetre_Largeur*Menu_Facteur_X)) || (Mouse_Y>=Fenetre_Pos_Y+(Fenetre_Hauteur*Menu_Facteur_Y)) ) { Effacer_curseur(); Couleur_choisie=Lit_pixel(Mouse_X,Mouse_Y); Forme_curseur=FORME_CURSEUR_FLECHE; Cacher_curseur=Ancien_Cacher_curseur; Loupe_Mode=Ancien_Loupe_Mode; Afficher_curseur(); return Couleur_choisie; } } if ((Mouse_K==A_DROITE) || (Touche==TOUCHE_ESC)) { Effacer_curseur(); Forme_curseur=FORME_CURSEUR_FLECHE; Cacher_curseur=Ancien_Cacher_curseur; Loupe_Mode=Ancien_Loupe_Mode; Afficher_curseur(); return -1; } } } // -------------- Récupération d'une couleur derrière un menu ---------------- void Recuperer_couleur_derriere_fenetre(byte * Couleur, byte * click) { short width=Fenetre_Largeur*Menu_Facteur_X; short height=Fenetre_Hauteur*Menu_Facteur_Y; short Ancien_X=-1; short Ancien_Y=-1; short Indice; short a,b,c,d; // Variables temporaires et multitâches... byte * Buffer; char Chaine[25]; byte Cacher_curseur_avant_recuperation; if ((Buffer=(byte *) malloc(width*height))) { Effacer_curseur(); Cacher_curseur_avant_recuperation=Cacher_curseur; Cacher_curseur=0; for (Indice=0; IndiceLargeur_ecran-width) { Nouveau_X=Largeur_ecran-width; Dx = Mouse_X - Nouveau_X; } Nouveau_Y=Mouse_Y-Dy; if (Nouveau_Y<0) { Nouveau_Y=0; Dy = Mouse_Y; } if (Nouveau_Y>Hauteur_ecran-height) { Nouveau_Y=Hauteur_ecran-height; Dy = Mouse_Y - Nouveau_Y; } if ((Nouveau_X!=Ancien_X) || (Nouveau_Y!=Ancien_Y)) { Effacer_curseur(); Ligne_horizontale_XOR(Ancien_X,Ancien_Y,width); Ligne_verticale_XOR(Ancien_X,Ancien_Y+1,height-2); Ligne_verticale_XOR(Ancien_X+width-1,Ancien_Y+1,height-2); Ligne_horizontale_XOR(Ancien_X,Ancien_Y+height-1,width); Ligne_horizontale_XOR(Nouveau_X,Nouveau_Y,width); Ligne_verticale_XOR(Nouveau_X,Nouveau_Y+1,height-2); Ligne_verticale_XOR(Nouveau_X+width-1,Nouveau_Y+1,height-2); Ligne_horizontale_XOR(Nouveau_X,Nouveau_Y+height-1,width); Afficher_curseur(); UpdateRect(Ancien_X,Ancien_Y,width,height); UpdateRect(Nouveau_X,Nouveau_Y,width,height); } } Effacer_curseur(); Ligne_horizontale_XOR(Nouveau_X,Nouveau_Y,width); Ligne_verticale_XOR(Nouveau_X,Nouveau_Y+1,height-2); Ligne_verticale_XOR(Nouveau_X+width-1,Nouveau_Y+1,height-2); Ligne_horizontale_XOR(Nouveau_X,Nouveau_Y+height-1,width); if ((Nouveau_X!=Fenetre_Pos_X) || (Nouveau_Y!=Fenetre_Pos_Y)) { a=Menu_Ordonnee; Menu_Ordonnee=Menu_Ordonnee_avant_fenetre; b=Menu_visible; Menu_visible=Menu_visible_avant_fenetre; //Afficher_ecran(); //Afficher_menu(); Menu_Ordonnee=a; Menu_visible=b; // Sauvegarde du contenu actuel de la fenêtre Sauve_fond(&Buffer, Fenetre_Pos_X, Fenetre_Pos_Y, Fenetre_Largeur, Fenetre_Hauteur); // Restore de ce que la fenêtre cachait Restaure_fond(Fond_fenetre[Fenetre-1], Fenetre_Pos_X, Fenetre_Pos_Y, Fenetre_Largeur, Fenetre_Hauteur); Fond_fenetre[Fenetre-1] = NULL; // Sauvegarde de ce que la fenêtre remplace Sauve_fond(&(Fond_fenetre[Fenetre-1]), Nouveau_X, Nouveau_Y, Fenetre_Largeur, Fenetre_Hauteur); // Raffichage de la fenêtre Restaure_fond(Buffer, Nouveau_X, Nouveau_Y, Fenetre_Largeur, Fenetre_Hauteur); Buffer = NULL; // Mise à jour du rectangle englobant UpdateRect( (Nouveau_X>Fenetre_Pos_X)?Fenetre_Pos_X:Nouveau_X, (Nouveau_Y>Fenetre_Pos_Y)?Fenetre_Pos_Y:Nouveau_Y, ((Nouveau_X>Fenetre_Pos_X)?(Nouveau_X-Fenetre_Pos_X):(Fenetre_Pos_X-Nouveau_X)) + Fenetre_Largeur*Menu_Facteur_X, ((Nouveau_Y>Fenetre_Pos_Y)?(Nouveau_Y-Fenetre_Pos_Y):(Fenetre_Pos_Y-Nouveau_Y)) + Fenetre_Hauteur*Menu_Facteur_Y); Fenetre_Pos_X=Nouveau_X; Fenetre_Pos_Y=Nouveau_Y; } else { // Update pour effacer le rectangle XOR UpdateRect(Fenetre_Pos_X, Fenetre_Pos_Y, Fenetre_Largeur*Menu_Facteur_X, Fenetre_Hauteur*Menu_Facteur_Y); } Forme_curseur=FORME_CURSEUR_FLECHE; Afficher_curseur(); } // Gestion des dropdown short Fenetre_Dropdown_click(T_Bouton_dropdown *Bouton) { short Nb_choix; short Indice_choix; short Indice_selectionne; short Ancien_Indice_selectionne; short Hauteur_boite; T_Dropdown_choix *Choix; // Taille de l'ombre portée (en plus des dimensions normales) #define OMBRE_DROITE 3 #define OMBRE_BAS 4 // Comptage des items pour calculer la taille Nb_choix=0; for (Choix=Bouton->Premier_choix; Choix!=NULL; Choix=Choix->Next) { Nb_choix++; } Hauteur_boite=3+Nb_choix*8+1; Effacer_curseur(); Fenetre_Enfoncer_bouton_normal(Bouton->Pos_X,Bouton->Pos_Y,Bouton->Width,Bouton->Height); Ouvrir_popup( Fenetre_Pos_X+(Bouton->Pos_X)*Menu_Facteur_X, Fenetre_Pos_Y+(Bouton->Pos_Y+Bouton->Height)*Menu_Facteur_Y, Bouton->Largeur_choix+OMBRE_DROITE, Hauteur_boite+OMBRE_BAS); // Dessin de la boite // Bord gauche Block(Fenetre_Pos_X,Fenetre_Pos_Y,Menu_Facteur_X,Hauteur_boite*Menu_Facteur_Y,CM_Noir); // Cadre fonce et blanc Fenetre_Afficher_cadre_bombe(1,0,Bouton->Largeur_choix-1,Hauteur_boite); // Ombre portée if (OMBRE_BAS) { Block(Fenetre_Pos_X+OMBRE_DROITE*Menu_Facteur_X, Fenetre_Pos_Y+Hauteur_boite*Menu_Facteur_Y, Bouton->Largeur_choix*Menu_Facteur_X, OMBRE_BAS*Menu_Facteur_Y, CM_Noir); Block(Fenetre_Pos_X, Fenetre_Pos_Y+Hauteur_boite*Menu_Facteur_Y, OMBRE_DROITE*Menu_Facteur_X, Menu_Facteur_Y, CM_Noir); } if (OMBRE_DROITE) { Block(Fenetre_Pos_X+Bouton->Largeur_choix*Menu_Facteur_X, Fenetre_Pos_Y+OMBRE_BAS*Menu_Facteur_Y, OMBRE_DROITE*Menu_Facteur_X, (Hauteur_boite-OMBRE_BAS)*Menu_Facteur_Y, CM_Noir); Block(Fenetre_Pos_X+Bouton->Largeur_choix*Menu_Facteur_X, Fenetre_Pos_Y, Menu_Facteur_X, OMBRE_BAS*Menu_Facteur_Y, CM_Noir); } Indice_selectionne=-1; while (1) { Ancien_Indice_selectionne = Indice_selectionne; // Fenêtre grise Block(Fenetre_Pos_X+2*Menu_Facteur_X, Fenetre_Pos_Y+1*Menu_Facteur_Y, (Bouton->Largeur_choix-3)*Menu_Facteur_X,(Hauteur_boite-2)*Menu_Facteur_Y,CM_Clair); // Affichage des items for(Choix=Bouton->Premier_choix,Indice_choix=0; Choix!=NULL; Choix=Choix->Next,Indice_choix++) { byte color_1; byte color_2; if (Indice_choix==Indice_selectionne) { color_1=CM_Blanc; color_2=CM_Fonce; Block(Fenetre_Pos_X+3*Menu_Facteur_X, Fenetre_Pos_Y+((2+Indice_choix*8)*Menu_Facteur_Y), (Bouton->Largeur_choix-5)*Menu_Facteur_X,(8)*Menu_Facteur_Y,CM_Fonce); } else { color_1=CM_Noir; color_2=CM_Clair; } Print_dans_fenetre(3,2+Indice_choix*8,Choix->Label,color_1,color_2); } UpdateRect(Fenetre_Pos_X,Fenetre_Pos_Y,Fenetre_Largeur*Menu_Facteur_X,Fenetre_Hauteur*Menu_Facteur_Y); Afficher_curseur(); do { // Attente if(!Get_input()) Wait_VBL(); // Mise à jour du survol Indice_selectionne=Fenetre_click_dans_zone(2,2,Bouton->Largeur_choix-2,Hauteur_boite-1)? (((Mouse_Y-Fenetre_Pos_Y)/Menu_Facteur_Y-2)>>3) : -1; } while (Mouse_K && Indice_selectionne==Ancien_Indice_selectionne); if (!Mouse_K) break; Effacer_curseur(); } Fermer_popup(); Fenetre_Desenfoncer_bouton_normal(Bouton->Pos_X,Bouton->Pos_Y,Bouton->Width,Bouton->Height); Afficher_curseur(); if (Indice_selectionne>=0 && Indice_selectionnePremier_choix; Indice_selectionne; Choix=Choix->Next,Indice_selectionne--) ; Fenetre_Attribut2=Choix->Number; if (Bouton->Affiche_choix) { // Mettre à jour automatiquement le libellé de la dropdown Print_dans_fenetre(Bouton->Pos_X+2,Bouton->Pos_Y+(Bouton->Height-7)/2,Choix->Label,CM_Noir,CM_Clair); } return Bouton->Number; } Fenetre_Attribut2=-1; return 0; } // --- Fonction de clic sur un bouton a peu près ordinaire: // Attend que l'on relache le bouton, et renvoie le numero du bouton si on // est resté dessus, 0 si on a annulé en sortant du bouton. short Fenetre_bouton_normal_click(word x_pos, word y_pos, word width, word height, short btn_number) { while(1) { Effacer_curseur(); Fenetre_Enfoncer_bouton_normal(x_pos,y_pos,width,height); Afficher_curseur(); while (Fenetre_click_dans_zone(x_pos,y_pos,x_pos+width-1,y_pos+height-1)) { if(!Get_input()) Wait_VBL(); if (!Mouse_K) { Effacer_curseur(); Fenetre_Desenfoncer_bouton_normal(x_pos,y_pos,width,height); Afficher_curseur(); return btn_number; } } Effacer_curseur(); Fenetre_Desenfoncer_bouton_normal(x_pos,y_pos,width,height); Afficher_curseur(); while (!(Fenetre_click_dans_zone(x_pos,y_pos,x_pos+width-1,y_pos+height-1))) { if(!Get_input()) Wait_VBL(); if (!Mouse_K) return 0; } } } // --- Renvoie le numéro du bouton clicke (-1:hors de la fenêtre, 0:aucun) --- short Fenetre_Numero_bouton_clicke(void) { T_Bouton_normal * Temp1; T_Bouton_palette * Temp2; T_Bouton_scroller * Temp3; T_Bouton_special * Temp4; T_Bouton_dropdown * Temp5; long Hauteur_maxi_jauge; Fenetre_Attribut1=Mouse_K; // Test du click sur les boutons normaux for (Temp1=Fenetre_Liste_boutons_normal; Temp1; Temp1=Temp1->Next) { if (Fenetre_click_dans_zone(Temp1->Pos_X,Temp1->Pos_Y,Temp1->Pos_X+Temp1->Width-1,Temp1->Pos_Y+Temp1->Height-1)) { if (Temp1->Repetable) { Effacer_curseur(); Fenetre_Enfoncer_bouton_normal(Temp1->Pos_X,Temp1->Pos_Y,Temp1->Width,Temp1->Height); Afficher_curseur(); Tempo_jauge((Mouse_K==1)? Config.Valeur_tempo_jauge_gauche : Config.Valeur_tempo_jauge_droite); Effacer_curseur(); Fenetre_Desenfoncer_bouton_normal(Temp1->Pos_X,Temp1->Pos_Y,Temp1->Width,Temp1->Height); Afficher_curseur(); return Temp1->Number; } return Fenetre_bouton_normal_click(Temp1->Pos_X,Temp1->Pos_Y,Temp1->Width,Temp1->Height,Temp1->Number); } } // Test du click sur les zones "palette" for (Temp2=Fenetre_Liste_boutons_palette; Temp2; Temp2=Temp2->Next) { if (Fenetre_click_dans_zone(Temp2->Pos_X+5,Temp2->Pos_Y+3,Temp2->Pos_X+160,Temp2->Pos_Y+82)) { // On stocke dans Attribut2 le numero de couleur cliqué Fenetre_Attribut2 = (((Mouse_X-Fenetre_Pos_X)/Menu_Facteur_X)-(Temp2->Pos_X+2)) / 10 * 16 + (((Mouse_Y-Fenetre_Pos_Y)/Menu_Facteur_Y)-(Temp2->Pos_Y+3)) / 5; return Temp2->Number; } } // Test du click sur les barres de défilement for (Temp3=Fenetre_Liste_boutons_scroller; Temp3; Temp3=Temp3->Next) { if (Fenetre_click_dans_zone(Temp3->Pos_X,Temp3->Pos_Y,Temp3->Pos_X+10,Temp3->Pos_Y+Temp3->Height-1)) { // Bouton flèche Haut if (Fenetre_click_dans_zone(Temp3->Pos_X,Temp3->Pos_Y,Temp3->Pos_X+10,Temp3->Pos_Y+10)) { Effacer_curseur(); Fenetre_Enfoncer_bouton_normal(Temp3->Pos_X,Temp3->Pos_Y,11,11); if (Temp3->Position) { Temp3->Position--; Fenetre_Attribut1=1; Fenetre_Attribut2=Temp3->Position; Fenetre_Dessiner_jauge(Temp3); } else Fenetre_Attribut1=0; Afficher_curseur(); Tempo_jauge((Mouse_K==1)? Config.Valeur_tempo_jauge_gauche : Config.Valeur_tempo_jauge_droite); Effacer_curseur(); Fenetre_Desenfoncer_bouton_normal(Temp3->Pos_X,Temp3->Pos_Y,11,11); Afficher_curseur(); } else // Bouton flèche Bas if (Fenetre_click_dans_zone(Temp3->Pos_X,Temp3->Pos_Y+Temp3->Height-11,Temp3->Pos_X+10,Temp3->Pos_Y+Temp3->Height-1)) { Effacer_curseur(); Fenetre_Enfoncer_bouton_normal(Temp3->Pos_X,Temp3->Pos_Y+Temp3->Height-11,11,11); if (Temp3->Position+Temp3->Nb_visiblesNb_elements) { Temp3->Position++; Fenetre_Attribut1=2; Fenetre_Attribut2=Temp3->Position; Fenetre_Dessiner_jauge(Temp3); } else Fenetre_Attribut1=0; Afficher_curseur(); Tempo_jauge((Mouse_K==1)? Config.Valeur_tempo_jauge_gauche : Config.Valeur_tempo_jauge_droite); Effacer_curseur(); Fenetre_Desenfoncer_bouton_normal(Temp3->Pos_X,Temp3->Pos_Y+Temp3->Height-11,11,11); Afficher_curseur(); } else // Jauge if (Fenetre_click_dans_zone(Temp3->Pos_X,Temp3->Pos_Y+12,Temp3->Pos_X+10,Temp3->Pos_Y+Temp3->Height-13)) { if (Temp3->Nb_elements>Temp3->Nb_visibles) { // S'il y a la place de faire scroller le curseur: Hauteur_maxi_jauge=(Temp3->Height-24); // Fenetre_Attribut2 reçoit la position dans la jauge correspondant au click Fenetre_Attribut2 =(Mouse_Y-Fenetre_Pos_Y) / Menu_Facteur_Y; Fenetre_Attribut2-=(Temp3->Pos_Y+12+((Temp3->Hauteur_curseur-1)>>1)); Fenetre_Attribut2*=(Temp3->Nb_elements-Temp3->Nb_visibles); if (Fenetre_Attribut2<0) Fenetre_Attribut2=0; else { Fenetre_Attribut2 =Round_div(Fenetre_Attribut2,Hauteur_maxi_jauge-Temp3->Hauteur_curseur); if (Fenetre_Attribut2+Temp3->Nb_visibles>Temp3->Nb_elements) Fenetre_Attribut2=Temp3->Nb_elements-Temp3->Nb_visibles; } // Si le curseur de la jauge bouge: if (Temp3->Position!=Fenetre_Attribut2) { Temp3->Position=Fenetre_Attribut2; Fenetre_Attribut1=3; Effacer_curseur(); Fenetre_Dessiner_jauge(Temp3); Afficher_curseur(); } else // Si le curseur de la jauge ne bouge pas: Fenetre_Attribut1=0; } else // S'il n'y a pas la place de bouger le curseur de la jauge: Fenetre_Attribut1=0; } else // Le click se situe dans la zone de la jauge mais n'est sur aucune // des 3 parties importantes de la jauge Fenetre_Attribut1=0; return (Fenetre_Attribut1)? Temp3->Number : 0; } } // Test du click sur une zone spéciale for (Temp4=Fenetre_Liste_boutons_special; Temp4; Temp4=Temp4->Next) { if (Fenetre_click_dans_zone(Temp4->Pos_X,Temp4->Pos_Y,Temp4->Pos_X+Temp4->Width-1,Temp4->Pos_Y+Temp4->Height-1)) return Temp4->Number; } // Test du click sur une dropdown for (Temp5=Fenetre_Liste_boutons_dropdown; Temp5; Temp5=Temp5->Next) { if (Fenetre_click_dans_zone(Temp5->Pos_X,Temp5->Pos_Y,Temp5->Pos_X+Temp5->Width-1,Temp5->Pos_Y+Temp5->Height-1)) { if (Mouse_K & Temp5->Bouton_actif) return Fenetre_Dropdown_click(Temp5); else { Fenetre_Attribut2=-1; return Fenetre_bouton_normal_click(Temp5->Pos_X,Temp5->Pos_Y,Temp5->Width,Temp5->Height,Temp5->Number); } } } return 0; } short Fenetre_Numero_bouton_touche(void) { T_Bouton_normal * Temp; if (Touche & MOD_SHIFT) Fenetre_Attribut1=A_DROITE; else Fenetre_Attribut1=A_GAUCHE; // On fait une première recherche Temp=Fenetre_Liste_boutons_normal; while (Temp!=NULL) { if (Temp->Raccourci==Touche) { Effacer_curseur(); Fenetre_Enfoncer_bouton_normal(Temp->Pos_X,Temp->Pos_Y,Temp->Width,Temp->Height); Afficher_curseur(); Tempo_jauge(Config.Valeur_tempo_jauge_droite); Effacer_curseur(); Fenetre_Desenfoncer_bouton_normal(Temp->Pos_X,Temp->Pos_Y,Temp->Width,Temp->Height); Afficher_curseur(); return Temp->Number; } Temp=Temp->Next; } // Si la recherche n'a pas été fructueuse ET que l'utilisateur appuyait sur // , on regarde si un bouton ne pourrait pas réagir comme si // n'était pas appuyé. if (Fenetre_Attribut1==A_DROITE) { Temp=Fenetre_Liste_boutons_normal; while (Temp!=NULL) { if (Temp->Raccourci==(Touche&0x0FFF)) return Temp->Number; Temp=Temp->Next; } } return 0; } short Fenetre_Bouton_clicke(void) { short Bouton; if(!Get_input())Wait_VBL(); // Gestion des clicks if (Mouse_K) { if ((Mouse_X=Fenetre_Pos_X+(Fenetre_Largeur*Menu_Facteur_X)) || (Mouse_Y>=Fenetre_Pos_Y+(Fenetre_Hauteur*Menu_Facteur_Y))) return -1; else { if (Mouse_Y < Fenetre_Pos_Y+(12*Menu_Facteur_Y)) Deplacer_fenetre(Mouse_X-Fenetre_Pos_X,Mouse_Y-Fenetre_Pos_Y); else return Fenetre_Numero_bouton_clicke(); } } // Gestion des touches if (Touche) { Bouton=Fenetre_Numero_bouton_touche(); if (Bouton) { Touche=0; return Bouton; } } return 0; } // Fonction qui sert à remapper les parties sauvegardées derriere les // fenetres ouvertes. C'est utilisé par exemple par la fenetre de palette // Qui remappe des couleurs, afin de propager les changements. void Remappe_fond_fenetres(byte * Table_de_conversion, int Min_Y, int Max_Y) { int Indice_fenetre; byte* EDI; int dx,cx; for (Indice_fenetre=0; Indice_fenetreMax_Y) return; if (dx+Pile_Fenetre_Pos_Y[Indice_fenetre]0;cx--) { *EDI = Table_de_conversion[*EDI]; EDI ++; } } } }