/****************************************************************************/ /* Fichiers … inclure */ /****************************************************************************/ #include #include #include #include #include #include #include /* Ici sont d‚finies toutes les variables n‚cessaires */ /* pour avour accŠs aux routines graphiques, ainsi qu'aux */ /* fonctions systŠme gemdos() et appels CP/M 68K */ #include #include "flower.h" /* ****************** TYPE DE FENETRE ******************/ /* GEM vous permet de d‚finir diff‚rents types de fenˆtres. Ici, on choisit un type de fenˆtre particulier, et GEM se charge du reste (c…d de l'ouvrir, changer de taille, etc...). Pour vous il s'agit seulement de faire les appels n‚cessaires aux routines correspondantes. Le type de fenˆtre se d‚finit dpnc de la fa‡on suivante: */ /* TYPE DE FENETRE: TAILLE VARIABLE, AVEC NOM, PEUT BOUGER **************/ #define WI_KIND (SIZER | NAME | CLOSER | MOVER | FULLER) /* Si l'utilisateur r‚tr‚cit complŠtement sa fenˆtre, il n'est plus possible de s'en sortir. Pour empˆcher ce problŠme d'apparaŒtre, on d‚finit une taille minimale au del… de laquelle il n'est plus possible de r‚tr‚cir la fenˆtre. */ #define NO_WINDOW (-1) #define MIN_WIDTH (2*gl_wbox) #define MIN_HEIGHT (3*gl_hbox) /* La variable msgbuff contient les codes de retour de GEM et permet d'agir selon le contenu du message pass‚ par GEM. */ int ret, msgbuff[8]; /* GEM simule un multi-tƒches, et msgbuff est une zone tampon dans laquelle il est possible pour GEM de vous laisser un message. Une espŠce de boite … lettres pour ainsi dire. */ extern int gp_apid; /* variable n‚cessaire pour le GEM */ /* Zone de la m‚moire n‚cessaire pour les fonctions graphiques de GEM. */ int contrl[12]; int intin[128]; int ptsin[128]; int intout[128]; int ptsout[128]; /* GEM permet d'appeler les mˆmes utilitaires depuis l'assembleur. Si vous ˆtes int‚ress‚(e) vous pouvez appeler avec les variables contrl, intin, etc directement les routines graphiques sans aucune interface "C". */ /* "handle" est l'identification de la station de travail. "wi_handle" identifie la fenˆtre dans laquelle ontravaille. */ int handle, wi_handle, top_window, work_in[11], work_out[57]; /* "phys_handle" est le handle physique (il est possible d'avoir plusieurs stations de travail ouvertes en mˆme temps sur la mˆme station physique). "keycode" donne le code de la touche press‚e par l'utilisateur, "butdown" est une drapeau pour indiquer sir l'utilisateur a appui‚ le bouton de la souris. */ int phys_handle, keycode, butdown; /* zone de la m‚moire utilis‚e par le GEM */ int pxyarray[128]; /* Variables n‚cessaire pour le changement d'une fenˆtre.*/ int xold, yold, wold, hold; /* Utilis‚es dans la fonction multi(), "gl_hchar" et "gl_wchar" sont la largeur et la hauteur des caractŠres. "gl_hbox" et "gl_wbox" sont la largeur et la hauteur de leur encadrement (box=cadre). */ int gl_hchar, gl_wchar, gl_wbox, gl_hbox; int xdesk, ydesk, hdesk, wdesk; /* taille du bureau. */ int xwind, ywind, hwind, wwind; /* taille de la fenˆtre. */ /* "xwork" et "ywork" sont les coordonn‚es sup‚rieures gauche de la fenˆtre active. Chaque appel … l'‚criture graphique doir en tenir compte pour dessiner les objets dans la fenˆtre et pas en dehors... */ int xwork, ywork, hwork, wwork, mx, my; /* Drapeau pour indiquer si la fenˆtre est derriŠre ou en plein ‚cran. */ int hidden, fulled; /* Pour ‚viter de calculer … chaque fois le sinus et le cosinus, on calcule leur valeurs et on les garde dans les tableaux suivants: */ static float sinus[720], cosinus[720], trd[720]; /* Texte pour afficher les paramŠtres RD (Radius Differential) et TD (T... Differential). Voir text. */ static char *titre = { "RD = [ ], TD = [ ]" }; /* Autres variables pour calculer la figure. */ static int theta, rad, radius, points[2880], centrex, centrey; /****************************************************************************/ /* PROGRAMME PRINCIPAL */ /****************************************************************************/ int main(int argc, char *argv[], char *envp[]) { /* while (*envp) { printf(*envp); envp++; } */ int x, y, term; appl_init(); phys_handle = graf_handle(&gl_wchar, &gl_hchar, &gl_wbox, &gl_hbox); wind_get(0, WF_WORKXYWH, &xdesk, &ydesk, &wdesk, &hdesk); open_vwork(); /* Ouvre la station de travail */ open_window(); /* Ouvre la fenˆtre */ graf_mouse(5,NULL); /* Change la forme de la souris */ vsm_type(handle, 1); /* point = polymarker */ /* Initialisation de diverses variables. */ hidden = FALSE; fulled = FALSE; rad =1; theta = 1; butdown = TRUE; initfleur(); /* Initialisation du cosinus et sinus */ multi(); /* Appel au multi-tƒches */ return 0; } /****************************************************************************/ /* OUVRIR LA STATION DE TRAVAIL */ /* Ici, on fait appel … la fonction GEM v_opnvwk (open virtual workstation: ouvrir une station de travail virtuelle). Les paramŠtres … passer sont d‚crits d'un fa‡on plus approfondie dans le mode d'emploi GEM. Il suffit ici de remarquer que work_in[10] est 2, cela signifie qu'on travaille dans les coordonn‚es raster de la machine, et pas dans le systŠme de coordonn‚es virtuelles. La diff‚rence est que dans notre cas, les coordonn‚es utilis‚es ici ne sont pas portables sur une autre machine. Par contre, le dessin est plus rapide parce que l'effort de translation de coordonn‚es n'est plus n‚cessaire. Remarquez que l'origine est en haut … gauche de l'‚cran. */ void open_vwork() { int i; for (i=0; i<10; work_in[i++] = 1); work_in[10] = 2; /* Coordonn‚es absolues RC */ handle = phys_handle; /* Ouvre la station de travail */ v_opnvwk(work_in, &handle, work_out); } /* Fonction pour dessiner une fleur avec les paramŠtres rd et td. */ /* Pour gagner du temps, on utilise les sym‚tries de la figure */ void unefleur(int rd, int td) { int z, c, s; register int i,m; i = 0; for (m=0; m<180; m++) { z = (int)(0.5 + td*(double)m)%720; c = (int)(0.5 + trd[m]*cosinus[z]); s = (int)(0.5 + trd[m]*sinus[z]); points[i] = centrex + c; points[i+1] = centrey + s; points[i+360] = centrex + c; points[i+361] = centrey - s; points[i+720] = centrex - c; points[i+721] = centrey + s; points[i+1080] = centrex - c; points[i+1081] = centrey - s; i += 2; } } /* Initialisation de sinus et cosinus ======================================*/ void initfleur() { float angle, delta; int i, cadre[4]; angle = -M_PI; delta = M_PI / 180.0; for (i=0; i<720; i++) { sinus[i] = sin(angle); cosinus[i] = cos(angle); angle = angle + delta; } initrd(); } /* Ouvre la fenˆtre et obtient xwork et ywork du GEM avec wind_get */ /* Pour utiliser une fenˆtre, uk faut: 1: la cr‚er avec wind_create. 2: lui donner un nom avec wind_set. 3: l'ouvrir avec wind_open. 4: ‚tablir les coordonn‚es dans xwork etc avec wind_get (WF_WORKXYWH). Toutes les variables en majuscules sont d‚finies dans les fichiers "include" dŠs les premiŠres lignes du programme. */ void open_window() { wi_handle = wind_create(WI_KIND,xdesk,ydesk,wdesk,hdesk); wind_set(wi_handle,WF_NAME, " FLEUR ", 0, 0); graf_growbox(xwind+wwind/2, ywind+hwind/2, gl_wbox, gl_hbox, xdesk, ydesk, wdesk, hdesk); wind_open(wi_handle, xdesk, ydesk, wdesk, hdesk); /* On donne … GEM l'adresse du xwork etc. GEM remplit les valeurs */ wind_get(wi_handle, WF_WORKXYWH,&xwork,&ywork,&wwork,&hwork); } /* La fameuse fonction multitƒches =========================================*/ void multi() { int event; do { event = evnt_multi(MU_MESAG | MU_BUTTON | MU_KEYBD, 1,1,butdown, 0,0,0,0,0, 0,0,0,0,0, msgbuff,0,0,&mx,&my,&ret,&ret,&keycode,&ret); wind_update(TRUE); /* Il faut mettre … jour le fenˆtre alors */ if(event & MU_MESAG) switch (msgbuff[0]) { case WM_REDRAW: /* Voil…, on redessine la fenˆtre */ do_redraw(msgbuff[4],msgbuff[5], msgbuff[6],msgbuff[7]); break; case WM_NEWTOP: case WM_TOPPED: wind_set(wi_handle, WF_TOP,0,0,0,0); do_redraw(msgbuff[4],msgbuff[5], msgbuff[6],msgbuff[7]); break; case WM_SIZED: case WM_MOVED: /* Si l'utilisateur a boug‚ la fenˆtre, on la redessine aprŠs avoir recalcul‚ les paramŠtres xwork et ywork. ATTENTION: si la fenˆtre est au minimum, on interdit … l'utilisateur de la r‚tr‚cir davantage! */ if(msgbuff[6]12) { /* Si rad > 12 on recommence … nouveau */ rad = 1; initrd(); } else initrd(); /* Sinon on recommence une nouvelle s‚rie */ } /* Pour ‚viter de laisser des traces pendant le temps qu'une fenˆtre est boug‚e par l'utilisateur, il FAUT cacher la souris. */ void hide_mouse() { if (!hidden) { graf_mouse(256, NULL); hidden = TRUE; } } void show_mouse() { if (hidden) { graf_mouse(257,NULL); hidden = FALSE; } } /* Coupe toutes les lignes en dehors de la fenˆtre */ void set_clip(int x,int y,int w,int h) { int p[4]; p[0] = x; p[1] = y; p[2] = x+w; p[3] = y+h; vs_clip(handle, 1, p); } /* Ecrit les paramŠtres =================================================== */ void ecrit(int x, int y, char *str) { /* La fonction v_justified a besoin de handle, coordonn‚es x,y, la longueur du texte (dans notre cas en coordonn‚es r‚elles RC) et de deux paramŠtres qui d‚finissent le type de centrage d‚sir‚ par l'utilisateur. */ v_justified(handle,x,y,str,100,1,1); } /* redessine la fenˆtre =================================================== */ void do_redraw(int xc, int yc, int wc, int hc) { GRECT t1, t2; hide_mouse(); wind_update(TRUE); t2.g_x = xc; t2.g_y = yc; t2.g_w = wc; t2.g_h = hc; wind_get(wi_handle,WF_FIRSTXYWH,&t1.g_x,&t1.g_y,&t1.g_w,&t1.g_h); while (t1.g_w && t1.g_h) { if(rc_intersect(&t2,&t1)) { set_clip(t1.g_x,t1.g_y,t1.g_w,t1.g_h); dofleur(); } wind_get(wi_handle,WF_NEXTXYWH,&t1.g_x,&t1.g_y,&t1.g_w,&t1.g_h); } wind_update(FALSE); show_mouse(); } /* Initialise RD ========================================================== */ void initrd() { register int i,t; if (hwork