1 /* GLArea.c */
2 /**********************************************************************************************************
3 Copyright (c) 2002-2013 Abdul-Rahman Allouche. All rights reserved
4 
5 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6 documentation files (the Gabedit), to deal in the Software without restriction, including without limitation
7 the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
8 and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
9 
10   The above copyright notice and this permission notice shall be included in all copies or substantial portions
11   of the Software.
12 
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
14 TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
15 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
16 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17 DEALINGS IN THE SOFTWARE.
18 ************************************************************************************************************/
19 
20 #include "../../Config.h"
21 #include <gdk/gdkkeysyms.h>
22 #include <gtk/gtkgl.h>
23 /* #include <pthread.h>*/
24 #include "GlobalOrb.h"
25 #include "../Utils/Vector3d.h"
26 #include "../Utils/Transformation.h"
27 #include "../Utils/UtilsGL.h"
28 #include "GeomDraw.h"
29 #include "../Utils/Utils.h"
30 #include "../Utils/UtilsInterface.h"
31 #include "../Utils/AtomsProp.h"
32 #include "../Utils/Constants.h"
33 #include "UtilsOrb.h"
34 #include "GeomOrbXYZ.h"
35 #include "Basis.h"
36 #include "TriangleDraw.h"
37 #include "ContoursDraw.h"
38 #include "PlanesMappedDraw.h"
39 #include "ContoursPov.h"
40 #include "PlanesMappedPov.h"
41 #include "SurfacesPov.h"
42 #include "Orbitals.h"
43 #include "StatusOrb.h"
44 #include "GridPlans.h"
45 #include "Dipole.h"
46 #include "AxisGL.h"
47 #include "PrincipalAxisGL.h"
48 #include "VibrationDraw.h"
49 #include "Images.h"
50 #include "PovrayGL.h"
51 #include "MenuToolBarGL.h"
52 #include "LabelsGL.h"
53 #include "RingsOrb.h"
54 #include "RingsPov.h"
55 
56 
57 /* static pthread_mutex_t theRender_mutex = PTHREAD_MUTEX_INITIALIZER;*/
58 
59 static gint OperationType = OPERATION_ROTATION_FREE;
60 
61 static gint numberOfSurfaces = 0;
62 static GLuint* positiveSurfaces = NULL;
63 static GLuint* negativeSurfaces = NULL;
64 static GLuint* nullSurfaces = NULL;
65 
66 static GLuint listRings[] = {0,0,0,0,0,0};
67 static gboolean selectedListRings[] = {FALSE,FALSE,FALSE,FALSE,FALSE,FALSE};
68 static gint nMaxListRings = G_N_ELEMENTS (listRings);
69 
70 static GLuint GeomList = 0;
71 static GLuint VibList = 0;
72 static GLuint DipList = 0;
73 static GLuint axisList = 0;
74 static GLuint principalAxisList = 0;
75 static GLuint* contoursLists = NULL;
76 static GLuint* planesMappedLists = NULL;
77 static gint i0Contours = 0;
78 static gint i1Contours = 1;
79 static gint i0PlaneMapped = 0;
80 static gint i1PlaneMapped = 1;
81 static gint numPlaneContours = 0;
82 static gint numPlaneMaps = 0;
83 static gint numberOfContours = 0;
84 static gdouble* values = NULL;
85 static gint optcol = 0;
86 static gint nPlanesContours = 0;
87 static gint nPlanesMapped = 0;
88 static gboolean newPlaneMapped = FALSE;
89 static gint newPlaneGridForContours = FALSE;
90 static gint newPlaneGridForPlanesMapped = FALSE;
91 static gdouble gapContours = 0.0;
92 static gdouble gapPlanesMapped = 0.0;
93 static gboolean lightOnOff[3] = { TRUE,FALSE,FALSE};
94 static gdouble Trans[3] = { 0,0,-50.0};
95 static V4d light0_position = {0.0, 0.0,50.0,0.0};
96 static V4d light1_position = {0.0, 50.0,50.0,0.0};
97 static V4d light2_position = {50.0, 0.0,50.0,0.0};
98 static gdouble zNear = 1.0;
99 static gdouble zFar = 100.0;
100 static GLdouble Zoom = 45;
101 static gboolean perspective = TRUE;
102 static gboolean animateContours = FALSE;
103 static gboolean animatePlanesMapped = FALSE;
104 /*********************************************************************************************/
105 static gdouble scaleBall = 1.0;
106 static gdouble scaleStick = 1.0;
107 static gboolean showOneSurface = TRUE;
108 static gboolean showBox = TRUE;
109 
110 static PangoContext *ft2_context = NULL;
111 
112 /*********************************************************************************************/
113 static V4d BackColor[7] =
114 {
115   {0.0, 0.0, 0.0, 1.0}, /* black */
116   {1.0, 1.0, 1.0, 1.0}, /* white */
117   {1.0, 0.0, 0.0, 1.0}, /* red   */
118   {0.0, 1.0, 0.0, 1.0}, /* green */
119   {0.0, 0.0, 1.0, 1.0}, /* blue  */
120   {1.0, 0.5, 0.5, 1.0}, /* peach */
121   {0.7, 0.7, 0.7, 1.0}, /* Grey  */
122 };
123 /*********************************************************************************************/
getScaleBall()124 gdouble getScaleBall()
125 {
126 	return scaleBall;
127 }
128 /*********************************************************************************************/
getScaleStick()129 gdouble getScaleStick()
130 {
131 	return scaleStick;
132 }
133 /*********************************************************************************************/
getShowOneSurface()134 gboolean getShowOneSurface()
135 {
136 	return showOneSurface;
137 }
138 /*********************************************************************************************/
getShowBox()139 gboolean getShowBox()
140 {
141 	return showBox;
142 }
143 /*********************************************************************************************/
setShowBox(gboolean c)144 void setShowBox(gboolean c)
145 {
146 	showBox = c;
147 }
148 /*********************************************************************************************/
setScaleBall(gdouble a)149 void setScaleBall(gdouble a)
150 {
151 	scaleBall = fabs(a);
152 }
153 /*********************************************************************************************/
setScaleStick(gdouble a)154 void setScaleStick(gdouble a)
155 {
156 	scaleStick = fabs(a);
157 }
158 /*********************************************************************************************/
setShowOneSurface(gboolean a)159 void setShowOneSurface(gboolean a)
160 {
161 	showOneSurface = a;
162 }
163 /*********************************************************************************************/
getOptCol()164 gint getOptCol()
165 {
166 	return optcol;
167 }
168 /*********************************************************************************************/
setOptCol(gint i)169 void setOptCol(gint i)
170 {
171 	optcol = i;
172 	if(optcol<-1 || optcol>6) optcol = 0;
173 }
174 /*********************************************************************************************/
build_rings(gint size,gboolean showMessage)175 void build_rings(gint size, gboolean showMessage)
176 {
177 	if(size<3 || size > nMaxListRings-1+3)
178 		return ;
179 	selectedListRings[size-3] = TRUE;
180 	IsoRingsAllGenLists(&listRings[size-3], size,size, showMessage);
181 }
182 /*********************************************************************************************/
delete_rings_all()183 void delete_rings_all()
184 {
185 	gint i;
186 	for(i=0;i<nMaxListRings;i++)
187 	{
188 		selectedListRings[i] = FALSE;
189 		if (glIsList(listRings[i]) == GL_TRUE) glDeleteLists(listRings[i],1);
190 		listRings[i] = 0;
191 	}
192 	deleteRingsPovRayFile();
193 }
194 /*********************************************************************************************/
195 
get_background_color(guchar color[])196 gint get_background_color(guchar color[])
197 {
198 	if(optcol<0) return optcol;
199 	color[0] = (guchar)(BackColor[optcol][0]*255+0.5);
200 	color[1] = (guchar)(BackColor[optcol][1]*255+0.5);
201 	color[2] = (guchar)(BackColor[optcol][2]*255+0.5);
202 	return optcol;
203 }
204 /*********************************************************************************************/
addFog()205 void  addFog()
206 {
207 	/*
208     GLdouble fog_c[] = {0.7f, 0.7f, 0.7f, 1.0f};
209     glFogi(GL_FOG_MODE, GL_LINEAR);
210     glFogf(GL_FOG_START, zNear);
211     glFogf(GL_FOG_END, zFar);
212     glFogdv(GL_FOG_COLOR, fog_c);
213     glEnable(GL_FOG);
214     */
215 
216   GLdouble fogstart =  -0.5;
217   GLdouble fogend = 1.51;
218   GLdouble fogcolor[4] = {0.0, 0.0, 0.0, 1.0};
219 
220   glShadeModel(GL_SMOOTH);
221   glFogi(GL_FOG_MODE, GL_LINEAR);
222   glFogdv(GL_FOG_COLOR, fogcolor);
223   glHint(GL_FOG_HINT, GL_DONT_CARE);
224   glFogf(GL_FOG_START, fogstart);
225   glFogf(GL_FOG_END, fogend);
226 }
227 /*********************************************************************************************/
drawChecker()228 void drawChecker()
229 {
230 	GLdouble x, y, z;
231 	GLint i,j;
232 	V4d Diffuse1  = {0.0,0.0,0.0,0.8};
233 	V4d Diffuse2  = {0.8,0.8,0.8,0.8};
234 	V4d Specular = {0.8,0.8,0.8,0.8 };
235 	V4d Ambiant  = {0.1,0.1,0.1,0.8};
236 	static GLdouble w = 4;
237 	static GLint n = 50;
238 	static GLdouble x0 = -100;
239 	static GLdouble y0 = 0;
240 	static GLdouble z0 = -100;
241 	GLdouble max = 0;
242 
243 	if(nCenters>0) max = fabs(GeomOrb[0].C[0]);
244 	else max = 10;
245 	for(i=0;i<(gint)nCenters;i++)
246 	{
247 		if(max<fabs(GeomOrb[i].C[0])) max = fabs(GeomOrb[i].C[0]);
248 		if(max<fabs(GeomOrb[i].C[1])) max = fabs(GeomOrb[i].C[1]);
249 		if(max<fabs(GeomOrb[i].C[2])) max = fabs(GeomOrb[i].C[2]);
250 	}
251 	/* max *= 45/Zoom;*/
252 	if(y0>-5-max) y0 = -5-max;
253 
254 	glMaterialdv(GL_FRONT_AND_BACK,GL_SPECULAR,Specular);
255 	glMaterialdv(GL_FRONT_AND_BACK,GL_DIFFUSE,Diffuse1);
256 	glMaterialdv(GL_FRONT_AND_BACK,GL_AMBIENT,Ambiant);
257 	glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,100);
258 
259 	glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
260 	glRotatef(-5,0,1,0);
261 
262 	for(i=0;i<n;i++)
263 	for(j=0;j<n;j++)
264 	{
265 		if((i+j)%2==0)
266 		{
267 			/*glMaterialdv(GL_FRONT_AND_BACK,GL_DIFFUSE,Diffuse1);*/
268 			glMaterialdv(GL_FRONT_AND_BACK,GL_AMBIENT,Diffuse1);
269 		}
270 		else
271 		{
272 			/*glMaterialdv(GL_FRONT_AND_BACK,GL_DIFFUSE,Diffuse2);*/
273 			glMaterialdv(GL_FRONT_AND_BACK,GL_AMBIENT,Diffuse2);
274 		}
275 
276 		glBegin(GL_POLYGON);
277 		glNormal3f(0.0,1.0,0.0);
278 		x = x0 + i*w;
279 		y = y0;
280 		z = z0 + j*w;
281 		glVertex3f(x,y,z);
282 		glVertex3f(x,y,z+w);
283 		glVertex3f(x+w,y,z+w);
284 		glVertex3f(x+w,y,z);
285 		glEnd();
286 	}
287 	glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
288 }
289 /*********************************************************************************************/
setAnimatePlanesMapped(gboolean anim)290 void  setAnimatePlanesMapped(gboolean anim)
291 {
292 	animatePlanesMapped = anim;
293 }
294 /*********************************************************************************************/
setAnimateContours(gboolean anim)295 void  setAnimateContours(gboolean anim)
296 {
297 	animateContours = anim;
298 }
299 /*********************************************************************************************/
sourceIsOn(gint numsSource)300 gboolean  sourceIsOn(gint numsSource)
301 {
302 	if(numsSource>=0 && numsSource<=2)
303 		return lightOnOff[numsSource];
304 	else
305 		return FALSE;
306 }
307 /*********************************************************************************************/
get_orgin_molecule(gdouble orig[])308 void  get_orgin_molecule(gdouble orig[])
309 {
310 	gint i = 0;
311 	for(i=0;i<3;i++) orig[i] = Trans[i];
312 	/*
313 	if(!perspective)
314 		for(i=0;i<3;i++) orig[i] /= 10;
315 		*/
316 }
317 /*********************************************************************************************/
get_camera_values(gdouble * zn,gdouble * zf,gdouble * angle,gdouble * aspect,gboolean * persp)318 void  get_camera_values(gdouble* zn, gdouble* zf, gdouble* angle, gdouble* aspect, gboolean* persp)
319 {
320 	gdouble width = 500;
321 	gdouble height = 500;
322 
323 	if(GLArea)
324 	{
325 		width =  GLArea->allocation.width;
326 		height = GLArea->allocation.height;
327 	}
328 	*aspect = width/height;
329 	*zn = zNear;
330 	*zf = zFar;
331 	*angle = Zoom;
332 	*persp = perspective;
333 }
334 /*********************************************************************************************/
335 static gint redraw(GtkWidget *widget, gpointer data);
336 /*********************************************************************************************/
set_camera_values(gdouble zn,gdouble zf,gdouble zo,gboolean persp)337 void set_camera_values(gdouble zn, gdouble zf, gdouble zo, gboolean persp)
338 {
339 	zNear = zn;
340 	zFar = zf;
341 	Zoom = zo;
342 	Trans[2] = -zf/2;
343 	perspective = persp;
344 	redraw(GLArea,NULL);
345 }
346 /*********************************************************************************************/
get_light(gint num,gdouble v[])347 gboolean get_light(gint num,gdouble v[])
348 {
349 	gint i;
350 	v[0] = v[1] = v[2] = 0;
351 	if(num<0 || num>2) return FALSE;
352 	switch(num)
353 	{
354 		case 0 :
355 			for(i=0;i<3;i++)
356 				 v[i] = light0_position[i];
357 			 break;
358 		case 1 :
359 			for(i=0;i<3;i++)
360 				 v[i] = light1_position[i];
361 			 break;
362 		case 2 :
363 			for(i=0;i<3;i++)
364 				 v[i] = light2_position[i];
365 			 break;
366 	}
367 	return lightOnOff[num];
368 }
369 /*********************************************************************************************/
get_light_position(gint num)370 gchar**  get_light_position(gint num)
371 {
372 	gint i;
373 	gchar** t = g_malloc(3*sizeof(gchar*));
374 	switch(num)
375 	{
376 		case 0 :
377 			for(i=0;i<3;i++)
378 				 t[i] = g_strdup_printf("%lf",light0_position[i]);
379 			 break;
380 		case 1 :
381 			for(i=0;i<3;i++)
382 				 t[i] = g_strdup_printf("%lf",light1_position[i]);
383 			 break;
384 		case 2 :
385 			for(i=0;i<3;i++)
386 				 t[i] = g_strdup_printf("%lf",light2_position[i]);
387 			 break;
388 	}
389 	return t;
390 }
391 /*********************************************************************************************/
set_light_position(gint num,gdouble v[])392 void set_light_position(gint num,gdouble v[])
393 {
394 	gint i;
395 	switch(num)
396 	{
397 		case 0 :
398 			for(i=0;i<3;i++)
399 				 light0_position[i] = v[i];
400 			 break;
401 		case 1 :
402 			for(i=0;i<3;i++)
403 				 light1_position[i] = v[i];
404 			 break;
405 		case 2 :
406 			for(i=0;i<3;i++)
407 				 light2_position[i] = v[i];
408 			 break;
409 	}
410 }
411 /*********************************************************************************************/
set_operation_type(gint i)412 void set_operation_type(gint i)
413 {
414 	OperationType = i;
415 }
416 /*********************************************************************************************/
set_light_on_off(gint i)417 void set_light_on_off(gint i)
418 {
419 	lightOnOff[i] = !lightOnOff[i] ;
420 }
421 /*********************************************************************************************/
add_surface()422 void add_surface()
423 {
424 	numberOfSurfaces++;
425 	if(!positiveSurfaces) positiveSurfaces = g_malloc(sizeof(GLuint));
426 	else positiveSurfaces = g_realloc(positiveSurfaces, numberOfSurfaces*sizeof(GLuint));
427 	positiveSurfaces[numberOfSurfaces-1] = 0;
428 
429 	if(!negativeSurfaces) negativeSurfaces = g_malloc(sizeof(GLuint));
430 	else negativeSurfaces = g_realloc(negativeSurfaces, numberOfSurfaces*sizeof(GLuint));
431 	negativeSurfaces[numberOfSurfaces-1] = 0;
432 
433 	if(!nullSurfaces) nullSurfaces = g_malloc(sizeof(GLuint));
434 	else nullSurfaces = g_realloc(nullSurfaces, numberOfSurfaces*sizeof(GLuint));
435 	nullSurfaces[numberOfSurfaces-1] = 0;
436 
437 	RebuildSurf = TRUE;
438 	addLastSurface();
439 }
440 /*********************************************************************************************/
add_maps(gint ii0,gint ii1,gint inumPlane,gdouble igap,gboolean newGrid)441 void add_maps(gint ii0, gint ii1, gint inumPlane, gdouble igap, gboolean newGrid)
442 {
443 	i0PlaneMapped = ii0;
444 	i1PlaneMapped = ii1;
445 	numPlaneMaps = inumPlane;
446 	gapPlanesMapped = igap;
447 	newPlaneGridForPlanesMapped = newGrid;
448 	if(numPlaneMaps>=0)
449 	{
450 		newPlaneMapped = TRUE;
451 		nPlanesMapped++;
452 		reDrawPlaneMappedPlane = TRUE;
453 		if(!planesMappedLists) planesMappedLists = g_malloc(sizeof(GLuint));
454 		else planesMappedLists = g_realloc(planesMappedLists, nPlanesMapped*sizeof(GLuint));
455 	}
456 }
457 /*********************************************************************************************/
add_void_maps()458 void add_void_maps()
459 {
460 	if(nPlanesMapped<1) return;
461 	i0PlaneMapped = 0;
462 	i1PlaneMapped = 1;
463 	numPlaneMaps = -1;
464 	gapPlanesMapped = 0;
465 	newPlaneGridForPlanesMapped = FALSE;
466 	newPlaneMapped = TRUE;
467 	nPlanesMapped++;
468 	reDrawPlaneMappedPlane = TRUE;
469 	if(!planesMappedLists) planesMappedLists = g_malloc(sizeof(GLuint));
470 	else planesMappedLists = g_realloc(planesMappedLists, nPlanesMapped*sizeof(GLuint));
471 	planesMappedLists[nPlanesMapped-1] = 0;
472 }
473 /********************************************************/
free_planes_mapped_all()474 void free_planes_mapped_all()
475 {
476 	if(planesMappedLists)
477 	{
478 		gint i;
479 		for(i=0;i<nPlanesMapped;i++)
480 		if (glIsList(planesMappedLists[i]) == GL_TRUE) glDeleteLists(planesMappedLists[i],1);
481 		g_free(planesMappedLists);
482 	}
483 	newPlaneGridForPlanesMapped = FALSE;
484 	newPlaneMapped = FALSE;
485 	nPlanesMapped = 0;
486 	planesMappedLists = NULL;
487 	deletePlanesMappedPovRayFile();
488 	hideColorMapPlanesMapped();
489 	reDrawPlaneMappedPlane = FALSE;
490 }
491 /*********************************************************************************************/
add_void_contours()492 void add_void_contours()
493 {
494 	if(nPlanesContours<1) return;
495 	if(values) g_free(values);
496 	values = NULL;
497 	numberOfContours = 0;
498 	i0Contours = 0;
499 	i1Contours = 1;
500 	numPlaneContours = 0;
501 	gapContours = 0;
502 	newContours = TRUE;
503 	nPlanesContours++;
504 	if(!contoursLists) contoursLists = g_malloc(sizeof(GLuint));
505 	else contoursLists = g_realloc(contoursLists,nPlanesContours*sizeof(GLuint));
506 	contoursLists[nPlanesContours-1] = 0;
507 	reDrawContoursPlane = TRUE;
508 }
509 /*********************************************************************************************/
set_contours_values(gint N,gdouble * cvalues,gint ii0,gint ii1,gint inumPlane,gdouble igap)510 void set_contours_values(gint N,gdouble* cvalues,gint ii0,gint ii1,gint inumPlane,gdouble igap)
511 {
512 	if(values) g_free(values);
513 	values = cvalues;
514 	numberOfContours = N;
515 	i0Contours = ii0;
516 	i1Contours = ii1;
517 	numPlaneContours = inumPlane;
518 	gapContours = igap;
519 	if(values)
520 	{
521 		newContours = TRUE;
522 		nPlanesContours++;
523 		if(!contoursLists) contoursLists = g_malloc(sizeof(GLuint));
524 		else contoursLists = g_realloc(contoursLists,nPlanesContours*sizeof(GLuint));
525 	}
526 	/* Debug("End set_contours_values\n");*/
527 	reDrawContoursPlane = TRUE;
528 }
529 /********************************************************/
set_contours_values_from_plane(gdouble minv,gdouble maxv,gint N,gdouble igap,gboolean linear)530 void set_contours_values_from_plane(gdouble minv,gdouble maxv,gint N,gdouble igap, gboolean linear)
531 {
532 	gint i;
533     	gdouble* cvalues;
534     	gdouble step;
535 
536     	cvalues = g_malloc(N*sizeof(gdouble));
537 	if(linear)
538 	{
539     		if(N==1) step = (maxv+minv)/2;
540 		else step = (maxv-minv)/(N-1);
541 
542 		for(i=0;i<N;i++) cvalues[i] = minv + step*i;
543 	}
544 	else
545 	{
546 		gdouble e = exp(1.0);
547 		if(N==1) step = 1.0/2.0;
548 		else step = (1.0)/(N-1);
549 		for(i=0;i<N;i++) cvalues[i] = minv+(maxv-minv)*log(step*i*(e-1)+1);
550 	}
551 
552 	if(gridPlaneForContours)
553 	{
554 		/* Debug("begin Set contour\n");*/
555     		set_contours_values(N,cvalues,0,1,0,igap);
556 		/* Debug("End set contour\n");*/
557 		newPlaneGridForContours = TRUE;
558 	}
559 	else
560 	{
561 		if(cvalues) g_free(cvalues);
562 	}
563 }
564 /********************************************************/
set_background_optcolor(gint i)565 void set_background_optcolor(gint i)
566 {
567 	optcol = i;
568 }
569 /********************************************************/
set_background_color()570 static void set_background_color()
571 {
572 	if(optcol>=0) glClearColor(BackColor[optcol][0],BackColor[optcol][1],BackColor[optcol][2],BackColor[optcol][3]);
573 	else
574 	{
575 		glClearColor(BackColor[4][0],BackColor[4][1],BackColor[4][2],BackColor[4][3]);
576 	}
577 }
578 /********************************************************/
free_contours_all()579 void free_contours_all()
580 {
581 	if(contoursLists)
582 	{
583 		gint i;
584 		for(i=0;i<nPlanesContours;i++)
585 		if (glIsList(contoursLists[i]) == GL_TRUE) glDeleteLists(contoursLists[i],1);
586 		g_free(contoursLists);
587 	}
588 	set_contours_values(0,NULL,0,1,0,0.0);
589 	nPlanesContours = 0;
590 	contoursLists = NULL;
591 	deleteContoursPovRayFile();
592 	hideColorMapContours();
593 	reDrawContoursPlane = FALSE;
594 }
595 /********************************************************/
free_iso_all()596 void free_iso_all()
597 {
598 	set_status_label_info("IsoSurface","Nothing");
599 	if(isopositive) isopositive = iso_free(isopositive);
600 	if(isonegative) isonegative = iso_free(isonegative);
601 	if(isonull) isonull = iso_free(isonull);
602 	RebuildSurf = TRUE;
603 }
604 /********************************************************/
free_surfaces_all()605 void free_surfaces_all()
606 {
607 	if(positiveSurfaces)
608 	{
609 		gint i;
610 		for(i=0;i<numberOfSurfaces;i++)
611 		if (glIsList(positiveSurfaces[i]) == GL_TRUE) glDeleteLists(positiveSurfaces[i],1);
612 		g_free(positiveSurfaces);
613 	}
614 	if(negativeSurfaces)
615 	{
616 		gint i;
617 		for(i=0;i<numberOfSurfaces;i++)
618 		if (glIsList(negativeSurfaces[i]) == GL_TRUE) glDeleteLists(negativeSurfaces[i],1);
619 		g_free(negativeSurfaces);
620 	}
621 	if(nullSurfaces)
622 	{
623 		gint i;
624 		for(i=0;i<numberOfSurfaces;i++)
625 		if (glIsList(nullSurfaces[i]) == GL_TRUE) glDeleteLists(nullSurfaces[i],1);
626 		g_free(nullSurfaces);
627 	}
628 	numberOfSurfaces = 0;
629 	positiveSurfaces = NULL;
630 	negativeSurfaces = NULL;
631 	nullSurfaces = NULL;
632 	free_iso_all();
633 	deleteSurfacesPovRayFile();
634 }
635 /********************************************************/
free_objects_all()636 void free_objects_all()
637 {
638 	free_surfaces_all();
639 	free_contours_all();
640 	delete_rings_all();
641 	free_planes_mapped_all();
642 	deleteContoursPovRayFile();
643 	deletePlanesMappedPovRayFile();
644 }
645 /********************************************************/
free_grid_all()646 void free_grid_all()
647 {
648 	set_status_label_info("Grid","Nothing");
649 	if(grid)
650 		grid = free_grid(grid);
651 }
652 /********************************************************/
add_objects_for_new_grid()653 void add_objects_for_new_grid()
654 {
655 	reset_old_geometry();
656 	add_void_maps();
657 	add_void_contours();
658 	if(!showOneSurface || numberOfSurfaces<1 ) add_surface();
659 }
660 /********************************************************/
Define_Iso(gdouble isovalue)661 void Define_Iso(gdouble isovalue)
662 {
663 	free_iso_all();
664 	set_status_label_info("IsoSurface","Computing");
665 
666 	/* printf("DefineIso newSUrface = %d\n",newSurface);*/
667 	if(grid)
668 	{
669 		if(newSurface || numberOfSurfaces<1 )
670 			if(!showOneSurface || numberOfSurfaces<1 ) add_surface();
671 		newSurface = FALSE;
672 		isopositive=define_iso_surface(grid,isovalue, grid->mapped );
673 		if(fabs(isovalue)>1e-13)
674 		isonegative=define_iso_surface(grid,-isovalue, grid->mapped );
675 		if(isopositive != NULL || isonegative != NULL) set_status_label_info("IsoSurface","Ok");
676 	}
677 	RebuildSurf = TRUE;
678 }
679 /********************************************************/
Define_Grid()680 void Define_Grid()
681 {
682 	free_grid_all();
683 	/*
684 	free_contours_all();
685 	free_planes_mapped_all();
686 	*/
687 
688 	grid = define_grid(NumPoints,limits);
689 	if(grid)
690 	{
691 		if(!showOneSurface || numberOfSurfaces<1 ) add_surface();
692 		free_iso_all();
693 		limits.MinMax[0][3] = grid->limits.MinMax[0][3];
694 		limits.MinMax[1][3] = grid->limits.MinMax[1][3];
695 	}
696 }
697 /********************************************************/
698 static V4d Quat;
699 static GLdouble BeginX = 0;
700 static GLdouble BeginY = 0;
701 /*********************************************************************************************/
resetBeginNegative()702 void resetBeginNegative()
703 {
704 	BeginX = -1;
705 	BeginY = -1;
706 }
707 /*********************************************************************************************/
getQuat(gdouble q[])708 void getQuat(gdouble q[])
709 {
710 	gint i;
711 	for(i=0;i<4;i++) q[i] = Quat[i];
712 }
713 /*********************************************************************************************/
SetLight()714 static void SetLight()
715 {
716 	static float lmodel_ambient[] = {0.1, 0.1, 0.1, 0.1};
717 	static float lmodel_twoside[] = {GL_TRUE};
718 	static float lmodel_local[] = {GL_FALSE};
719 
720 	static V4d light0_ambient  = {0.5, 0.5, 0.5, 1.0};
721 	static V4d light0_diffuse  = {1.0, 1.0, 1.0, 0.0};
722 	static V4d light0_specular = {1.0, 1.0, 1.0, 0.0};
723 
724 	static V4d light1_ambient  = {1.0, 1.0, 1.0, 1.0};
725 	static V4d light1_diffuse  = {1.0, 1.0, 1.0, 0.0};
726 	static V4d light1_specular = {1.0, 1.0, 1.0, 0.0};
727 
728 	static V4d light2_ambient  = {0.1, 0.1, 0.1, 1.0};
729 	static V4d light2_diffuse  = {1.0, 1.0, 1.0, 0.0};
730 	static V4d light2_specular = {1.0, 1.0, 1.0, 0.0};
731 
732 	glLightdv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
733 	glLightdv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
734 	glLightdv(GL_LIGHT0, GL_SPECULAR, light0_specular);
735 	glLightdv(GL_LIGHT0, GL_POSITION, light0_position);
736 
737 	glLightdv(GL_LIGHT1, GL_AMBIENT, light1_ambient);
738 	glLightdv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
739 	glLightdv(GL_LIGHT1, GL_SPECULAR, light1_specular);
740 	glLightdv(GL_LIGHT1, GL_POSITION, light1_position);
741 
742 	glLightdv(GL_LIGHT2, GL_AMBIENT, light2_ambient);
743 	glLightdv(GL_LIGHT2, GL_DIFFUSE, light2_diffuse);
744 	glLightdv(GL_LIGHT2, GL_SPECULAR, light2_specular);
745 	glLightdv(GL_LIGHT2, GL_POSITION, light2_position);
746 
747 	glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_local);
748 	glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
749 	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
750 	glEnable(GL_LIGHTING);
751 	glDisable(GL_LIGHT0);
752 	glDisable(GL_LIGHT1);
753 	glDisable(GL_LIGHT2);
754 	if(lightOnOff[0])
755 		glEnable(GL_LIGHT0);
756 	if(lightOnOff[1])
757 		glEnable(GL_LIGHT1);
758 	if(lightOnOff[2])
759 		glEnable(GL_LIGHT2);
760 }
761 /*****************************************************************************/
InitGL()762 void	InitGL()
763 {
764 
765 	/* static GLdouble fog_color[4] = { 0.0, 0.0, 0.0, 0.0 };*/
766  	/* remove back faces */
767 	glEnable(GL_DEPTH_TEST);
768 	glDisable(GL_CULL_FACE);
769 	glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);
770 	/*glEnable(GL_COLOR_MATERIAL);*/
771     	glEnable(GL_NORMALIZE);
772 	glShadeModel(GL_SMOOTH);
773 	SetLight();
774 	init_labels_font();
775 	/*
776 	glInitFontsOld();
777 	*/
778 	glInitFonts(&ft2_context);
779 	/*
780 	glFogi(GL_FOG_MODE, GL_EXP);
781 	glFogf(GL_FOG_DENSITY, 0.15);
782 	glFogdv(GL_FOG_COLOR, fog_color);
783 	*/
784 }
785 /*****************************************************************************/
init(GtkWidget * widget)786 gint init(GtkWidget *widget)
787 {
788 	GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
789 	GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
790 
791 	if(!GTK_IS_WIDGET(widget)) return TRUE;
792 	if(!GTK_WIDGET_REALIZED(widget)) return TRUE;
793 
794 	if (gdk_gl_drawable_gl_begin (gldrawable, glcontext))
795 	{
796 		glViewport(0,0, widget->allocation.width, widget->allocation.height);
797 		InitGL();
798 		gdk_window_invalidate_rect (gtk_widget_get_parent_window (widget), &widget->allocation, TRUE);
799 		/* gdk_window_process_updates (gtk_widget_get_parent_window (widget), TRUE);*/
800 	}
801 	return TRUE;
802 }
803 /*****************************************************************************/
redrawGeometry()804 static void redrawGeometry()
805 {
806 	gint i;
807 	if (RebuildGeom || glIsList(GeomList) != GL_TRUE )
808 	{
809 		/* Debug("Re Gen Geom List\n");*/
810 		GeomList = GeomGenList(GeomList, scaleBall, scaleStick, getShowBox());
811 		GeomShowList(GeomList);
812 		DipList = DipGenList(DipList);
813 		DipShowList(DipList);
814 
815 		axisList = axisGenList(axisList);
816 		axisShowList(axisList);
817 
818 		principalAxisList = principalAxisGenList(principalAxisList);
819 		principalAxisShowList(principalAxisList);
820 
821 		VibList = VibGenList(VibList);
822 		VibShowList(VibList);
823 		RebuildGeom = FALSE;
824 
825 		delete_rings_all();
826 	}
827 	else
828 	{
829 		/* Debug("from Lists GeomList = %d\n",GeomList);*/
830 		GeomShowList(GeomList);
831 		DipShowList(DipList);
832 		axisShowList(axisList);
833 		principalAxisShowList(principalAxisList);
834 		VibShowList(VibList);
835 
836 		for(i=0;i<nMaxListRings;i++)
837 			if(selectedListRings[i])
838 					IsoRingsAllShowLists(listRings[i]);
839 	}
840 }
841 /*****************************************************************************/
redrawSurfaces()842 static void  redrawSurfaces()
843 {
844 	if (RebuildSurf && numberOfSurfaces>0)
845 	{
846 		gint i;
847 		IsoGenLists(&positiveSurfaces[numberOfSurfaces-1], &negativeSurfaces[numberOfSurfaces-1], &nullSurfaces[numberOfSurfaces-1],isopositive,isonegative,isonull);
848 		createLastSurfacePovRay();
849 		for(i=0;i<numberOfSurfaces;i++)
850 		IsoShowLists(positiveSurfaces[i], negativeSurfaces[i], nullSurfaces[i]);
851 		RebuildSurf = FALSE;
852 	}
853 	else
854 	{
855 		gint i;
856 		for(i=0;i<numberOfSurfaces;i++)
857 		IsoShowLists(positiveSurfaces[i], negativeSurfaces[i], nullSurfaces[i]);
858 	}
859 }
860 /*****************************************************************************/
redrawBox()861 static void  redrawBox()
862 {
863 	GLuint box = 0;
864 	if(!showBox) return;
865 	BoxGenLists(&box);
866 	BoxShowLists(box);
867 }
868 /*****************************************************************************/
redrawContours()869 static void redrawContours()
870 {
871 	gboolean reBuildFirstPlaneContours = TRUE;
872 	gint  i;
873 
874 	if(newContours && nPlanesContours>0)
875 	{
876 		if(nPlanesContours==1 && !animateContours ) showColorMapContours();
877 		else hideColorMapContours();
878 
879 		if(newPlaneGridForContours)
880 		{
881 			/*
882 			Debug("Begin Contourlist calculation\n");
883 			Debug("GridPlans = %d\n",gridPlaneForContours);
884 			Debug("numberOfContours = %d\n",numberOfContours);
885 			Debug("values = %d\n",values);
886 			*/
887 	   		contoursLists[nPlanesContours-1]= ContoursGenLists(contoursLists[nPlanesContours-1],gridPlaneForContours,numberOfContours,values,i0Contours,i1Contours,numPlaneContours,gapContours);
888 			addContoursPovRay(gridPlaneForContours,numberOfContours,values,i0Contours,i1Contours,numPlaneContours,gapContours);
889 			/* Debug("End Contourlist calculation\n");*/
890 			newPlaneGridForContours = FALSE;
891 
892 			if(nPlanesContours!=1)
893 			{
894 				if(gridPlaneForContours) g_free(gridPlaneForContours);
895 				gridPlaneForContours = NULL;
896 			}
897 
898 		}
899 		else
900 		{
901 	   		contoursLists[nPlanesContours-1]= ContoursGenLists(contoursLists[nPlanesContours-1],grid,numberOfContours,values,i0Contours,i1Contours,numPlaneContours,gapContours);
902 	   		addContoursPovRay(grid,numberOfContours,values,i0Contours,i1Contours,numPlaneContours,gapContours);
903 		}
904 		newContours = FALSE;
905 		reBuildFirstPlaneContours = FALSE;
906 
907 	}
908 	if(nPlanesContours>1 && gridPlaneForContours)
909 	{
910 		if(gridPlaneForContours) g_free(gridPlaneForContours);
911 		gridPlaneForContours = NULL;
912 	}
913 	if(reBuildFirstPlaneContours && nPlanesContours==1 && BeginX == -1 )
914 	{
915 		deleteContoursPovRayFile();
916 		if(gridPlaneForContours && reDrawContoursPlane)
917 		{
918 	   		contoursLists[nPlanesContours-1]= ContoursGenLists(contoursLists[nPlanesContours-1],gridPlaneForContours,numberOfContours,values,i0Contours,i1Contours,numPlaneContours,gapContours);
919 			addContoursPovRay(gridPlaneForContours,numberOfContours,values,i0Contours,i1Contours,numPlaneContours,gapContours);
920 		}
921 		else
922 		if(reDrawContoursPlane)
923 		{
924 	   		contoursLists[nPlanesContours-1]= ContoursGenLists(contoursLists[nPlanesContours-1],grid,numberOfContours,values,i0Contours,i1Contours,numPlaneContours,gapContours);
925 	   		addContoursPovRay(grid,numberOfContours,values,i0Contours,i1Contours,numPlaneContours,gapContours);
926 		}
927 	}
928 
929 	for(i=0;i<nPlanesContours;i++) ContoursShowLists(contoursLists[i]);
930 }
931 /*****************************************************************************/
redrawPlanesMapped()932 static void redrawPlanesMapped()
933 {
934 	gboolean reBuildFirstPlaneMapped = TRUE;
935 	gint i;
936 
937 	if(newPlaneMapped && nPlanesMapped>0)
938 	{
939 		if(nPlanesMapped==1 && !animatePlanesMapped) showColorMapPlanesMapped();
940 		else hideColorMapPlanesMapped();
941 
942 		if(newPlaneGridForPlanesMapped)
943 		{
944 	   		planesMappedLists[nPlanesMapped-1]= PlanesMappedGenLists(planesMappedLists[nPlanesMapped-1],gridPlaneForPlanesMapped,i0PlaneMapped,i1PlaneMapped,numPlaneMaps,gapPlanesMapped);
945 			addPlaneMappedPovRay(gridPlaneForPlanesMapped,i0PlaneMapped,i1PlaneMapped,numPlaneMaps,gapPlanesMapped);
946 
947 			newPlaneGridForPlanesMapped = FALSE;
948 
949 			if(nPlanesMapped!=1)
950 			{
951 				if(gridPlaneForPlanesMapped) g_free(gridPlaneForPlanesMapped);
952 				gridPlaneForPlanesMapped = NULL;
953 			}
954 
955 		}
956 		else
957 		{
958 	   		planesMappedLists[nPlanesMapped-1]= PlanesMappedGenLists(planesMappedLists[nPlanesMapped-1],grid,i0PlaneMapped,i1PlaneMapped,numPlaneMaps,gapPlanesMapped);
959 	   		addPlaneMappedPovRay(grid,i0PlaneMapped,i1PlaneMapped,numPlaneMaps,gapPlanesMapped);
960 		}
961 		newPlaneMapped = FALSE;
962 		reBuildFirstPlaneMapped = FALSE;
963 
964 	}
965 	if(nPlanesMapped>1 && gridPlaneForPlanesMapped)
966 	{
967 		if(gridPlaneForPlanesMapped) g_free(gridPlaneForPlanesMapped);
968 		gridPlaneForPlanesMapped = NULL;
969 	}
970 	if(reBuildFirstPlaneMapped && nPlanesMapped==1 && BeginX == -1 )
971 	{
972 		deletePlanesMappedPovRayFile();
973 		if(gridPlaneForPlanesMapped&& reDrawPlaneMappedPlane)
974 		{
975 	   		planesMappedLists[nPlanesMapped-1]= PlanesMappedGenLists(planesMappedLists[nPlanesMapped-1],gridPlaneForPlanesMapped,i0PlaneMapped,i1PlaneMapped,numPlaneMaps,gapPlanesMapped);
976 			addPlaneMappedPovRay(gridPlaneForPlanesMapped,i0PlaneMapped,i1PlaneMapped,numPlaneMaps,gapPlanesMapped);
977 		}
978 		else
979 		if(reDrawPlaneMappedPlane)
980 		{
981 	   		planesMappedLists[nPlanesMapped-1]= PlanesMappedGenLists(planesMappedLists[nPlanesMapped-1],grid,i0PlaneMapped,i1PlaneMapped,numPlaneMaps,gapPlanesMapped);
982 	   		addPlaneMappedPovRay(grid,i0PlaneMapped,i1PlaneMapped,numPlaneMaps,gapPlanesMapped);
983 		}
984 	}
985 
986 	for(i=0;i<nPlanesMapped;i++) PlanesMappedShowLists(planesMappedLists[i]);
987 }
988 /*****************************************************************************/
createImagesFiles()989 static void createImagesFiles()
990 {
991 		if(createBMPFiles)
992 		{
993 			gchar* message;
994 			gchar* t = g_strdup_printf("The %s%sgab%d.bmp file was created",get_last_directory(),G_DIR_SEPARATOR_S,numBMPFile);
995 			message = new_bmp(get_last_directory(), ++numBMPFile);
996 			if(message == NULL) setTextInProgress(t);
997 			else
998 			{
999     				GtkWidget* m;
1000 				createBMPFiles = FALSE;
1001 				numBMPFile = 0;
1002     				m = Message(message,"Error",TRUE);
1003 				gtk_window_set_modal (GTK_WINDOW (m), TRUE);
1004 			}
1005 			g_free(t);
1006 
1007 		}
1008 		if(createPPMFiles)
1009 		{
1010 			gchar* message;
1011 			gchar* t = g_strdup_printf("The %s%sgab%d.ppm file was created",get_last_directory(),G_DIR_SEPARATOR_S,numPPMFile);
1012 			message = new_ppm(get_last_directory(), ++numPPMFile);
1013 			if(message == NULL)
1014 				setTextInProgress(t);
1015 			else
1016 			{
1017     				GtkWidget* m;
1018 				createPPMFiles = FALSE;
1019 				numPPMFile = 0;
1020     				m = Message(message,"Error",TRUE);
1021 				gtk_window_set_modal (GTK_WINDOW (m), TRUE);
1022 			}
1023 			g_free(t);
1024 
1025 		}
1026 		if(createPOVFiles)
1027 		{
1028 			gchar* message;
1029 			gchar* t = g_strdup_printf("The %s%sgab%d.pov file was created",get_last_directory(),G_DIR_SEPARATOR_S,numPOVFile);
1030 			message = new_pov(get_last_directory(), ++numPOVFile);
1031 			if(message == NULL) setTextInProgress(t);
1032 			else
1033 			{
1034     				GtkWidget* m;
1035 				createPOVFiles = FALSE;
1036 				numPOVFile = 0;
1037     				m = Message(message,"Error",TRUE);
1038 				gtk_window_set_modal (GTK_WINDOW (m), TRUE);
1039 			}
1040 			g_free(t);
1041 
1042 		}
1043 		if(!createBMPFiles && !createPPMFiles && !createPOVFiles) setTextInProgress(" ");
1044 }
1045 /*****************************************************************************/
redrawGL2PS()1046 gint redrawGL2PS()
1047 {
1048 	GLdouble m[4][4];
1049 	GtkWidget *widget = GLArea;
1050 	if(!GTK_IS_WIDGET(widget)) return TRUE;
1051 	if(!GTK_WIDGET_REALIZED(widget)) return TRUE;
1052 
1053     	glMatrixMode(GL_PROJECTION);
1054     	glLoadIdentity();
1055 	addFog();
1056 	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
1057 	set_background_color();
1058 
1059 	mYPerspective(45,(GLdouble)widget->allocation.width/(GLdouble)widget->allocation.height,1,100);
1060     	glMatrixMode(GL_MODELVIEW);
1061 	glLoadIdentity();
1062 	if(optcol==-1) drawChecker();
1063 
1064     	glMatrixMode(GL_PROJECTION);
1065     	glLoadIdentity();
1066 	if(perspective)
1067 		mYPerspective(Zoom,(GLdouble)widget->allocation.width/(GLdouble)widget->allocation.height,zNear,zFar);
1068 	else
1069 	{
1070 	  	gdouble fw = (GLdouble)widget->allocation.width/(GLdouble)widget->allocation.height;
1071 	  	gdouble fh = 1.0;
1072 		glOrtho(-fw,fw,-fh,fh,-1,1);
1073 	}
1074 
1075     	glMatrixMode(GL_MODELVIEW);
1076 	glLoadIdentity();
1077 	if(perspective)
1078 		glTranslatef(Trans[0],Trans[1],Trans[2]);
1079 	else
1080 	{
1081 		 glTranslatef(Trans[0]/10,Trans[1]/10,0);
1082 		 glScalef(1/Zoom*2,1/Zoom*2,1/Zoom*2);
1083 	}
1084 	SetLight();
1085 
1086 	build_rotmatrix(m,Quat);
1087 	glMultMatrixd(&m[0][0]);
1088 
1089 	redrawGeometry();
1090 	redrawSurfaces();
1091 	redrawBox();
1092 	redrawContours();
1093 	redrawPlanesMapped();
1094 	if(get_show_symbols() || get_show_numbers() || get_show_charges()) showLabelSymbolsNumbersCharges(ft2_context);
1095 	if(get_show_dipole()) showLabelDipole(ft2_context);
1096 	if(get_show_distances()) showLabelDistances(ft2_context);
1097 	if(get_show_axes()) showLabelAxes(ft2_context);
1098 	if(get_show_axes()) showLabelPrincipalAxes(ft2_context);
1099 	showLabelTitle(GLArea->allocation.width,GLArea->allocation.height, ft2_context);
1100 
1101 	/* Swap backbuffer to front */
1102 	glFlush();
1103 
1104 	return TRUE;
1105 }
1106 /*****************************************************************************/
redraw(GtkWidget * widget,gpointer data)1107 static gint redraw(GtkWidget *widget, gpointer data)
1108 {
1109 	GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
1110 	GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
1111 	GLdouble m[4][4];
1112 	if(!GTK_IS_WIDGET(widget)) return TRUE;
1113 	if(!GTK_WIDGET_REALIZED(widget)) return TRUE;
1114 
1115 	if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext)) return FALSE;
1116 
1117     	glMatrixMode(GL_PROJECTION);
1118     	glLoadIdentity();
1119 	addFog();
1120 	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
1121 	set_background_color();
1122 
1123 	mYPerspective(45,(GLdouble)widget->allocation.width/(GLdouble)widget->allocation.height,1,100);
1124     	glMatrixMode(GL_MODELVIEW);
1125 	glLoadIdentity();
1126 	if(optcol==-1) drawChecker();
1127 
1128     	glMatrixMode(GL_PROJECTION);
1129     	glLoadIdentity();
1130 	if(perspective)
1131 		mYPerspective(Zoom,(GLdouble)widget->allocation.width/(GLdouble)widget->allocation.height,zNear,zFar);
1132 	else
1133 	{
1134 	  	gdouble fw = (GLdouble)widget->allocation.width/(GLdouble)widget->allocation.height;
1135 	  	gdouble fh = 1.0;
1136 		glOrtho(-fw,fw,-fh,fh,-1,1);
1137 	}
1138 
1139     	glMatrixMode(GL_MODELVIEW);
1140 	glLoadIdentity();
1141 	if(perspective)
1142 		glTranslatef(Trans[0],Trans[1],Trans[2]);
1143 	else
1144 	{
1145 		 glTranslatef(Trans[0]/10,Trans[1]/10,0);
1146 		 glScalef(1/Zoom*2,1/Zoom*2,1/Zoom*2);
1147 	}
1148 	SetLight();
1149 
1150 	build_rotmatrix(m,Quat);
1151 	glMultMatrixd(&m[0][0]);
1152 
1153 	redrawGeometry();
1154 	redrawSurfaces();
1155 	redrawBox();
1156 	redrawContours();
1157 	redrawPlanesMapped();
1158 	if(get_show_symbols() || get_show_numbers() || get_show_charges()) showLabelSymbolsNumbersCharges(ft2_context);
1159 	if(get_show_dipole()) showLabelDipole(ft2_context);
1160 	if(get_show_distances()) showLabelDistances(ft2_context);
1161 	if(get_show_axes()) showLabelAxes(ft2_context);
1162 	if(get_show_axes()) showLabelPrincipalAxes(ft2_context);
1163 	showLabelTitle(GLArea->allocation.width,GLArea->allocation.height, ft2_context);
1164 
1165 	/*
1166 	glEnable(GL_DEPTH_TEST);
1167 	glDepthMask(GL_TRUE);
1168 	glDepthRange(0.0f,1.0f);
1169 	*/
1170 
1171 	if (gdk_gl_drawable_is_double_buffered (gldrawable))
1172 		gdk_gl_drawable_swap_buffers (gldrawable);
1173 	else glFlush ();
1174 	gdk_gl_drawable_gl_end (gldrawable);
1175 
1176         while( gtk_events_pending() ) gtk_main_iteration();
1177 
1178 	createImagesFiles();
1179 	/* gtk_widget_queue_draw(PrincipalWindow);*/
1180 
1181 	return TRUE;
1182 }
1183 /*********************************************************************************/
1184 /* When widget is exposed it's contents are redrawn. */
draw(GtkWidget * widget,GdkEventExpose * event)1185 static gint draw(GtkWidget *widget, GdkEventExpose *event)
1186 {
1187 	static gint i = 0;
1188 	i++;
1189 	if (!GTK_IS_WIDGET(widget)) return TRUE;
1190 	if(!GTK_WIDGET_REALIZED(widget)) return TRUE;
1191 	/* Draw only last expose. */
1192 	if (event->count > 0) return FALSE;
1193 
1194 	redraw(widget,NULL);
1195 
1196 	return FALSE;
1197 }
1198 
1199 /*****************************************************************************/
1200 /* When GLArea widget size changes, viewport size is set to match the new size */
reshape(GtkWidget * widget,GdkEventConfigure * event)1201 static gint reshape(GtkWidget *widget, GdkEventConfigure *event)
1202 {
1203 	GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
1204 	GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
1205 
1206 	if(!GTK_IS_WIDGET(widget)) return TRUE;
1207 	if(!GTK_WIDGET_REALIZED(widget)) return TRUE;
1208 
1209 	if (gdk_gl_drawable_gl_begin (gldrawable, glcontext))
1210 	{
1211 		/* pthread_mutex_lock (&theRender_mutex);*/
1212 		glViewport(0,0, widget->allocation.width, widget->allocation.height);
1213 		glMatrixMode(GL_PROJECTION);
1214 		glLoadIdentity();
1215 		if(perspective)
1216 			mYPerspective(Zoom,(GLdouble)widget->allocation.width/(GLdouble)widget->allocation.height,zNear,zFar);
1217 		else
1218 		{
1219 			gdouble fw = (GLdouble)widget->allocation.width/(GLdouble)widget->allocation.height;
1220 			gdouble fh = 1.0;
1221 			glOrtho(-fw,fw,-fh,fh,-1,1);
1222 		}
1223 		glMatrixMode(GL_MODELVIEW);
1224 		glLoadIdentity();
1225 		gdk_gl_drawable_gl_end (gldrawable);
1226 		/* pthread_mutex_unlock (&theRender_mutex);*/
1227 
1228 		gdk_window_invalidate_rect (gtk_widget_get_parent_window (widget), &widget->allocation, TRUE);
1229 		gdk_window_process_updates (gtk_widget_get_parent_window (widget), TRUE);
1230 	}
1231 	return TRUE;
1232 }
1233 
1234 /********************************************************************************/
set_key_press(GtkWidget * wid,GdkEventKey * event,gpointer data)1235 static gint set_key_press(GtkWidget* wid, GdkEventKey *event, gpointer data)
1236 {
1237 	if((event->keyval == GDK_Control_L || event->keyval == GDK_Control_R) )
1238 		g_object_set_data(G_OBJECT (wid), "ControlKeyPressed", GINT_TO_POINTER(1));
1239 	if((event->keyval == GDK_Alt_L || event->keyval == GDK_Alt_R) )
1240 		g_object_set_data(G_OBJECT (wid), "ControlKeyPressed", GINT_TO_POINTER(1));
1241 
1242 	if((event->keyval == GDK_c || event->keyval == GDK_C) )
1243 	{
1244 		gint ControlKeyPressed = GPOINTER_TO_INT(g_object_get_data(G_OBJECT (wid), "ControlKeyPressed"));
1245 		if(ControlKeyPressed)
1246 		{
1247 			/* printf("Copy to clipboard\n");*/
1248 			copy_to_clipboard();
1249 		}
1250 
1251 	}
1252 	GTK_WIDGET_GET_CLASS(wid)->key_press_event(wid, event);
1253 	return TRUE;
1254 
1255 }
1256 /********************************************************************************/
set_key_release(GtkWidget * wid,GdkEventKey * event,gpointer data)1257 static gint set_key_release(GtkWidget* wid, GdkEventKey *event, gpointer data)
1258 {
1259 	if((event->keyval == GDK_Control_L || event->keyval == GDK_Control_R) )
1260 		g_object_set_data(G_OBJECT (wid), "ControlKeyPressed", GINT_TO_POINTER(0));
1261 	if((event->keyval == GDK_Alt_L || event->keyval == GDK_Alt_R) )
1262 		g_object_set_data(G_OBJECT (wid), "ControlKeyPressed", GINT_TO_POINTER(0));
1263 	return TRUE;
1264 }
1265 /*****************************************************************************
1266 *  event_dispatcher
1267 ******************************************************************************/
event_dispatcher(GtkWidget * DrawingArea,GdkEvent * event,gpointer data)1268 static gint event_dispatcher(GtkWidget *DrawingArea, GdkEvent *event, gpointer data)
1269 {
1270 	GdkEventButton *bevent;
1271 
1272 	switch (event->type)
1273 	{
1274 		case GDK_BUTTON_PRESS:
1275 		{
1276 			bevent = (GdkEventButton *) event;
1277 			if (bevent->button == 3) /* Right Button ==> Popup Menu */
1278 			{
1279 				PopupMenuIsOpen = TRUE;
1280 				popuo_menu_GL(bevent->button, bevent->time);
1281 			}
1282 			return TRUE;
1283 		}
1284 		default : return TRUE;
1285 	}
1286 	return FALSE;
1287 }
1288 
1289 /******************************************************************************/
glarea_button_release(GtkWidget * widget,GdkEventButton * event)1290 gint glarea_button_release (GtkWidget *widget, GdkEventButton *event)
1291 {
1292 	if (event->button == 1 || event->button == 2)
1293 	{
1294 		resetBeginNegative();
1295 		redraw(widget,NULL);
1296 		return TRUE;
1297 	}
1298 	return FALSE;
1299 }
1300 /******************************************************************************/
glarea_button_press(GtkWidget * widget,GdkEventButton * event)1301 gint glarea_button_press(GtkWidget *widget, GdkEventButton *event)
1302 {
1303 	if (event->button == 1 || event->button == 2)
1304 	{
1305 		/* beginning of drag, reset mouse position */
1306 		BeginX= event->x;
1307 		BeginY = event->y;
1308 		return TRUE;
1309 	}
1310 	return FALSE;
1311 }
1312 
1313 /*****************************************************************/
rotation(GtkWidget * widget,GdkEventMotion * event,gint x,gint y)1314 static void rotation(GtkWidget *widget, GdkEventMotion *event,gint x, gint y)
1315 {
1316 	gdouble width;
1317 	gdouble height;
1318 
1319 	width  = widget->allocation.width;
1320 	height = widget->allocation.height;
1321 	GLdouble spin_quat[4];
1322 
1323 	/* drag in progress, simulate trackball */
1324 	trackball(spin_quat,
1325 	      (2.0*BeginX-       width) / width,
1326 	      (     height - 2.0*BeginY) / height,
1327 	      (           2.0*x -       width) / width,
1328 	      (     height -            2.0*y) / height);
1329 	add_quats(spin_quat, Quat, Quat);
1330 
1331 	BeginX = x;
1332 	BeginY = y;
1333 }
1334 /*****************************************************************/
rotationAboutAnAxis(GtkWidget * widget,gdouble phi,gint axe)1335 void rotationAboutAnAxis(GtkWidget *widget, gdouble phi, gint axe)
1336 {
1337 	GLdouble spin_quat[4] = {0,0,0,0};
1338 	gdouble phiRad = phi/180*PI;
1339 	if(axe<0 || axe>2) return;
1340 	spin_quat[axe] = 1.0;
1341 
1342 	v3d_scale(spin_quat,sin(phiRad/2));
1343 	spin_quat[3] = cos(phiRad/2);
1344 
1345 	add_quats(spin_quat, Quat, Quat);
1346 
1347 }
1348 /*****************************************************************/
rotationXYZ(GtkWidget * widget,GdkEventMotion * event,gint x,gint y,gint axe)1349 static void rotationXYZ(GtkWidget *widget, GdkEventMotion *event,gint x, gint y, gint axe)
1350 {
1351   GLdouble spin_quat[4];
1352   gint width = widget->allocation.width;
1353   gint height = widget->allocation.height;
1354 
1355 
1356   if(axe==0)
1357   {
1358     BeginX = x = widget->allocation.width/2;
1359   }
1360   if(axe==1)
1361   {
1362     BeginY = y = widget->allocation.height/2;
1363   }
1364   if(axe==2)
1365   {
1366 	  gdouble phi = 1;
1367 	  if(abs(BeginX-x)>abs(BeginY-y))
1368 	  {
1369 		  gdouble sign  = 1.0;
1370 		  if(BeginY> height/2 && BeginX<x) sign = -1;
1371 		  if(BeginY< height/2 && BeginX>x) sign = -1;
1372 		  phi = sign* fabs(BeginX-x)/width*180;
1373 	  }
1374 	  else
1375 	  {
1376 		  gdouble sign = 1.0;
1377 		  if(BeginX> width/2 && BeginY>y) sign = -1;
1378 		  if(BeginX< width/2 && BeginY<y) sign = -1;
1379 		  phi = sign* fabs(BeginY-y)/height*180;
1380 	  }
1381 	  rotationAboutAnAxis(widget, phi, 2);
1382   	BeginX = x;
1383   	BeginY = y;
1384 	  return;
1385   }
1386 
1387 
1388    /* drag in progress, simulate trackball */
1389     trackball(spin_quat,
1390 	      (2.0*BeginX - width) / width,
1391 	      (height     - 2.0*BeginY) / height,
1392 	      (2.0*x      - width) / width,
1393 	      (height     - 2.0*y) / height);
1394     add_quats(spin_quat, Quat, Quat);
1395 
1396   BeginX = x;
1397   BeginY = y;
1398 
1399 }
1400 /*****************************************************************/
zoom(GtkWidget * widget,GdkEventMotion * event,gint x,gint y)1401 static void zoom(GtkWidget *widget, GdkEventMotion *event,gint x,gint y)
1402 {
1403 
1404 	/* gdouble width;*/
1405 	gdouble height;
1406 
1407 	/* width  = widget->allocation.width;*/
1408 	height = widget->allocation.height;
1409 
1410 	/* zooming drag */
1411 	Zoom -= ((y - BeginY) / height) * 40;
1412 	if (Zoom < 0.1) Zoom = 0.1;
1413 	if (Zoom > 500) Zoom = 500;
1414 
1415 	BeginX = x;
1416 	BeginY = y;
1417 }
1418 /*****************************************************************/
translate(GtkWidget * widget,GdkEventMotion * event,gint x,gint y)1419 static void translate(GtkWidget *widget, GdkEventMotion *event,gint x,gint y)
1420 {
1421 	gdouble width;
1422 	gdouble height;
1423 
1424 	width  = widget->allocation.width;
1425 	height = widget->allocation.height;
1426 
1427 	Trans[0] += ((x - BeginX) / width) * 40;
1428 	Trans[1] += ((BeginY - y) / height) * 40;
1429 
1430 	BeginX = x;
1431 	BeginY = y;
1432 }
1433 /******************************************************************************/
glarea_motion_notify(GtkWidget * widget,GdkEventMotion * event)1434 gint glarea_motion_notify(GtkWidget *widget, GdkEventMotion *event)
1435 {
1436   gint x, y;
1437   GdkModifierType state;
1438 
1439 	if (event->is_hint)
1440 	{
1441 #if !defined(G_OS_WIN32)
1442 		gdk_window_get_pointer(event->window, &x, &y, &state);
1443 #else
1444 		state = event->state;
1445 #endif
1446 
1447 	}
1448 	else
1449 		state = event->state;
1450 
1451     x = event->x;
1452     y = event->y;
1453 
1454   if (state & GDK_BUTTON1_MASK)
1455   {
1456 	  switch(OperationType)
1457 	  {
1458 		case  OPERATION_ROTATION_FREE : rotation(widget,event,x,y);
1459 				redraw(widget,NULL);
1460 				 break;
1461 		case  OPERATION_ROTATION_X : rotationXYZ(widget,event,x,y,0);
1462 				redraw(widget,NULL);
1463 				 break;
1464 		case  OPERATION_ROTATION_Y : rotationXYZ(widget,event,x,y,1);
1465 				redraw(widget,NULL);
1466 				 break;
1467 		case  OPERATION_ROTATION_Z : rotationXYZ(widget,event,x,y,2);
1468 				redraw(widget,NULL);
1469 				 break;
1470 		case  OPERATION_ZOOM 	: zoom(widget,event,x,y);
1471 				redraw(widget,NULL);
1472 			     	break;
1473 		case  OPERATION_TRANSLATION	: translate(widget,event,x,y);
1474 				redraw(widget,NULL);
1475 			     	break;
1476 	  }
1477   }
1478 
1479   if (state & GDK_BUTTON2_MASK)
1480   {
1481 		rotation(widget,event,x,y);
1482 		redraw(widget,NULL);
1483   }
1484 
1485   return TRUE;
1486 }
1487 /******************************************************************************/
glarea_rafresh(GtkWidget * widget)1488 gint glarea_rafresh(GtkWidget *widget)
1489 {
1490 	if(!widget) return FALSE;
1491 	redraw(GLArea,NULL);
1492 	return TRUE;
1493 }
1494 /******************************************************************************/
rafresh_window_orb()1495 void rafresh_window_orb()
1496 {
1497 	 if(GLArea != NULL)
1498 	 {
1499 		 gint j;
1500 
1501 		 RebuildGeom = TRUE;
1502 		 RebuildSurf = TRUE;
1503 		 for(j=0;j<nCenters;j++)
1504 			GeomOrb[j].Prop = prop_atom_get(GeomOrb[j].Symb);
1505 
1506 		 redraw(GLArea,NULL);
1507 	 }
1508 }
1509 /********************************************************************************************/
1510 /* Configure the OpenGL framebuffer.*/
configure_gl()1511 static GdkGLConfig *configure_gl()
1512 {
1513 	GdkGLConfig *glconfig;
1514 	GdkGLConfigMode modedouble = GDK_GL_MODE_RGB    | GDK_GL_MODE_DEPTH  | GDK_GL_MODE_DOUBLE;
1515 	GdkGLConfigMode modesimple = GDK_GL_MODE_RGB    | GDK_GL_MODE_DEPTH;
1516 	GdkGLConfigMode mode = GDK_GL_MODE_RGB;
1517 	OpenGLOptions openGLOptions = get_opengl_options();
1518 
1519 	/* Try the user visual */
1520 	if(openGLOptions.rgba !=0)  mode = GDK_GL_MODE_RGBA;
1521 	if(openGLOptions.depthSize!=0) mode |= GDK_GL_MODE_DEPTH;
1522 	if(openGLOptions.alphaSize!=0) mode |= GDK_GL_MODE_ALPHA;
1523 	if(openGLOptions.doubleBuffer!=0) mode |= GDK_GL_MODE_DOUBLE;
1524 	glconfig = gdk_gl_config_new_by_mode (mode);
1525 	if(glconfig!=NULL) return glconfig;
1526 
1527 
1528 	/* Try double-buffered visual */
1529 	glconfig = gdk_gl_config_new_by_mode (modedouble);
1530 	if (glconfig == NULL)
1531 	{
1532       		printf ("\n*** Cannot find the double-buffered visual.\n");
1533       		printf ("\n*** Trying single-buffered visual.\n");
1534 
1535 		/* Try single-buffered visual */
1536 		glconfig = gdk_gl_config_new_by_mode (modesimple);
1537 		if (glconfig == NULL)
1538 		{
1539 	  		printf ("*** No appropriate OpenGL-capable visual found.\n");
1540 	  		exit (1);
1541 		}
1542 	}
1543 	return glconfig;
1544 }
1545 /********************************************************************************/
open_menu(GtkWidget * Win,GdkEvent * event,gpointer Menu)1546 static void open_menu(GtkWidget *Win,  GdkEvent *event, gpointer Menu)
1547 {
1548 	GdkEventButton *bevent;
1549 	bevent = (GdkEventButton *) event;
1550 	popuo_menu_GL( bevent->button, bevent->time);
1551 }
1552 /********************************************************************************/
add_menu_button(GtkWidget * Win,GtkWidget * box)1553 static void add_menu_button(GtkWidget *Win, GtkWidget *box)
1554 {
1555 	GtkWidget* menuButton;
1556         menuButton = gtk_button_new_with_label("M");
1557   	gtk_box_pack_start (GTK_BOX (box), menuButton, FALSE, TRUE, 0);
1558 
1559 	g_signal_connect(G_OBJECT(menuButton), "button_press_event",G_CALLBACK(open_menu), NULL);
1560 	gtk_widget_show (menuButton);
1561 }
1562 /********************************************************************************************/
NewGLArea(GtkWidget * vboxwin)1563 gboolean NewGLArea(GtkWidget* vboxwin)
1564 {
1565 	GtkWidget* frame;
1566   /*
1567 	gchar *info_str;
1568   */
1569 	GtkWidget* table;
1570 	GtkWidget* hboxtoolbar;
1571 	GtkWidget* vbox;
1572 
1573 #define DIMAL 13
1574 	/* int k = 0;*/
1575 	GdkGLConfig *glconfig;
1576 
1577 	/*
1578 	k = 0;
1579 	if(openGLOptions.alphaSize!=0)
1580 	{
1581 		attrlist[k++] = GDK_GL_ALPHA_SIZE;
1582 		attrlist[k++] = 1;
1583 	}
1584 	if(openGLOptions.depthSize!=0)
1585 	{
1586 		attrlist[k++] = GDK_GL_DEPTH_SIZE;
1587 		attrlist[k++] = 1;
1588 	}
1589 	if(openGLOptions.doubleBuffer!=0) attrlist[k++] = GDK_GL_DOUBLEBUFFER;
1590 	*/
1591 	set_show_symbols(FALSE);
1592 	set_show_distances(FALSE);
1593 	trackball(Quat , 0.0, 0.0, 0.0, 0.0);
1594 
1595 	frame = gtk_frame_new (NULL);
1596 	gtk_container_set_border_width (GTK_CONTAINER (frame), 0);
1597   	gtk_frame_set_shadow_type( GTK_FRAME(frame),GTK_SHADOW_ETCHED_OUT);
1598 	gtk_box_pack_start (GTK_BOX (vboxwin), frame, TRUE, TRUE, 0);
1599 	gtk_widget_show (frame);
1600 
1601 	table = gtk_table_new(2,2,FALSE);
1602 	gtk_container_add(GTK_CONTAINER(frame),table);
1603 	gtk_widget_show(GTK_WIDGET(table));
1604 
1605 /*
1606 	hboxtoolbar = gtk_hbox_new (FALSE, 0);
1607 	gtk_widget_show (hboxtoolbar);
1608 	gtk_table_attach(GTK_TABLE(table), hboxtoolbar,0,1,0,1, (GtkAttachOptions)(GTK_FILL | GTK_SHRINK  ), (GtkAttachOptions)(GTK_FILL | GTK_EXPAND ), 0,0);
1609 */
1610 
1611 	vbox = gtk_vbox_new (FALSE, 0);
1612 	gtk_table_attach(GTK_TABLE(table), vbox, 0,1, 0,1, GTK_FILL , GTK_FILL, 0, 0);
1613 	gtk_widget_show(vbox);
1614 	add_menu_button(PrincipalWindow, vbox);
1615 	hboxtoolbar = gtk_hbox_new (FALSE, 0);
1616   	gtk_box_pack_start (GTK_BOX (vbox), hboxtoolbar, TRUE, TRUE, 0);
1617 	gtk_widget_show(hboxtoolbar);
1618 
1619 
1620 	gtk_quit_add_destroy(1, GTK_OBJECT(PrincipalWindow));
1621 
1622 	/* Create new OpenGL widget. */
1623 	/* pthread_mutex_init (&theRender_mutex, NULL);*/
1624 	GLArea = gtk_drawing_area_new ();
1625 	gtk_drawing_area_size(GTK_DRAWING_AREA(GLArea),(gint)(ScreenHeight*0.2),(gint)(ScreenHeight*0.2));
1626 	gtk_table_attach(GTK_TABLE(table),GLArea,1,2,0,1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND  ), (GtkAttachOptions)(GTK_FILL | GTK_EXPAND ), 0,0);
1627 	gtk_widget_show(GTK_WIDGET(GLArea));
1628 	/* Events for widget must be set before X Window is created */
1629 	gtk_widget_set_events(GLArea,
1630 			GDK_EXPOSURE_MASK|
1631 			GDK_BUTTON_PRESS_MASK|
1632 			GDK_BUTTON_RELEASE_MASK|
1633 			GDK_POINTER_MOTION_MASK|
1634 			GDK_POINTER_MOTION_HINT_MASK |
1635 			GDK_SCROLL_MASK
1636 			);
1637 	/* prepare GL */
1638 	glconfig = configure_gl();
1639 	if (!glconfig) { g_assert_not_reached (); }
1640 	if (!gtk_widget_set_gl_capability (GLArea, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE)) { g_assert_not_reached (); }
1641 
1642 	g_signal_connect(G_OBJECT(GLArea), "realize", G_CALLBACK(init), NULL);
1643 	g_signal_connect(G_OBJECT(GLArea), "configure_event", G_CALLBACK(reshape), NULL);
1644 	g_signal_connect(G_OBJECT(GLArea), "expose_event", G_CALLBACK(draw), NULL);
1645 	/*gtk_widget_set_size_request(GTK_WIDGET(GLArea ),(gint)(ScreenHeight*0.2),(gint)(ScreenHeight*0.2));*/
1646 
1647 
1648 	gtk_widget_realize(GTK_WIDGET(PrincipalWindow));
1649 	/*
1650 	info_str = gdk_gl_get_info();
1651 	Debug("%s\n",info_str);
1652 	g_free(info_str);
1653 	*/
1654 
1655 	g_signal_connect (G_OBJECT(GLArea), "button_press_event", G_CALLBACK(glarea_button_press), NULL);
1656 	g_signal_connect_after(G_OBJECT(GLArea), "button_press_event", G_CALLBACK(event_dispatcher), NULL);
1657 	g_signal_connect_after(G_OBJECT(GLArea), "motion_notify_event", G_CALLBACK(glarea_motion_notify), NULL);
1658 	g_signal_connect (G_OBJECT(GLArea), "button_release_event", G_CALLBACK(glarea_button_release), NULL);
1659 
1660 
1661 	create_toolbar_and_popup_menu_GL(hboxtoolbar);
1662 	g_signal_connect(G_OBJECT (PrincipalWindow), "key_press_event", (GCallback) set_key_press, GLArea);
1663 	g_signal_connect(G_OBJECT (PrincipalWindow), "key_release_event", (GCallback) set_key_release, NULL);
1664 
1665 
1666 	return TRUE;
1667 }
1668 /*****************************************************************************/
1669