1 // $Id: CrystalView.cxx 1103 2011-01-15 16:14:13Z martin $
2 //
3 // CrystalView.cxx - main routine for DRAWxtl V5.5 - the GUI version
4 //
5 // Coded using the FLTK 1.1.6 widget set
6 //
7 // Larry W. Finger, Martin Kroeker and Brian Toby
8 //
9 // This module includes many of the support routines for the GUI
10 //
11 // routines contained within this file:
12 //
13 // main - the entry point
14 // AngleInRange - places angle in range -180 to 180
15 // Clear_Last_Omit_cb - callback routine to remove last entry in 'omit' item list
16 // CrystalView::CrystalView constructor
17 // CrystalView::draw - draw routine for CrystalView class
18 // Destroy_Open_Windows - call the destructor for all open windows
19 // Error_Box - display error box
20 // Exit_cb - the callback routine from the "Exit" menu button pressed or when main window is closed
21 // ImportDataFile_cb - Callback from Import External Format menu item
22 // Include_Cutouts_cb - callback routine when 'Include Cutouts' check box is changed
23 // Load_Bond_Data - get bond data from out file into array
24 // LoadConfig - load configuration file
25 // Max_Min_cb - callback routine to readout Max- and Min- sliders
26 // Offset_cb - callback routine when Origin values are changed
27 // pick_box - routine to pick the corners of the slab box overlay
28 // process_hits - routine to process the omit list
29 // Process_Inp - read the DRAWxtl input file
30 // Restore_Working_Copy - restores working copy of str file from saved version
31 // Rotation_cb - callback routine to readout rotation widgets
32 // Save_Current_cb - Callback from Save Current menu button
33 // Save_Working_Copy - Copies the working version of the str file into a "save" file
34 // SelectDataFile_cb - Callback from Select Data File menu item
35 // show_slab_ovl - overlay draw routine for the temporary slab outline
36 // start_picking - routine to pick objects to be omitted from drawing
37 // update_box - routine to process the GL hits from pick_box
38 // Update_Str - routine to update the 'str' file from widget contents
39 // WriteConfig - write updated configuration file
40 // XYZ_Rot_to_Q - X, Y, Z rotations to quaternion
41 // moveto_atom - routine to pick an atom and move the crosshair to it (UNUSED)
42 // pick_label - routine to pick a labeltext and return its number
43
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <ctype.h>
47 #include <math.h>
48 #include <FL/x.H>
49 #include <FL/Fl_Tooltip.H>
50 #include "drawxtl.h"
51 #include "DRAWxtlViewUI.h"
52 #include "EditView.h"
53 #include "Ellipsoids.h"
54 #include "draw_gbl.h"
55
56 extern int Block_CIF;
57
58 extern int volatile w_width;
59
60 extern volatile int w_height;
61
62 extern int w_st_x;
63
64 extern int w_st_y;
65
66 #ifdef WIN32
67 #include <io.h>
68 #include <direct.h>
69 #define AMBLEV 0.2f
70 #define snprintf _snprintf
71 #else
72 #include <unistd.h>
73 #define _chdir chdir
74 #if !defined(__APPLE__)
75 #include <X11/xpm.h>
76 # endif
77 #define AMBLEV 0.2f
78 #endif
79
80 // function prototypes
81
82 #include "DRAWxtl_proto.h"
83
84 #ifdef WIN32
85 const char *flu_file_chooser (const char *, const char *, const char *);
86 char Configure_file[] = { ".drawxtlrc" };
87
88 char foldersymbol = '\\';
89 #else
90 char Configure_file[] = { "~/.drawxtlrc" };
91
92 char foldersymbol = '/';
93 #endif
94
95 #ifdef FREEGLUT24
96 struct freeglut_compat
97 { // ugly hack to access internal data structures of freeglut 2.4
98 int n0;
99 int n1;
100 GLboolean n2;
101 int n3;
102 int n4;
103 GLboolean n5;
104 unsigned int n6;
105 GLboolean Initialised;
106 };
107
108 extern freeglut_compat fgState;
109 #endif
110
111 int
main(int argc,char ** argv)112 main (int argc, char **argv)
113 {
114 int i = 0;
115
116 #if !defined (WIN32) && !defined (__APPLE__)
117 #include "DRAWxtl.xpm"
118 #endif
119
120 LoadConfig (0); /* quick read to get saved size only */
121 drvui = new DRAWxtlViewUI;
122 drvui->destroy = 0;
123 drvui->max_frame = 0;
124 drvui->origin1_flag = 0;
125 drvui->Stereo = 0;
126 drvui->cross_eyed = 1;
127 drvui->stereo_base = 0.05f;
128 drvui->atom_no = NULL;
129 drvui->atom_so = NULL;
130 drvui->orig_atom_no = NULL;
131 drvui->table = NULL;
132 drvui->msgbuffer = (char*) zalloc(sizeof(char));
133 drvui->vert_occ = NULL;
134 drvui->label_scale = 1.0f;
135 drvui->triple[0] = 0;
136 drvui->labels_inited = 0;
137 drvui->auto_ellipse = 0;
138 drvui->nmag_alloc = 0;
139 drvui->nsurf = 0;
140 drvui->crystalDL = 0;
141 drvui->voidmap = NULL;
142 drvui->voidflag = 0;
143 drvui->voiddata1 = NULL;
144 drvui->voiddata2 = NULL;
145 drvui->Cursor_posW = NULL;
146 drvui->cur_reset = -1;
147 init_dynamic_storage ();
148 memset (drvui->saved_x_label, 0, 24 * sizeof (float));
149 memset (drvui->slab_con, 0, sizeof (drvui->slab_con));
150 offset[0] = offset[1] = offset[2] = 0.0f;
151 drvui->glback[0] = drvui->glback[1] = drvui->glback[2] = 1.0f;
152 vzero (drvui->Trans);
153 Fl_Tooltip::font (FL_COURIER_BOLD);
154 Fl_Tooltip::size (12);
155 Fl_Tooltip::color (23);
156 strcpy (drvui->Cur_File, "");
157 strcpy (drvui->Cur_Root, "");
158 drvui->Str_File_Changed = 0;
159 strcpy (drvui->ProgramPath, argv[0]);
160 Omit = new OmitParam;
161 drvui->b_mat[0][0] = drvui->b_mat[1][1] = drvui->b_mat[2][2] = 1.;
162 drvui->b_mat[0][1] = drvui->b_mat[1][0] = 0.;
163 drvui->b_mat[0][2] = drvui->b_mat[2][0] = 0.;
164 drvui->b_mat[1][2] = drvui->b_mat[2][1] = 0.;
165
166 #ifdef WIN32
167 drvui->mainWindow->icon ((char *) LoadIcon (fl_display, MAKEINTRESOURCE (IDI_ICON1)));
168 #else
169 fl_open_display ();
170 #if !defined(__APPLE__)
171 XpmCreatePixmapFromData (fl_display, DefaultRootWindow (fl_display), drawxtl_xpm,
172 &drvui->icon, &shapemask, NULL);
173 drvui->mainWindow->icon ((char *) drvui->icon);
174 #endif
175 #endif
176 Fl::args (argc, argv, i);
177
178 #ifdef FREEGLUT24
179 fgState.Initialised = 1; // convince freeglut 2.4 that we did call glutInit()
180 #endif
181
182 LoadConfig (1);
183 if (i < argc) {
184 if (strcmp (argv[i], "-h") && strcmp (argv[i], "-?")) {
185 strcpy (drvui->Cur_File, argv[i]); // input file specified on start line
186 if (!strchr (drvui->Cur_File, foldersymbol)) {
187 getcwd (drvui->Cur_Dir, 1023);
188 } else {
189 strcpy (drvui->Cur_Dir, drvui->Cur_File);
190 char *end = strrchr (drvui->Cur_Dir, foldersymbol);
191
192 end++;
193 *end = '\0';
194
195 // path may be relative to the cwd, go there to obtain the absolute path
196 chdir (drvui->Cur_Dir);
197 getcwd (drvui->Cur_Dir, 1023);
198
199 // remove path component from filename
200 char *start = strrchr (drvui->Cur_File, foldersymbol);
201
202 start++;
203 memmove (drvui->Cur_File, start, strlen (start) + 1);
204 }
205
206 if (strstr (drvui->Cur_File, ".cif")
207 && strlen (strstr (drvui->Cur_File, ".cif")) == 4) { // filename ends in .cif
208 char tmp_file[256], string[256], newfile[256];
209
210 FILE *newstr, *inp;
211
212 static int one = 1;
213
214 strcpy (newfile, drvui->Cur_File);
215 strcpy (tmp_file, drvui->Cur_File); // copy original cif filename
216 strcat (tmp_file, ".str"); // and add extension
217
218 newstr = fopen (tmp_file, "r");
219 if (!(inp = fopen (newfile, "r"))) {
220 sprintf (string, "The file you selected ('%s') cannot be read\n"
221 "Do you wish to continue?", newfile);
222 if (fl_choice (string, "No", "Yes", NULL)) {
223 inp = fopen (tmp_file, "w");
224 fclose (inp);
225 Edit_STR_cb (NULL, &one);
226 }
227 } else {
228 strcpy (drvui->Cur_File, tmp_file);
229 WriteConfig (); // update configuration file
230 drvui->CurFile->value (drvui->Cur_File); // update main screen widgets
231 drvui->CurDir->value (drvui->Cur_Dir);
232 newstr = fopen (drvui->Cur_File, "w");
233 fprintf (newstr, "titl imported\n");
234 Block_CIF = 0;
235 fprintf (newstr, "import cif %s\n", newfile);
236 drvui->auto_ellipse = 1;
237 fprintf (newstr, "box 0.02 Black\n");
238 fprintf (newstr, "background White\n");
239 fprintf (newstr, "view 0. 0. 0.\n");
240 fprintf (newstr, "pack -0.05 1.05 -0.05 1.05 -0.05 1.05\n");
241 fprintf (newstr, "end\n");
242 fclose (newstr);
243 fclose (inp);
244 }
245 }
246 strcpy (drvui->Cur_Root, drvui->Cur_File);
247 trim_string (drvui->Cur_Root, 256);
248 int j;
249
250 for (j = strlen (drvui->Cur_Root); j > 0; --j) {
251 if (drvui->Cur_Root[j] == '.') {
252 drvui->Cur_Root[j] = 0;
253 break;
254 }
255 }
256 }
257 }
258 WriteConfig ();
259 drvui->mainWindow->show (argc, argv);
260 return Fl::run ();
261 }
262
~CrystalView()263 CrystalView::~CrystalView ()
264 {
265 }
266
267 double
AngleInRange(double angle)268 AngleInRange (double angle)
269 {
270 // routine to return an angle in the range -180 to 180
271 if (angle > 180.0)
272 angle -= 180.0;
273 if (angle < -180.0)
274 angle += 180.0;
275 if (angle < 0.0) {
276 angle = int (100.0 * angle - 0.5) / 100.0;
277 } else {
278 angle = int (100.0 * angle + 0.5) / 100.0;
279 }
280 return angle;
281 }
282
283 void
Clean_Up_Files(void)284 Clean_Up_Files (void)
285 {
286 // delete the "frm", "save", "tmp" and "cns" files
287 int r;
288
289 char string[512], tmp[50];
290
291 if (!strlen (drvui->Cur_Root))
292 return;
293
294 for (r = 1; r <= drvui->max_frame; r++) { // delete the frm* files
295 strcpy (string, drvui->Cur_Root);
296 sprintf (tmp, ".frm%d", r);
297 strcat (string, tmp);
298 unlink (string);
299 }
300 strcpy (string, drvui->Cur_Root);
301 strcat (string, ".save");
302 unlink (string); // delete the "save" file
303 unlink (drvui->Cur_Temp); // delete the tmp file
304 unlink (drvui->Cur_Console); // delete the cns file
305 }
306
307 void
Clear_Last_Omit_cb(Fl_Button *,void *)308 Clear_Last_Omit_cb (Fl_Button *, void *)
309 {
310 if (Omit->nomits > 0) {
311 drvui->Str_File_Changed = 1;
312 --Omit->nomits;
313 if (!Omit->nomits) {
314 edtprm->ClearLastOmit->deactivate ();
315 edtprm->ClearOmit->deactivate ();
316 }
317 }
318 Update_Str (0); // update the 'str' file
319 Generate_Drawing (1); // regenerate the drawing
320 Fl::redraw (); // update the screen
321 }
322
CrystalView(int x,int y,int w,int h,const char * l)323 CrystalView::CrystalView (int x, int y, int w, int h, const char *l)
324 :
325 Tb_Window (x, y, w, h, l)
326 {
327 // CrystalView constructor - subclass of Tb_Window - use default constructor
328 }
329
330 void
Destroy_Open_Windows(void)331 Destroy_Open_Windows (void)
332 {
333 // call the destructor for all open windows and delete the database
334 if (arrows) {
335 arrows->ArrowWindow->~Fl_Window ();
336 delete (arrows->ArrowWindow);
337 delete (arrows->ArrowBuffer);
338 delete (arrows);
339 arrows = NULL;
340 }
341 if (Bonds) {
342 // delete(Bonds->Bond_Output_Buffer);
343 // delete(Bonds->BondBuffer);
344 Bonds->Bond_Edit_Window->~Fl_Window ();
345 delete (Bonds);
346 Bonds = NULL;
347 }
348 if (Configure) {
349 Configure->ConfigWindow->~Fl_Window ();
350 delete (Configure->ConfigWindow);
351 delete (Configure);
352 Configure = NULL;
353 }
354 if (MiscConfigure) {
355 MiscConfigure->MiscConfigWindow->~Fl_Window ();
356 delete (MiscConfigure->MiscConfigWindow);
357 delete (MiscConfigure);
358 MiscConfigure = NULL;
359 }
360 if (MSMSConfigure) {
361 MSMSConfigure->MSMSConfigWindow->~Fl_Window ();
362 delete (MSMSConfigure->MSMSConfigWindow);
363 delete (MSMSConfigure);
364 MSMSConfigure = NULL;
365 }
366 if (edtprm) {
367 edtprm->editWindow->~Fl_Window ();
368 delete (edtprm->editWindow);
369 delete (edtprm);
370 edtprm = NULL;
371 }
372 if (ellipsoids) {
373 ellipsoids->Ellips_Window->~Fl_Window ();
374 delete (ellipsoids->Ellips_Window);
375 delete (ellipsoids->ColorInputBuf);
376 delete (ellipsoids);
377 ellipsoids = NULL;
378 }
379 if (LonePairs) {
380 LonePairs->LonePair_Edit_Window->~Fl_Window ();
381 delete (LonePairs->LonePair_Edit_Window);
382 delete (LonePairs->LonePairBuffer);
383 delete (LonePairs);
384 LonePairs = NULL;
385 }
386 if (Maps) {
387 Maps->Maps_Edit_Window->~Fl_Window ();
388 delete (Maps->Maps_Edit_Window);
389 delete (Maps->MapsBuffer);
390 delete (Maps);
391 Maps = NULL;
392 }
393 if (Modparms) {
394 // we cannot simply call the destructor here as this menu contains spinners
395 Fl::delete_widget (Modparms->Mods_Edit_Window);
396 delete (Modparms);
397 Modparms = NULL;
398 }
399 if (MiscConfigure) {
400 MiscConfigure->MiscConfigWindow->~Fl_Window ();
401 delete (MiscConfigure->MiscConfigWindow);
402 delete (MiscConfigure);
403 MiscConfigure = NULL;
404 }
405 if (Polyhedra) {
406 Polyhedra->Polyhedra_Edit_Window->~Fl_Window ();
407 delete (Polyhedra->Polyhedra_Edit_Window);
408 delete (Polyhedra->PolyhedraBuffer);
409 delete (Polyhedra->Polyhedra_Output_Buffer);
410 delete (Polyhedra);
411 Polyhedra = NULL;
412 }
413 if (Slabs) {
414 Slabs->SlabWindow->~Fl_Window ();
415 delete (Slabs->SlabWindow);
416 delete (Slabs);
417 Slabs = NULL;
418 }
419 if (Spheres) {
420 Spheres->Sphere_Edit_Window->~Fl_Window ();
421 delete (Spheres->Sphere_Edit_Window);
422 if (Spheres->SphereBuffer) {
423 delete (Spheres->SphereBuffer);
424 Spheres->SphereBuffer = NULL;
425 }
426 delete (Spheres);
427 Spheres = NULL;
428 }
429 if (listwindow1) {
430 listwindow1->~Fl_Window ();
431 if (textbuf1) {
432 delete (textbuf1);
433 textbuf1 = NULL;
434 }
435 delete (listwindow1);
436 listwindow1 = NULL;
437 }
438 if (listwindow2) {
439 listwindow2->~Fl_Window ();
440 if (textbuf2) {
441 delete (textbuf2);
442 textbuf2 = NULL;
443 }
444 delete (listwindow2);
445 listwindow2 = NULL;
446 }
447 if (listwindow3) {
448 listwindow3->~Fl_Window ();
449 if (textbuf3) {
450 delete (textbuf3);
451 textbuf3 = NULL;
452 }
453 delete (listwindow3);
454 listwindow3 = NULL;
455 }
456 if (helpwindow) {
457 helpwindow->~Fl_Window ();
458 if (helpbuf) {
459 delete (helpbuf);
460 helpbuf = NULL;
461 }
462 delete (helpwindow);
463 helpwindow = NULL;
464 }
465 if (helpwindow1) {
466 helpwindow1->~Fl_Window ();
467 if (helpbuf1) {
468 delete (helpbuf1);
469 helpbuf1 = NULL;
470 }
471 delete (helpwindow1);
472 helpwindow1 = NULL;
473 }
474 if (helpwindow2) {
475 helpwindow2->~Fl_Window ();
476 delete (helpwindow2);
477 helpwindow2 = NULL;
478 }
479 if (helpwindow3) {
480 helpwindow3->~Fl_Window ();
481 delete (helpwindow3);
482 helpwindow3 = NULL;
483 }
484 if (helpwindow4) {
485 helpwindow4->~Fl_Window ();
486 delete (helpwindow4);
487 helpwindow4 = NULL;
488 }
489 if (helpwindow5) {
490 helpwindow5->~Fl_Window ();
491 delete (helpwindow5);
492 helpwindow5 = NULL;
493 }
494 if (helpwindow6) {
495 Fl::delete_widget (helpwindow6);
496 // helpwindow6->~Fl_Window();
497 // delete(helpwindow6);
498 helpwindow6 = NULL;
499 }
500 if (textwindow) {
501 textwindow->~Fl_Window ();
502 if (textbuf) {
503 delete (textbuf);
504 textbuf = NULL;
505 }
506 delete (textwindow);
507 textwindow = NULL;
508 }
509 drvui->destroy = 0;
510 }
511
512 void
draw(void)513 CrystalView::draw (void)
514 {
515 // routine to draw crystal object to GL Window
516 static int first_time = 1;
517
518 float cpx, cpy, cpz;
519
520 float m[16];
521 GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
522 GLfloat light_ambient[] = { AMBLEV, AMBLEV, AMBLEV, 1.0f };
523 GLfloat light_specular[] = { 0.1f, 0.1f, 0.1f, 1.0f };
524 GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
525 GLfloat mat_shininess[] = { 0.8f };
526 GLfloat light_position[] = { 0.0f, 1.0f, 1.0f, 0.0f };
527 GLfloat light_direction[] = { 0.0f, -1.0f, 0.0f };
528 float ratio = (float) w () / (float) h ();
529
530 if (!valid ()) {
531 glLoadIdentity ();
532 glViewport (0, 0, w (), h ());
533 glEnable (GL_DEPTH_TEST);
534 }
535 if (first_time) {
536 first_time = 0;
537 drvui->crystalDL = glGenLists (1);
538 drvui->frame_no = 1;
539 if (strncmp (drvui->LoadOnStartup, "yes", 3) == 0 || strlen (drvui->Cur_Root)) {
540 Process_Inp (2);
541 Generate_Drawing (0);
542 Rotq = XYZ_Rot_to_Q (Xrot, Yrot, Zrot);
543 if (drvui->max_frame > 1) {
544 Add_Frame_Main ();
545 Main_Frame_Combo_cb (NULL, NULL);
546 } else {
547 drvui->Frame_No->hide ();
548 }
549 }
550 }
551 glMatrixMode (GL_PROJECTION);
552
553 glLoadIdentity ();
554 if (M_cameras == 0) {
555 if (ratio <= 1.)
556 glOrtho (-gl_size, gl_size, -gl_size / ratio, gl_size / ratio, -10000.,
557 10000.);
558 else
559 glOrtho (-gl_size * ratio, gl_size * ratio, -gl_size, gl_size, -10000.,
560 10000.);
561 } else {
562 gluPerspective (17, ratio, 0.01, 1000.); // view angle, aspect,near/far clip
563 }
564 glMatrixMode (GL_MODELVIEW);
565 glLoadIdentity ();
566 cpx = (POV_Max[0] + POV_Min[0]) / 2.0f;
567 cpy = (POV_Max[1] + POV_Min[1]) / 2.0f;
568 cpz = (POV_Max[2] + POV_Min[2]) / 2.0f;
569 // glShadeModel (GL_SMOOTH);
570 glMaterialfv (GL_FRONT, GL_SPECULAR, mat_specular);
571 glMaterialfv (GL_FRONT, GL_SHININESS, mat_shininess);
572 glLightfv (GL_LIGHT0, GL_SPECULAR, light_specular);
573 glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse);
574 glLightfv (GL_LIGHT0, GL_AMBIENT, light_ambient);
575 glLightModeli (GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
576 glEnable (GL_LIGHTING);
577 glEnable (GL_LIGHT0);
578 glEnable (GL_COLOR_MATERIAL);
579 glColorMaterial (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
580 glEnable (GL_DEPTH_TEST);
581 glClearColor (drvui->glback[0], drvui->glback[1], drvui->glback[2], 0.0f);
582 glClear ((GLbitfield) (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
583 gluLookAt (cpx, cpy, Scale * .50, // camera position
584 cpx, cpy, -1.0, // camera lookat point
585 0.0f, 1.0f, 0.0f); // camera "up" vector
586 glColor3f (0.0f, 0.0f, 0.0f);
587 glLightfv (GL_LIGHT0, GL_POSITION, light_position);
588 glLightfv (GL_LIGHT0, GL_SPOT_DIRECTION, light_direction);
589 glPushMatrix ();
590 // glTranslatef (gl_pos_x, gl_pos_y, gl_pos_z);
591 Tb_Window::calculate (m); // convert quaternion to matrix
592
593 Yrot = -asin (m[2]) * RAD; // convert to equivalent rotations
594 double cosy = cos (Yrot / RAD);
595
596 if (fabs (cosy) > 1.0e-3) {
597 Xrot = atan2 (m[6] / cosy, m[10] / cosy) * RAD;
598 Zrot = atan2 (m[1] / cosy, m[0] / cosy) * RAD;
599 } else {
600 Zrot = 0.0;
601 Xrot = atan2 (-m[9], m[5]) * RAD;
602 }
603 char string[20];
604
605 sprintf (string, "%6.2f", Zrot); // load widgets on main screen
606 drvui->Z_Rot->value (string);
607 sprintf (string, "%6.2f", Yrot);
608 drvui->Y_Rot->value (string);
609 sprintf (string, "%6.2f", Xrot);
610 drvui->X_Rot->value (string);
611
612 // glRotatef ((float)Xrot, (float) 1., (float) 0., (float) 0.);
613 // glRotatef ((float)Yrot, (float) 0., (float) 1., (float) 0.);
614 // glRotatef ((float)Zrot, (float) 0., (float) 0., (float) 1.);
615 glMultMatrixf (m); // this line equivalent to 3 above
616 // glTranslatef (-cpx,-cpy,-cpz); //this can mess up initial positioning w.r.t POV
617 draw_cursor ();
618 glCallList (drvui->crystalDL);
619 int saved_frame_no = drvui->frame_no;
620
621 for (drvui->frame_no = 1; drvui->frame_no <= drvui->max_frame; drvui->frame_no++)
622 generate_gl_texts ();
623 if (ShowMapLegend)
624 MapLegend();
625 drvui->frame_no = saved_frame_no;
626 glGetIntegerv (GL_VIEWPORT, viewport); // save matrices for later
627 glGetDoublev (GL_MODELVIEW_MATRIX, modelMatrix);
628 glGetDoublev (GL_PROJECTION_MATRIX, projMatrix);
629 glPopMatrix ();
630 if (drvui->destroy) { // close windows that are no longer needed
631 if (drvui->destroy & LIST1) {
632 listwindow1->~Fl_Window ();
633 listwindow1 = NULL;
634 drvui->destroy &= !LIST1;
635 }
636 if (drvui->destroy & LIST2) {
637 listwindow2->~Fl_Window ();
638 listwindow2 = NULL;
639 if (textbuf2) {
640 delete (textbuf2);
641 textbuf2 = NULL;
642 }
643 drvui->destroy &= !LIST2;
644 }
645 if (drvui->destroy & LIST3) {
646 listwindow3->~Fl_Window ();
647 listwindow3 = NULL;
648 if (textbuf3) {
649 delete (textbuf3);
650 textbuf3 = NULL;
651 }
652 drvui->destroy &= !LIST3;
653 }
654 if (drvui->destroy & SPHERE) {
655 Spheres->Sphere_Edit_Window->~Fl_Window ();
656 Spheres->Sphere_Edit_Window = NULL;
657 if (Spheres->SphereBuffer) {
658 delete (Spheres->SphereBuffer);
659 Spheres->SphereBuffer = NULL;
660 }
661 if (Spheres->Sphere_Output_Buffer) {
662 delete (Spheres->Sphere_Output_Buffer);
663 Spheres->Sphere_Output_Buffer = NULL;
664 }
665 delete (Spheres);
666 Spheres = NULL;
667 drvui->destroy &= !SPHERE;
668 }
669 if (drvui->destroy & ELLIPSOID) {
670 ellipsoids->Ellips_Window->~Fl_Window ();
671 ellipsoids->Ellips_Window = NULL;
672 delete (ellipsoids->ColorInputBuf);
673 delete (ellipsoids);
674 ellipsoids = NULL;
675 drvui->destroy &= !ELLIPSOID;
676 }
677 if (drvui->destroy & LONEPAIR) {
678 LonePairs->LonePair_Edit_Window->~Fl_Window ();
679 delete (LonePairs->LonePairBuffer);
680 delete (LonePairs);
681 LonePairs = NULL;
682 drvui->destroy &= !LONEPAIR;
683 }
684 if (drvui->destroy & TEXT1) {
685 textwindow->~Fl_Window ();
686 textwindow = NULL;
687 delete (textbuf);
688 textbuf = NULL;
689 drvui->destroy &= !TEXT1;
690 }
691 }
692 if (drvui->origin1_flag)
693 drvui->Origin1_Msg->show ();
694 else
695 drvui->Origin1_Msg->hide ();
696 }
697
698 void
draw_overlay(void)699 CrystalView::draw_overlay (void)
700 {
701 static float cpx, cpy, cpz;
702
703 float m[16];
704
705
706 if (slabmode < 2)
707 return;
708
709 float ratio = 1.0f * (float) w () / (float) h ();
710
711 glPushMatrix ();
712 glMatrixMode (GL_PROJECTION);
713 glLoadIdentity ();
714 if (M_cameras == 0) {
715 if (ratio <= 1.)
716 glOrtho (-gl_size, gl_size, -gl_size / ratio, gl_size / ratio, -10000.,
717 10000.);
718 else
719 glOrtho (-gl_size * ratio, gl_size * ratio, -gl_size, gl_size, -10000.,
720 10000.);
721 } else {
722 gluPerspective (17, ratio, 0.01, 1000.);
723 }
724
725 glMatrixMode (GL_MODELVIEW);
726 Tb_Window::calculate (m);
727
728 glMultMatrixf (m);
729 cpx = (POV_Max[0] + POV_Min[0]) / 2.0f;
730 cpy = (POV_Max[1] + POV_Min[1]) / 2.0f;
731 cpz = (POV_Max[2] + POV_Min[2]) / 2.0f;
732 glTranslatef (-cpx, -cpy, -cpz);
733
734 show_slab_ovl ();
735 glPopMatrix ();
736 }
737
738 void
Error_Box(const char * message)739 Error_Box (const char *message)
740 {
741 int yy = 100;
742
743 // routine for Error message windows
744
745 if (errorbox) {
746 errorbox->~Fl_Window ();
747 // Fl::delete_widget(errorbox);
748 errorbox = NULL;
749 }
750
751 drvui->msgbuffer= (char*) realloc(drvui->msgbuffer,(strlen(drvui->msgbuffer)+strlen(message)+2)*sizeof(char));
752 strcat(drvui->msgbuffer,message);
753 if (strstr (message, "\n"))
754 yy = 140;
755 errorbox = new Fl_Window (200, 180, 500, yy, "Error");
756 errorbox->begin ();
757 errorbox->callback ((Fl_Callback *) Error_Box_cb);
758
759 int y = 20;
760
761 Fl_Multiline_Output *box = new Fl_Multiline_Output (0, 10, 500, yy - 50, "");
762
763 box->box (FL_NO_BOX);
764 box->labelsize (14);
765 box->labelcolor ((Fl_Color) 1);
766 box->color (FL_GRAY);
767 box->cursor_color (FL_BACKGROUND_COLOR);
768 box->value (drvui->msgbuffer);
769 y += 15 + yy - 80;
770 Fl_Button *o = new Fl_Button (210, y, 80, 30, "Close");
771
772 o->callback ((Fl_Callback *) Error_Box_cb);
773 #if !defined (WIN32) && !defined (__APPLE__)
774 errorbox->icon ((char *) drvui->icon);
775 #endif
776 errorbox->end ();
777 errorbox->show ();
778 strcat(drvui->msgbuffer,"\n");
779 // errorbox->set_modal();
780 }
781
782 void
Error_Box_cb(Fl_Widget * w,void *)783 Error_Box_cb (Fl_Widget * w, void *)
784 {
785 // callback to hide error message window
786 w->window ()->hide ();
787 free (drvui->msgbuffer);
788 drvui->msgbuffer = (char*) zalloc (sizeof (char));
789 }
790
791 void
Exit_cb(void)792 Exit_cb (void)
793 {
794 // callback routine when exit menuitem is clicked or when main window is closed
795 int r;
796
797 if (strlen (drvui->Cur_File) && drvui->Str_File_Changed) {
798 r = fl_choice ("The current str file has not been saved.\n"
799 "What action should be taken?", "Cancel", "Save", "Discard");
800 if (!r)
801 return;
802 if (r == 1)
803 Update_Str (1);
804 }
805 WriteConfig ();
806 Clean_Up_Files (); // delete all the temporary files
807 Destroy_Open_Windows ();
808 if (FourierPt)
809 free (FourierPt);
810 free (crystal);
811 delete (Omit);
812 if (s_vert)
813 free (s_vert);
814 if (o_vert)
815 free (o_vert);
816 if (o_vert_nm)
817 free (o_vert_nm);
818 if (drvui->vert_occ)
819 free (drvui->vert_occ);
820 if (xypos)
821 free (xypos);
822 if (xypos_nm)
823 free (xypos_nm);
824 if (vert_sym_no)
825 free (vert_sym_no);
826 if (vert_sym_nos)
827 free (vert_sym_nos);
828 if (vertex_list)
829 free (vertex_list);
830 if (poly_list)
831 free (poly_list);
832 if (drvui->atom_no)
833 free (drvui->atom_no);
834 if (drvui->atom_so)
835 free (drvui->atom_so);
836 if (drvui->orig_atom_no)
837 free (drvui->orig_atom_no);
838 if (drvui->modulate_x)
839 free (drvui->modulate_x);
840 if (drvui->modulate_3x)
841 free (drvui->modulate_3x);
842 if (drvui->modulate_3t)
843 free (drvui->modulate_3t);
844 if (drvui->atoms)
845 free (drvui->atoms);
846 if (drvui->ellips)
847 free (drvui->ellips);
848 if (drvui->fourier)
849 free (drvui->fourier);
850 if (drvui->labels)
851 free (drvui->labels);
852 if (drvui->bplanes)
853 free (drvui->bplanes);
854 if (drvui->planes)
855 free (drvui->planes);
856 if (drvui->polyhedra)
857 free (drvui->polyhedra);
858 if (drvui->polyedges)
859 free (drvui->polyedges);
860 if (drvui->spheres)
861 free (drvui->spheres);
862 if (drvui->atprops)
863 free (drvui->atprops);
864 if (drvui->modulate_gbl)
865 free (drvui->modulate_gbl);
866 if (drvui->frames)
867 free (drvui->frames);
868 if (drvui->nsurf > 1) {
869 for (r = 1; r < drvui->nsurf; r++) {
870 free (drvui->surfx[r]);
871 free (drvui->surfy[r]);
872 free (drvui->surfz[r]);
873 }
874 }
875 if (drvui->voidmap) {
876 for (int j = 0; j < drvui->voidgrid[0]; j++) {
877 for (int k = 0; k < drvui->voidgrid[1]; k++)
878 free (drvui->voidmap[j][k]);
879 free (drvui->voidmap[j]);
880 }
881 free (drvui->voidmap);
882 }
883 if (!strncmp (drvui->LoadOnStartup, "maybe", 5)) {
884 strcpy (drvui->LoadOnStartup, "yes");
885 WriteConfig ();
886 }
887 Fl::delete_widget (drvui->mainWindow);
888 free (drvui->table);
889 free (drvui->arrows);
890 free (drvui->cones);
891 free (drvui->bonds);
892 free (drvui->msgbuffer);
893 delete (drvui);
894 exit (0);
895 }
896
897 int
Get_Unique_Atoms(char atoms[100][5],int Frame_No)898 Get_Unique_Atoms (char atoms[100][5], int Frame_No)
899 {
900 // routine to return the unique atom names in current frame
901 int j;
902
903 int mlist = 0;
904
905 char atom1[5];
906
907 FILE *aout;
908
909 char string[256];
910
911 strcpy (string, drvui->Cur_Root);
912 strcat (string, ".frm");
913 sprintf (atom1, "%d", Frame_No);
914 strcat (string, atom1);
915 if (!(aout = fopen (string, "r"))) {
916 Error_Box ("Unable to open frm file.");
917 return 0;
918 }
919 strcpy (string, "");
920 while (!feof (aout)) {
921 fgets (string, 100, aout);
922 memset (atom1, 0, 5);
923 if (strlen (string) < 4)
924 break;
925 (void) sscanf (string, "%s", atom1);
926 atom1[4] = 0;
927 for (j = 3; j >= 0; --j) {
928 if (atom1[j] == ' ')
929 atom1[j] = 0;
930 }
931 strncpy (atoms[mlist++], atom1, 5); // add new one to end of list
932
933 for (j = 0; j < mlist - 1; j++) { // if not unique, truncate list
934 if (!strncmp (atoms[j], atom1, 4))
935 --mlist;
936 }
937 }
938 for (j = 0; j < mlist - 1; j++) {
939 int k;
940
941 for (k = j + 1; k < mlist; k++) { // sort atom names
942 if (strncmp (atoms[k], atoms[j], 4) < 0) {
943 strncpy (atom1, atoms[j], 4);
944 strncpy (atoms[j], atoms[k], 4);
945 strncpy (atoms[k], atom1, 4);
946 }
947 }
948 }
949 fclose (aout);
950 return mlist;
951 }
952
953 void
ImportDataFile_cb(Fl_Widget *,void * arg)954 ImportDataFile_cb (Fl_Widget *, void *arg)
955 {
956 // Callback routine to import a structure file
957 int r;
958
959 int i;
960
961 FILE *inp;
962
963 FILE *newstr;
964
965 static int one = 1;
966
967 const char *phase;
968
969 char string[2048];
970
971 char tmp_dir[1024];
972
973 char tmp_file[1024];
974
975 char newfile2[1024];
976
977 char Input_string[256];
978 char string0[] = { "Select CIF Data File" };
979 char string1[] = { "Select FDAT Data File" };
980 char string2[] = { "Select GSAS Data File" };
981 char string3[] = { "Select SCHAKAL Data File" };
982 char string4[] = { "Select SHELX Data File" };
983 char string5[] = { "Select WIEN2k Data File" };
984 char string6[] = { "Select DISCUS Data File" };
985 char string7[] = { "Select FULLPROF Data File" };
986 char string8[] = { "Select EXCITING Data File" };
987
988 switch ((long) arg) {
989 case 0:
990 strcpy (Input_string, string0);
991 break;
992 case 1:
993 strcpy (Input_string, string1);
994 break;
995 case 2:
996 strcpy (Input_string, string2);
997 break;
998 case 3:
999 strcpy (Input_string, string3);
1000 break;
1001 case 4:
1002 strcpy (Input_string, string4);
1003 break;
1004 case 5:
1005 strcpy (Input_string, string5);
1006 break;
1007 case 6:
1008 strcpy (Input_string, string6);
1009 break;
1010 case 7:
1011 strcpy (Input_string, string7);
1012 break;
1013 case 8:
1014 strcpy (Input_string, string8);
1015 break;
1016 }
1017 if (strlen (drvui->Cur_File) && drvui->Str_File_Changed) {
1018 r = fl_choice ("The current str file has not been saved.\n"
1019 "What action should be taken?", "Cancel", "Save", "Discard");
1020 if (!r)
1021 return;
1022 if (r == 1)
1023 Update_Str (1);
1024 }
1025 #if defined(WIN32)
1026 char drive[_MAX_DRIVE];
1027
1028 char dir[_MAX_DIR];
1029
1030 char fname[_MAX_FNAME];
1031
1032 char ext[_MAX_EXT];
1033
1034 const char *newfile = flu_file_chooser (Input_string, "*", drvui->Cur_File);
1035
1036 if (newfile) {
1037 _splitpath (newfile, drive, dir, fname, ext); //Windows code
1038 strcpy (tmp_dir, drive); // Drive letter
1039 strcat (tmp_dir, dir); // and directory
1040 strcpy (tmp_file, fname); // copy file name
1041 strcat (tmp_file, ".str"); // and add extension
1042 #else
1043 int k = 0;
1044
1045 const char *newfile = fl_file_chooser (Input_string, "*", drvui->Cur_File);
1046
1047 if (newfile) {
1048 strcpy (tmp_file, newfile);
1049 strcpy (tmp_dir, newfile);
1050 for (i = strlen (tmp_dir); i > 0; --i) { // Find final / in file name
1051 if (tmp_dir[i - 1] == '/') {
1052 tmp_dir[i] = 0;
1053 break;
1054 }
1055 }
1056 for (i = strlen (tmp_dir); newfile[i] != 0; i++) {
1057 tmp_file[k++] = newfile[i]; // copy file name to tmp_file
1058 }
1059 tmp_file[k] = 0;
1060 strcat (tmp_file, ".str");
1061 #endif
1062 chdir (tmp_dir); // switch to that directory
1063 newstr = fopen (tmp_file, "r");
1064 if (newstr) {
1065 snprintf (string, 2048,
1066 "The implied output file ('%s') will be overwritten.\n"
1067 "Do you wish to continue?", tmp_file);
1068 fclose (newstr);
1069 if (!fl_choice (string, "No", "Yes", NULL)) {
1070 chdir (drvui->Cur_Dir); // restore the original directory
1071 return;
1072 }
1073 }
1074 if (!(inp = fopen (newfile, "r"))) {
1075 snprintf (string, 2048, "The file you selected ('%s') cannot be read\n"
1076 "Do you wish to continue?", newfile);
1077 if (fl_choice (string, "No", "Yes", NULL)) {
1078 inp = fopen (tmp_file, "w");
1079 fclose (inp);
1080 Edit_STR_cb (NULL, &one);
1081 }
1082 } else {
1083 drvui->Str_File_Changed = 0;
1084 Clean_Up_Files (); // delete the temporary files,
1085 Destroy_Open_Windows (); // input dialogs and maps
1086 if (FourierPt) { // associated with the previous
1087 free (FourierPt); // structure
1088 FourierPt = NULL;
1089 }
1090 if (drvui->nsurf > 1) {
1091 for (i = 1; i < drvui->nsurf; i++) {
1092 free (drvui->surfx[i]);
1093 free (drvui->surfy[i]);
1094 free (drvui->surfz[i]);
1095 drvui->surfx[i] = NULL;
1096 drvui->surfy[i] = NULL;
1097 drvui->surfz[i] = NULL;
1098 }
1099 }
1100 strcpy (drvui->Cur_File, tmp_file);
1101 strcpy (drvui->Cur_Dir, tmp_dir);
1102 WriteConfig (); // update configuration file
1103 drvui->CurFile->value (drvui->Cur_File); // update main screen widgets
1104 drvui->CurDir->value (drvui->Cur_Dir);
1105 newstr = fopen (drvui->Cur_File, "w");
1106 if (!newstr) {
1107 snprintf (string, 256,
1108 "The implied output file ('%s') could not be created.",
1109 drvui->Cur_File);
1110 Error_Box (string);
1111 char *newfile =
1112 fl_file_chooser ("Please choose a new location in a writable directory", "*.str",
1113 drvui->Cur_File);
1114 if (!newfile || !(newstr=fopen(newfile,"w"))) {
1115 fclose (inp);
1116 return;
1117 } else {
1118 strcpy(drvui->Cur_File,newfile);
1119 strcpy(drvui->Cur_Dir,newfile);
1120 for (i = strlen (drvui->Cur_Dir); i > 0; --i) { // Find final / in file name
1121 if (drvui->Cur_Dir[i - 1] == '/') {
1122 drvui->Cur_Dir[i] = 0;
1123 break;
1124 }
1125 }
1126 WriteConfig (); // update configuration file
1127 drvui->CurFile->value (drvui->Cur_File); // update main screen widgets
1128 drvui->CurDir->value (drvui->Cur_Dir);
1129 }
1130 }
1131 fprintf (newstr, "titl imported\n");
1132
1133 if (strlen (newfile) > 80) {
1134 // remove path component from filename if the full name plus import instruction
1135 // would exceed our maximum input line length of 100 bytes
1136 const char *start = strrchr (newfile, '/');
1137
1138 if (!start) {
1139 start = strrchr (newfile, '\\'); // look for the other Windows folder marker
1140 if (!start) {
1141 Error_Box
1142 ("Unable to find folder/directory markers in file string\n"
1143 "Is your input file name really longer than 80 characters?\n"
1144 "If so, please rename it.");
1145 fclose (inp);
1146 fclose (newstr);
1147 return;
1148 }
1149 }
1150 start++;
1151 memmove (newfile2, start, strlen (start) + 1);
1152 if (strlen (newfile2) > 80) {
1153 Error_Box
1154 ("Your file name is longer than 80 characters. Please rename it.");
1155 fclose (inp);
1156 fclose (newstr);
1157 return;
1158 }
1159 } else {
1160 strcpy (newfile2, newfile);
1161 }
1162
1163 switch ((long) arg) {
1164 case 0: // CIF file
1165 Block_CIF = 0;
1166 // fprintf (newstr, "import cif %s\n", newfile2);
1167 fprintf (newstr, "inline cif\n");
1168 while (!feof (inp)) {
1169 fgets (string, 133, inp);
1170 fprintf (newstr, "%s", string);
1171 }
1172 fprintf (newstr, "# End of data for %s\n", newfile2);
1173 drvui->auto_ellipse =
1174 fl_choice ("Should ellipsoids be displayed automatically?", "No",
1175 "Yes", NULL);
1176 break;
1177 case 1: // FDAT file
1178 fprintf (newstr, "import fdat %s\n", newfile2);
1179 break;
1180 case 2: // GSAS file
1181 phase = fl_input ("Enter GSAS phase number:", "1");
1182 if (!phase)
1183 fprintf (newstr, "import gsas %s 1\n", newfile2);
1184 else
1185 fprintf (newstr, "import gsas %s %s\n", newfile2, phase);
1186 break;
1187 case 3: // SCHAKAL file
1188 fprintf (newstr, "import schakal %s\n", newfile2);
1189 break;
1190 case 4: // process SHELX file
1191 drvui->auto_ellipse =
1192 fl_choice ("Should ellipsoids be displayed automatically?", "No",
1193 "Yes", NULL);
1194 fprintf (newstr, "inline shelx\n");
1195 while (!feof (inp)) {
1196 fgets (string, 133, inp);
1197 fprintf (newstr, "%s", string);
1198 if (!strncmp (string, "HKLF", 4) || !strncmp (string, "hklf", 4)
1199 || !strncmp (string, "END", 3) || !strncmp (string, "end", 3))
1200 break;
1201 }
1202 if (drvui->autolabel == 1)
1203 drvui->autolabel = 2;
1204 break;
1205 case 5: // WIEN file
1206 fprintf (newstr, "import wien2k %s\n", newfile2);
1207 break;
1208 case 6: // DISCUS file
1209 fprintf (newstr, "import discus %s\n", newfile2);
1210 break;
1211 case 7: // FULLPROF file
1212 phase = fl_input ("Enter FULLPROF phase number:", "1");
1213 if (!phase)
1214 fprintf (newstr, "import pcr %s 1\n", newfile2);
1215 else
1216 fprintf (newstr, "import pcr %s %s\n", newfile2, phase);
1217 break;
1218 case 8: // Exciting file
1219 fprintf (newstr, "import exciting %s\n", newfile2);
1220 break;
1221 }
1222 fprintf (newstr, "box 0.02 Black\n");
1223 fprintf (newstr, "background White\n");
1224 fprintf (newstr, "view 0. 0. 0.\n");
1225 fprintf (newstr, "pack -0.05 1.05 -0.05 1.05 -0.05 1.05\n");
1226 fprintf (newstr, "end\n");
1227 fclose (newstr);
1228 fclose (inp);
1229 }
1230 Process_Inp (2);
1231 Rotq = XYZ_Rot_to_Q (Xrot, Yrot, Zrot);
1232 Add_Frame_Main ();
1233 Generate_Drawing (0); // generate this structure
1234 Fl::redraw (); // and draw it
1235 }
1236 }
1237
1238 void
1239 Include_Cutouts_cb (void)
1240 {
1241 // callback routine when Use_Cutouts checkbox is changed
1242 char string[128];
1243
1244 drvui->Str_File_Changed = 1;
1245 if (ellipsoids->Use_Cutouts->value ()) {
1246 ellipsoids->Cutout_Color->activate ();
1247 drvui->El_Cutout = 1;
1248 strcpy (string, ellipsoids->Cutout_Color->value ());
1249 if (!strlen (string))
1250 strcpy (string, (char *) "Gray20");
1251 ellipsoids->Cutout_Color->value (string);
1252 } else {
1253 drvui->El_Cutout = 0;
1254 ellipsoids->Cutout_Color->deactivate ();
1255 }
1256 }
1257
1258 void
1259 Load_Bond_Data (const char *atom, char table[20480])
1260 {
1261 // get sorted bond data for 'atom' from out file into character array table
1262 FILE *flin;
1263
1264 int i;
1265
1266 float f1, f2, f3, d;
1267
1268 char filename[256];
1269
1270 char string[100];
1271
1272 char string1[20], string2[40], string3[20];
1273
1274 char atom1[5];
1275
1276 int nfound = 0;
1277
1278 char atoms[1000][5];
1279
1280 float d_list[1000];
1281
1282 memset (string1, 0, 20);
1283 memset (string2, 0, 20);
1284 memset (string3, 0, 20);
1285 strcpy (filename, drvui->Cur_Root); // generate name of '.out' file
1286 strcat (filename, ".out");
1287 if (!(flin = fopen (filename, "r"))) {
1288 strcpy (table, "Generated Bond Table\n not available!");
1289 return;
1290 }
1291
1292 table[0] = 0;
1293 strcpy (string, " ");
1294 while (strncmp (string, " Bond Distance", 14)) { // find bond-distance table
1295 if (!fgets (string, 100, flin)) {
1296 strcpy (table, "Generated Bond Table\n not available!");
1297 fclose (flin);
1298 return;
1299 }
1300 }
1301 while (strncmp (string, "End of File.", 12) && strncmp (string, " doing frame", 12)) { // bond-distances over when end of file is reached
1302 int j;
1303
1304 if (!fgets (string, 100, flin)) {
1305 strcpy (table, "Generated Bond Table\n not available!");
1306 fclose (flin);
1307 return;
1308 }
1309 sscanf (string, "%s %s %s", string1, string2, string3);
1310 if ((!strncmp (string1, "Distances", 9))
1311 && (!strncmp (string3, atom, strlen (string3)))) {
1312 if (!fgets (string, 100, flin)) {
1313 if (!strlen (table)) {
1314 strcpy (table, "Generated Bond Table\n not available!");
1315 }
1316 fclose (flin);
1317 return;
1318 }
1319 if (!fgets (string, 100, flin)) {
1320 if (!strlen (table)) {
1321 strcpy (table, "Generated Bond Table\n not available!");
1322 }
1323 fclose (flin);
1324 return;
1325 }
1326 while (strlen (string) > 10 && nfound < 1000) {
1327 sscanf (string, "%s %d %s %f %f %f %f", string1, &j, string2, &f1, &f2,
1328 &f3, &d);
1329 strncpy (atoms[nfound], string1, 4);
1330 atoms[nfound][4] = 0;
1331 d_list[nfound++] = d;
1332 if (!fgets (string, 100, flin)) {
1333 if (!strlen (table)) {
1334 strcpy (table, "Generated Bond Table\n not available!");
1335 }
1336 fclose (flin);
1337 return;
1338 }
1339 }
1340 }
1341 }
1342 for (i = 0; i < nfound - 1; i++) {
1343 int k;
1344
1345 float tmp;
1346
1347 for (k = i + 1; k < nfound; k++) { // sort distances
1348 if (d_list[k] < d_list[i]) {
1349 tmp = d_list[i];
1350 d_list[i] = d_list[k];
1351 d_list[k] = tmp;
1352 strncpy (atom1, atoms[i], 4);
1353 strncpy (atoms[i], atoms[k], 4);
1354 strncpy (atoms[k], atom1, 4);
1355 }
1356 }
1357 }
1358 for (i = 0; i < nfound; i++) {
1359 sprintf (string, "%4s %8.3f\n", atoms[i], d_list[i]);
1360 strcat (table, string);
1361 }
1362
1363 if (!strlen (table)) {
1364 strcpy (table, "Generated Bond Table\n not available!");
1365 }
1366 fclose (flin);
1367 }
1368
1369 void
1370 LoadConfig (bool full_check)
1371 {
1372 // load configuration file. If full_check is true, load all data, else just saved screen size
1373 FILE *fname;
1374
1375 char filename[256];
1376
1377 char temp[256];
1378
1379 char stereo[256];
1380
1381 char autolabel[256];
1382
1383 #ifdef WIN32
1384 char profile[100];
1385
1386 OSVERSIONINFOEX osvi;
1387
1388 memset (&osvi, 0, sizeof (OSVERSIONINFOEX));
1389 osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
1390 GetVersionEx ((OSVERSIONINFO *) & osvi);
1391 if (osvi.dwMajorVersion == 4)
1392 strcpy (profile, "c:");
1393 else
1394 strcpy (profile, getenv ("USERPROFILE"));
1395 strcpy (filename, profile);
1396 strcat (filename, "\\");
1397 strcat (filename, Configure_file);
1398 #else
1399 fl_filename_expand (filename, Configure_file);
1400 #endif
1401 fname = fopen (filename, "r");
1402 if (!full_check) {
1403 if (fname) {
1404 int i;
1405
1406 for (i = 0; i < 15; i++)
1407 fgets (temp, 256, fname);
1408 if (strlen (temp) > 10) {
1409 int xpos, ypos, width, height;
1410
1411 if (sscanf (temp, "%d %d %d %d", &xpos, &ypos, &width, &height) == 4) {
1412 w_st_x = xpos;
1413 w_st_y = ypos;
1414 w_width = width;
1415 w_height = height;
1416 }
1417 }
1418 fclose (fname);
1419 }
1420 return;
1421 }
1422 if (!fname) {
1423 strcpy (drvui->Cur_Dir,
1424 "Unable to open Configuration - Please use 'Configure' menu items.");
1425 strcpy (drvui->Cur_File, "");
1426 strcpy (drvui->DefaultFinish, "finish 0.70 0.30 0.08 0.01");
1427 #ifdef WIN32 // Allow for different windows defaults
1428 strcpy (drvui->POV_Options, "+W600 +H600 +D +FC +A0.3 +P");
1429 // strcpy(drvui->POV_Include,"c:\\colors.inc"); // Is there a good default for windows?
1430 // strcpy(drvui->POV_Path,"povray.exe");
1431 #else
1432 strcpy (drvui->POV_Options, "+W600 +H600 +D +FC +A0.3 +P");
1433 #ifdef __APPLE__
1434 strcpy (drvui->POV_Include, "/sw/share/povray-3.5/include/colors.inc");
1435 strcpy (drvui->POV_Path, "/sw/bin/povray");
1436 #else
1437 strcpy (drvui->POV_Include, "/usr/local/share/povray-3.5/include/colors.inc");
1438 strcpy (drvui->POV_Path, "/usr/local/bin/povray");
1439 #endif
1440 #endif
1441 } else {
1442 fgets (drvui->DRAWxtl_Path, 256, fname);
1443 trim_string (drvui->DRAWxtl_Path, 256);
1444 fgets (drvui->POV_Path, 256, fname);
1445 trim_string (drvui->POV_Path, 256);
1446 fgets (drvui->VRML_Path, 256, fname);
1447 trim_string (drvui->VRML_Path, 256);
1448 fgets (drvui->EditName, 256, fname);
1449 trim_string (drvui->EditName, 256);
1450 fgets (drvui->FileViewName, 256, fname);
1451 trim_string (drvui->FileViewName, 256);
1452 fgets (drvui->POV_Options, 256, fname);
1453 trim_string (drvui->POV_Options, 256);
1454 fgets (drvui->Cur_File, 256, fname);
1455 trim_string (drvui->Cur_File, 256);
1456 fgets (drvui->Cur_Dir, 256, fname);
1457 trim_string (drvui->Cur_Dir, 256);
1458 fgets (drvui->POV_Include, 256, fname);
1459 trim_string (drvui->POV_Include, 256);
1460 fgets (drvui->LoadOnStartup, 10, fname);
1461 trim_string (drvui->LoadOnStartup, 10);
1462 fgets (drvui->DefaultFinish, 256, fname);
1463 trim_string (drvui->DefaultFinish, 256);
1464 fgets (temp, 256, fname); // skip over executable path
1465 fgets (autolabel, 256, fname);
1466 fgets (stereo, 256, fname);
1467 trim_string (stereo, 256);
1468 fgets (temp, 256, fname); // skip over window dimensions
1469 temp[0] = '\0';
1470 fgets (temp, 256, fname);
1471 trim_string (temp, 256);
1472 strcpy (drvui->MSMS_Path, "");
1473 fgets (drvui->MSMS_Path, 256, fname);
1474 trim_string (drvui->MSMS_Path, 256);
1475 strcpy (drvui->Mencoder_Path, "");
1476 fgets (drvui->Mencoder_Path, 256, fname);
1477 trim_string (drvui->Mencoder_Path, 256);
1478 strcpy (drvui->FFmpeg_Path, "");
1479 fgets (drvui->FFmpeg_Path, 256, fname);
1480 trim_string (drvui->FFmpeg_Path, 256);
1481 fclose (fname);
1482 }
1483 if (!strncmp (drvui->LoadOnStartup, "maybe", 5)) {
1484 Error_Box ("Previous attempt to load a structure on startup failed.\n"
1485 "LoadOnStartup cleared - Use Configure menu to reinstate.");
1486 strcpy (drvui->LoadOnStartup, "");
1487 } else if (!strlen (drvui->LoadOnStartup)) {
1488 strcpy (drvui->LoadOnStartup, "maybe");
1489 }
1490
1491 sscanf (drvui->DefaultFinish, "%*s %f %f %f %f",
1492 &drvui->ambient, &drvui->diffuse, &drvui->specular, &drvui->roughness);
1493
1494 if (!strncmp (autolabel, "autolabel", 9))
1495 drvui->autolabel = 1;
1496 else
1497 drvui->autolabel = 0;
1498 if (strlen (stereo) > 1) {
1499 sscanf (stereo, "%d %d %f", &drvui->Stereo, &drvui->cross_eyed,
1500 &drvui->stereo_base);
1501 }
1502 if (strlen (temp) > 10) {
1503 sscanf (temp, "povray %d vrml %d asy %d", &doPOV, &doVrml, &doAsy);
1504 } else {
1505 doPOV = doVrml = doAsy = 1;
1506 }
1507 WriteConfig ();
1508 }
1509
1510 void
1511 Max_Min_cb (void)
1512 {
1513 // callback routine to readout Max - Min spinners
1514 static int in_progress;
1515
1516 if (in_progress) {
1517 #ifndef WIN32
1518 fprintf (stderr, "calculation already in progress\n");
1519 #endif
1520 return;
1521 }
1522 in_progress = 1;
1523 int frame = atoi (drvui->Frame_No->value ());
1524
1525 if (!frame)
1526 frame = 1;
1527 Omit->nomits = 0;
1528 xmin = drvui->X_Min->value ();
1529 drvui->frames[frame].cryst_lim[0] = (float) xmin;
1530 xmax = drvui->X_Max->value ();
1531 drvui->frames[frame].cryst_lim[3] = (float) xmax;
1532 ymin = drvui->Y_Min->value ();
1533 drvui->frames[frame].cryst_lim[1] = (float) ymin;
1534 ymax = drvui->Y_Max->value ();
1535 drvui->frames[frame].cryst_lim[4] = (float) ymax;
1536 zmin = drvui->Z_Min->value ();
1537 drvui->frames[frame].cryst_lim[2] = (float) zmin;
1538 zmax = drvui->Z_Max->value ();
1539 drvui->frames[frame].cryst_lim[5] = (float) zmax;
1540 if (drvui->Use_Clipping->value () != 0) { // test check button
1541 clipflag = 1; // check button set
1542 // save spinner widget values
1543 drvui->frames[frame].clip_lim[0] =
1544 (float) max (drvui->X_Min_clip->value (), drvui->X_Min->value ());
1545 // MUST be within the min-max range
1546 drvui->frames[frame].clip_lim[0] =
1547 (float) min (drvui->frames[frame].clip_lim[0], drvui->X_Max->value ());
1548 drvui->frames[frame].clip_lim[1] =
1549 (float) max (drvui->Y_Min_clip->value (), drvui->Y_Min->value ());
1550 drvui->frames[frame].clip_lim[1] =
1551 (float) min (drvui->frames[frame].clip_lim[1], drvui->Y_Max->value ());
1552 drvui->frames[frame].clip_lim[2] =
1553 (float) max (drvui->Z_Min_clip->value (), drvui->Z_Min->value ());
1554 drvui->frames[frame].clip_lim[2] =
1555 (float) min (drvui->frames[frame].clip_lim[2], drvui->Z_Max->value ());
1556 drvui->frames[frame].clip_lim[3] =
1557 (float) min (drvui->X_Max_clip->value (), drvui->X_Max->value ());
1558 drvui->frames[frame].clip_lim[3] =
1559 (float) max (drvui->frames[frame].clip_lim[3], drvui->X_Min->value ());
1560 drvui->frames[frame].clip_lim[4] =
1561 (float) min (drvui->Y_Max_clip->value (), drvui->Y_Max->value ());
1562 drvui->frames[frame].clip_lim[4] =
1563 (float) max (drvui->frames[frame].clip_lim[4], drvui->Y_Min->value ());
1564 drvui->frames[frame].clip_lim[5] =
1565 (float) min (drvui->Z_Max_clip->value (), drvui->Z_Max->value ());
1566 drvui->frames[frame].clip_lim[5] =
1567 (float) max (drvui->frames[frame].clip_lim[5], drvui->Z_Min->value ());
1568 drvui->X_Min_clip->value (drvui->frames[frame].clip_lim[0]); // reload widgets with tested value
1569 drvui->Y_Min_clip->value (drvui->frames[frame].clip_lim[1]);
1570 drvui->Z_Min_clip->value (drvui->frames[frame].clip_lim[2]);
1571 drvui->X_Max_clip->value (drvui->frames[frame].clip_lim[3]);
1572 drvui->Y_Max_clip->value (drvui->frames[frame].clip_lim[4]);
1573 drvui->Z_Max_clip->value (drvui->frames[frame].clip_lim[5]);
1574
1575 drvui->X_Min_clip->activate (); // make widgets active
1576 drvui->X_Max_clip->activate ();
1577 drvui->Y_Min_clip->activate ();
1578 drvui->Y_Max_clip->activate ();
1579 drvui->Z_Min_clip->activate ();
1580 drvui->Z_Max_clip->activate ();
1581 } else {
1582 clipflag = 0; // check button off - clipping disabled
1583 drvui->X_Min_clip->deactivate (); // deactivate widgets
1584 drvui->X_Max_clip->deactivate ();
1585 drvui->Y_Min_clip->deactivate ();
1586 drvui->Y_Max_clip->deactivate ();
1587 drvui->Z_Min_clip->deactivate ();
1588 drvui->Z_Max_clip->deactivate ();
1589 #if 0
1590 drvui->X_Min_clip->value (drvui->X_Min->value ()); //load widgets with min or max value
1591 drvui->X_Max_clip->value (drvui->X_Max->value ());
1592 drvui->Y_Min_clip->value (drvui->Y_Min->value ());
1593 drvui->Y_Max_clip->value (drvui->Y_Max->value ());
1594 drvui->Z_Min_clip->value (drvui->Z_Min->value ());
1595 drvui->Z_Max_clip->value (drvui->Z_Max->value ());
1596 #endif
1597 }
1598 drvui->Str_File_Changed = 1;
1599 Update_Str (0);
1600 Generate_Drawing (0);
1601 Fl::redraw ();
1602 in_progress = 0;
1603 }
1604
1605 void
1606 Offset_cb (void)
1607 {
1608 // callback routine when Origin values are changed
1609 const char *string;
1610
1611 Omit->nomits = 0;
1612 drvui->Str_File_Changed = 1;
1613 string = drvui->Origin_X->value ();
1614 origin[0] = (float) atof (string);
1615 string = drvui->Origin_Y->value ();
1616 origin[1] = (float) atof (string);
1617 string = drvui->Origin_Z->value ();
1618 origin[2] = (float) atof (string);
1619 Update_Str (0);
1620 Generate_Drawing (0);
1621 Fl::redraw ();
1622 }
1623
1624 int
1625 pick_box (int x, int y, int w, int h)
1626 {
1627 GLint viewport[4];
1628
1629 int hits;
1630
1631 float cpx, cpy, cpz;
1632
1633 float m[16];
1634
1635 extern void show_slab (void);
1636
1637 float ratio = 1.0f * (float) w / (float) h;
1638
1639 memset (selectBuf, 0, BUFSIZE);
1640 glSelectBuffer (BUFSIZE, selectBuf);
1641 glRenderMode (GL_SELECT);
1642
1643 glMatrixMode (GL_PROJECTION);
1644 glPushMatrix ();
1645 glLoadIdentity ();
1646 glGetIntegerv (GL_VIEWPORT, viewport);
1647
1648 gluPickMatrix (x, viewport[3] - y, 1, 1, viewport);
1649
1650 if (M_cameras == 0) {
1651 if (ratio <= 1.)
1652 glOrtho (-gl_size, gl_size, -gl_size / ratio, gl_size / ratio, -10000.,
1653 10000.);
1654 else
1655 glOrtho (-gl_size * ratio, gl_size * ratio, -gl_size, gl_size, -10000.,
1656 10000.);
1657 } else {
1658 gluPerspective (17, ratio, 0.01, 1000.);
1659 }
1660
1661 glMatrixMode (GL_MODELVIEW);
1662
1663 glTranslatef (drvui->Trans[0], drvui->Trans[1], drvui->Trans[2]);
1664
1665 quaternion_to_rotmatrix (&Rotq, m);
1666
1667 glMultMatrixf (m);
1668
1669 cpx = (POV_Max[0] + POV_Min[0]) / 2.0f;
1670 cpy = (POV_Max[1] + POV_Min[1]) / 2.0f;
1671 cpz = (POV_Max[2] + POV_Min[2]) / 2.0f;
1672
1673 glTranslatef (-cpx, -cpy, -cpz);
1674
1675 glInitNames ();
1676 glPushName (~0);
1677
1678 show_slab_ovl ();
1679
1680 glMatrixMode (GL_PROJECTION);
1681 glMatrixMode (GL_MODELVIEW);
1682 glFlush ();
1683 glPopMatrix ();
1684 glFlush ();
1685 hits = glRenderMode (GL_RENDER);
1686 if (!hits)
1687 return (0);
1688 else
1689 hits = update_box (hits, selectBuf);
1690
1691 return (hits);
1692 }
1693
1694 void
1695 process_hits (int hits, GLuint buffer[])
1696 {
1697 int i;
1698
1699 GLuint names, *ptr, minZ, *ptrNames = 0, numberOfNames;
1700
1701 numberOfNames = 0;
1702
1703 ptr = (GLuint *) buffer;
1704 minZ = 0xffffffff;
1705 for (i = 0; i < hits; i++) {
1706 names = *ptr;
1707 ptr++;
1708 if (*ptr < minZ && *(ptr + 2) != (GLuint) - 1) {
1709 numberOfNames = names;
1710 minZ = *ptr;
1711 ptrNames = ptr + 2;
1712 }
1713 ptr += names + 2;
1714 }
1715 if (numberOfNames == 0)
1716 return;
1717
1718 ptr = ptrNames;
1719
1720 Omit->omit1[Omit->nomits] = *ptr;
1721 ptr++;
1722 Omit->omit2[Omit->nomits++] = *ptr;
1723
1724 if (Omit->nomits == 1 && edtprm) {
1725 edtprm->ClearLastOmit->activate ();
1726 edtprm->ClearOmit->activate ();
1727 }
1728 Generate_Drawing (1); /* regenerate drawing */
1729 }
1730
1731 void
1732 Process_Inp (int i)
1733 {
1734 // routine to process the DRAWxtl input file
1735 char string[60];
1736
1737 Init_DRAWxtl (); // initialize variables
1738 drvui->CurDir->value (drvui->Cur_Dir);
1739 if (strlen (drvui->Cur_File) < 2) {
1740 drvui->X_Min->value (-0.1);
1741 drvui->X_Max->value (1.1);
1742 drvui->Y_Min->value (-0.1);
1743 drvui->Y_Max->value (1.1);
1744 drvui->Z_Min->value (-0.1);
1745 drvui->Z_Max->value (1.1);
1746 xmin = -.1;
1747 xmax = 1.1;
1748 ymin = -.1;
1749 ymax = 1.1;
1750 zmin = -.1;
1751 zmax = 1.1;
1752 drvui->X_Origin = 0.5;
1753 drvui->Y_Origin = 0.5;
1754 drvui->Z_Origin = 0.5;
1755 drvui->X_Boxlim = 10.;
1756 drvui->Y_Boxlim = 10.;
1757 drvui->Z_Boxlim = 10.;
1758 drvui->Origin_X->value ("0.5");
1759 drvui->Origin_Y->value ("0.5");
1760 drvui->Origin_Z->value ("0.5");
1761 return;
1762 }
1763 memset (string, 0, 60);
1764 strcpy (string, drvui->Cur_File);
1765 if (string[strlen (string) - 1] == '_')
1766 string[strlen (string) - 1] = 0;
1767 drvui->CurFile->value (string);
1768
1769 _chdir (drvui->Cur_Dir);
1770
1771 drvui->fpin = fopen (drvui->Cur_File, "r"); // open 'str' file
1772 if (!drvui->fpin) {
1773 Error_Box ("Cannot open structure file !");
1774 strcpy (drvui->Cur_Temp, "");
1775 drvui->X_Min->value (-0.1);
1776 drvui->X_Max->value (1.1);
1777 drvui->Y_Min->value (-0.1);
1778 drvui->Y_Max->value (1.1);
1779 drvui->Z_Min->value (-0.1);
1780 drvui->Z_Max->value (1.1);
1781 xmin = -.1;
1782 xmax = 1.1;
1783 ymin = -.1;
1784 ymax = 1.1;
1785 zmin = -.1;
1786 zmax = 1.1;
1787 drvui->X_Origin = 0.5;
1788 drvui->Y_Origin = 0.5;
1789 drvui->Z_Origin = 0.5;
1790 drvui->X_Boxlim = 10.;
1791 drvui->Y_Boxlim = 10.;
1792 drvui->Z_Boxlim = 10.;
1793 drvui->Origin_X->value ("0.5");
1794 drvui->Origin_Y->value ("0.5");
1795 drvui->Origin_Z->value ("0.5");
1796
1797 return;
1798 } else {
1799 drvui->frame_no = 1;
1800 while (1) {
1801 read_inp (i); // read the 'str' file
1802 make_bmat (drvui->sys, drvui->lat_con, drvui->b_mat, drvui->ginv, drvui->rec_lat_con); /* create the lattice metric */
1803 rewind (drvui->fpin);
1804 drvui->frame_no++;
1805 if (drvui->frame_no > drvui->max_frame)
1806 break;
1807 }
1808 drvui->frame_no = drvui->max_frame;
1809 fclose (drvui->fpin); // close str file
1810 strcpy (drvui->Cur_Listing, drvui->Cur_File);
1811 trim_string (drvui->Cur_Listing, 256);
1812 int j;
1813
1814 for (j = strlen (drvui->Cur_Listing); j > 0; --j) {
1815 if (drvui->Cur_Listing[j] == '.') {
1816 drvui->Cur_Listing[j] = 0;
1817 break;
1818 }
1819 }
1820 strcpy (drvui->Cur_Root, drvui->Cur_Listing);
1821 strcpy (drvui->Cur_Console, drvui->Cur_Listing);
1822 strcpy (drvui->Cur_Temp, drvui->Cur_Listing);
1823 strcat (drvui->Cur_Listing, ".out");
1824 strcat (drvui->Cur_Console, ".cns");
1825 strcat (drvui->Cur_Temp, ".tmp");
1826 Fl_Text_Buffer *atextbuf = new Fl_Text_Buffer;
1827
1828 atextbuf->loadfile (drvui->Cur_File); // get text of str file
1829 if ( atextbuf->savefile (drvui->Cur_Temp)) { // output it to temp file
1830 Error_Box("Unable to create temporary str file - disk full or directory not writable");
1831
1832 char *newfile =
1833 fl_file_chooser ("Please save this file in a writable directory", "*.str",
1834 drvui->Cur_File);
1835 if (newfile) {
1836 atextbuf->savefile(newfile);
1837
1838 #if defined(WIN32)
1839 char drive[_MAX_DRIVE];
1840
1841 char dir[_MAX_DIR];
1842
1843 char fname[_MAX_FNAME];
1844
1845 char ext[_MAX_EXT];
1846
1847 _splitpath (newfile, drive, dir, fname, ext); //Windows code
1848 strcpy (drvui->Cur_Dir, drive); // Drive letter
1849 strcat (drvui->Cur_Dir, dir); // and directory
1850 strcpy (drvui->Cur_File, fname); // copy file name
1851 strcat (drvui->Cur_File, ext); // and add extension
1852 #else
1853 strcpy(drvui->Cur_File,newfile);
1854 strcpy (drvui->Cur_Dir,drvui->Cur_Listing);
1855 for (j = strlen (drvui->Cur_Dir); j > 0; --j) {
1856 if (drvui->Cur_Dir[j] == '/') {
1857 drvui->Cur_Dir[j] = 0;
1858 break;
1859 }
1860 }
1861 #endif
1862
1863 strcpy (drvui->Cur_Listing, drvui->Cur_File);
1864 trim_string (drvui->Cur_Listing, 256);
1865 int j;
1866
1867 for (j = strlen (drvui->Cur_Listing); j > 0; --j) {
1868 if (drvui->Cur_Listing[j] == '.') {
1869 drvui->Cur_Listing[j] = 0;
1870 break;
1871 }
1872 }
1873 strcpy (drvui->Cur_Root, drvui->Cur_Listing);
1874 strcpy (drvui->Cur_Console, drvui->Cur_Listing);
1875 strcpy (drvui->Cur_Temp, drvui->Cur_Listing);
1876 strcat (drvui->Cur_Listing, ".out");
1877 strcat (drvui->Cur_Console, ".cns");
1878 strcat (drvui->Cur_Temp, ".tmp");
1879 atextbuf->savefile(drvui->Cur_Temp);
1880 drvui->CurFile->value (drvui->Cur_File);
1881 drvui->CurDir->value (drvui->Cur_Dir);
1882 }
1883 }
1884 delete (atextbuf); // free the buffer
1885 }
1886 int frame = atoi (drvui->Frame_No->value ());
1887
1888 if (frame == 0)
1889 frame = 1;
1890 /* set limits of search regions */
1891 if (packflag == 0 && boxflag == 0) { /* neither given */
1892 drvui->frames[frame].cryst_lim[0] = origin[0] - 0.5f;
1893 drvui->frames[frame].cryst_lim[1] = origin[1] - 0.5f;
1894 drvui->frames[frame].cryst_lim[2] = origin[2] - 0.5f; /* set to generate one cell */
1895 drvui->frames[frame].cryst_lim[3] = origin[0] + 0.5f;
1896 drvui->frames[frame].cryst_lim[4] = origin[1] + 0.5f;
1897 drvui->frames[frame].cryst_lim[5] = origin[2] + 0.5f;
1898 packflag = 1;
1899 }
1900 xmin = drvui->frames[frame].cryst_lim[0]; // transfer DRAWxtl variables to widgets
1901 drvui->X_Min->value (xmin);
1902 xmax = drvui->frames[frame].cryst_lim[3];
1903 drvui->X_Max->value (xmax);
1904 ymin = drvui->frames[frame].cryst_lim[1];
1905 drvui->Y_Min->value (ymin);
1906 ymax = drvui->frames[frame].cryst_lim[4];
1907 drvui->Y_Max->value (ymax);
1908 zmin = drvui->frames[frame].cryst_lim[2];
1909 drvui->Z_Min->value (zmin);
1910 zmax = drvui->frames[frame].cryst_lim[5];
1911 drvui->Z_Max->value (zmax);
1912 if (clipflag == 1) { // clip active - load clip widgets
1913 drvui->Use_Clipping->value (1);
1914 drvui->X_Min_clip->value (drvui->frames[frame].clip_lim[0]);
1915 drvui->Y_Min_clip->value (drvui->frames[frame].clip_lim[1]);
1916 drvui->Z_Min_clip->value (drvui->frames[frame].clip_lim[2]);
1917 drvui->X_Max_clip->value (drvui->frames[frame].clip_lim[3]);
1918 drvui->Y_Max_clip->value (drvui->frames[frame].clip_lim[4]);
1919 drvui->Z_Max_clip->value (drvui->frames[frame].clip_lim[5]);
1920
1921 drvui->X_Min_clip->activate (); // activate them
1922 drvui->X_Max_clip->activate ();
1923 drvui->Y_Min_clip->activate ();
1924 drvui->Y_Max_clip->activate ();
1925 drvui->Z_Min_clip->activate ();
1926 drvui->Z_Max_clip->activate ();
1927 } else { // no clipping - load widgets with min and max values
1928 drvui->Use_Clipping->value (0); // and deactivate them
1929 drvui->X_Min_clip->deactivate ();
1930 drvui->X_Max_clip->deactivate ();
1931 drvui->Y_Min_clip->deactivate ();
1932 drvui->Y_Max_clip->deactivate ();
1933 drvui->Z_Min_clip->deactivate ();
1934 drvui->Z_Max_clip->deactivate ();
1935 drvui->X_Min_clip->value (drvui->X_Min->value ());
1936 drvui->X_Max_clip->value (drvui->X_Max->value ());
1937 drvui->Y_Min_clip->value (drvui->Y_Min->value ());
1938 drvui->Y_Max_clip->value (drvui->Y_Max->value ());
1939 drvui->Z_Min_clip->value (drvui->Z_Min->value ());
1940 drvui->Z_Max_clip->value (drvui->Z_Max->value ());
1941 }
1942 Xrot = xrot;
1943 sprintf (string, "%6.2f", Xrot);
1944 drvui->X_Rot->value (string);
1945 sprintf (string, "%6.2f", Yrot);
1946 Yrot = yrot;
1947 drvui->Y_Rot->value (string);
1948 Zrot = zrot;
1949 sprintf (string, "%6.2f", Zrot);
1950 drvui->Z_Rot->value (string);
1951 sprintf (string, "%6.2f", origin[0]);
1952 drvui->Origin_X->value (string);
1953 sprintf (string, "%6.2f", origin[1]);
1954 drvui->Origin_Y->value (string);
1955 sprintf (string, "%6.2f", origin[2]);
1956 drvui->Origin_Z->value (string);
1957 if (!Vrml2)
1958 drvui->Generate_VRML1->set (); // VRML1 checkbox is set
1959 else
1960 drvui->Generate_VRML1->clear ();
1961 if (!doVrml)
1962 drvui->Generate_VRML1->deactivate ();
1963 if (!doPOV)
1964 DRAWxtlViewUI::drawxtl_menu[39].deactivate ();
1965 if (!M_cameras)
1966 drvui->Orthographic_View->set (); // orthographic view checkbox set
1967 else
1968 drvui->Orthographic_View->clear ();
1969 if (Display_axes)
1970 drvui->Show_Vector_Triple->set (); // Show vector triple checkbox set
1971 else
1972 drvui->Show_Vector_Triple->clear ();
1973
1974 Update_Str (0);
1975 }
1976
1977 void
1978 Progress_Window (int type, const char *label, float max)
1979 {
1980
1981 // Routine to handle a progress bar. The first argument defines the type of call
1982 // type == -1, open a window. The second argument gives the label, 3rd the maximum.
1983 // type == -2, close the window. 2nd and 3rd arguments ignored.
1984 // type == 0, 3rd argument contains progress argument. 2nd ignored.
1985
1986 static Fl_Window *prog_window;
1987
1988 static Fl_Progress *prog_bar;
1989
1990 switch (type) {
1991
1992 case -1:
1993 prog_window = new Fl_Window (400, 300, 250, 50, "Please Wait");
1994 prog_window->begin ();
1995 prog_bar = new Fl_Progress (20, 10, 200, 30, label);
1996 prog_bar->minimum (0.0f);
1997 prog_bar->maximum (max);
1998 #if !defined (WIN32) && !defined (__APPLE__)
1999 prog_window->icon ((char *) drvui->icon);
2000 #endif
2001 prog_window->end ();
2002 prog_window->show ();
2003 break;
2004 case -2:
2005 prog_window->~Fl_Window ();
2006 delete(prog_window);
2007 break;
2008 default:
2009 prog_bar->value (max);
2010 }
2011 Fl::check ();
2012 }
2013
2014 void
2015 Restore_Working_Copy (void)
2016 {
2017 // restore working str file from saved version
2018 Fl_Text_Buffer *text = new Fl_Text_Buffer;
2019
2020 char savefile[256];
2021
2022 strcpy (savefile, drvui->Cur_Root);
2023 strcat (savefile, ".save");
2024 text->loadfile (savefile);
2025 text->savefile (drvui->Cur_Temp);
2026 delete (text);
2027 }
2028
2029 void
2030 Rotation_cb (void)
2031 {
2032 // callback routine to readout Rotation widgets
2033 Xrot = atof (drvui->X_Rot->value ());
2034 Xrot = AngleInRange (Xrot);
2035 xrot = (float) Xrot;
2036 Yrot = atof (drvui->Y_Rot->value ());
2037 Yrot = AngleInRange (Yrot);
2038 yrot = (float) Yrot;
2039 Zrot = atof (drvui->Z_Rot->value ());
2040 Zrot = AngleInRange (Zrot);
2041 zrot = (float) Zrot;
2042 Update_Str (0);
2043 Rotq = XYZ_Rot_to_Q (Xrot, Yrot, Zrot);
2044 Fl::redraw ();
2045 }
2046
2047 void
2048 Save_Current_cb (void)
2049 {
2050 // callback routine to save the current .str and .pov under a new name
2051 char oldpovfile[1024], newpovfile[1024];
2052
2053 char old_dir[1024], old_file[1024], new_file[1024];
2054
2055 int old_state;
2056
2057 #if defined(WIN32)
2058 char drive[_MAX_DRIVE];
2059
2060 char dir[_MAX_DIR];
2061
2062 char fname[_MAX_FNAME];
2063
2064 char ext[_MAX_EXT];
2065
2066 const char *newfile;
2067 #else
2068 int i;
2069
2070 char *newfile;
2071 #endif
2072
2073 if (!strlen (drvui->CurDir->value ())) { // Make sure rendering enabled
2074 Error_Box ("A Structure File must be selected first.");
2075 return;
2076 }
2077 strcpy (old_dir, drvui->Cur_Dir);
2078 strcpy (old_file, drvui->Cur_File);
2079 strcpy (oldpovfile, drvui->Cur_Root);
2080 strcat (oldpovfile, ".pov");
2081
2082 #if defined(WIN32)
2083 newfile = flu_file_chooser ("Select New Name for Current .STR/.POV Files",
2084 "*", drvui->Cur_Dir);
2085 if (newfile) {
2086 _splitpath (newfile, drive, dir, fname, ext); //Windows code
2087 strcpy (drvui->Cur_Dir, drive); // Drive letter
2088 strcat (drvui->Cur_Dir, dir); // and directory
2089 strcpy (drvui->Cur_File, fname); // copy file name
2090 } else
2091 return;
2092 #else
2093 newfile =
2094 fl_file_chooser ("Select New Name for Current .STR/.POV Files", "*",
2095 drvui->Cur_Dir);
2096 if (newfile) {
2097 strcpy (drvui->Cur_File, newfile);
2098 strcpy (drvui->Cur_Dir, newfile);
2099 for (i = strlen (drvui->Cur_Dir); i > 0; --i) { // Find final / in file name
2100 if (drvui->Cur_Dir[i - 1] == '/') {
2101 drvui->Cur_Dir[i] = 0;
2102 break;
2103 }
2104 }
2105 for (i = strlen (drvui->Cur_File); i > 0; --i) { // find final . in file name
2106 if (drvui->Cur_File[i - 1] == '.') {
2107 drvui->Cur_File[i - 1] = 0;
2108 break;
2109 }
2110 }
2111 } else
2112 return;
2113 #endif
2114
2115 strcpy (newpovfile, drvui->Cur_File);
2116 strcat (newpovfile, ".pov");
2117 rename (oldpovfile, newpovfile);
2118
2119 strcpy (new_file, drvui->Cur_File);
2120 strcat (new_file, ".str");
2121 strcpy (drvui->Cur_File, new_file);
2122 old_state = drvui->Str_File_Changed;
2123 Update_Str (1);
2124 drvui->Str_File_Changed = old_state;
2125 strcpy (drvui->Cur_File, old_file);
2126 strcpy (drvui->Cur_Dir, old_dir);
2127 }
2128
2129 void
2130 Save_Working_Copy (void)
2131 {
2132 // copy working version of str file into a "save" file
2133 Fl_Text_Buffer *text = new Fl_Text_Buffer;
2134
2135 char savefile[256];
2136
2137 strcpy (savefile, drvui->Cur_Root);
2138 strcat (savefile, ".save");
2139 text->loadfile (drvui->Cur_Temp);
2140 text->savefile (savefile);
2141 delete (text);
2142 }
2143
2144 void
2145 SelectDataFile_cb (void)
2146 {
2147 // Callback routine to select the data file
2148 int r, i;
2149
2150 FILE *inp;
2151
2152 static int one = 1;
2153
2154 if (strlen (drvui->Cur_File) && drvui->Str_File_Changed) {
2155 r = fl_choice ("The current str file has not been saved.\n"
2156 "What action should be taken?", "Cancel", "Save", "Discard");
2157 if (!r)
2158 return;
2159 if (r == 1)
2160 Update_Str (1);
2161 }
2162
2163 drvui->Str_File_Changed = 0;
2164
2165 #if defined(WIN32)
2166 char drive[_MAX_DRIVE];
2167
2168 char dir[_MAX_DIR];
2169
2170 char fname[_MAX_FNAME];
2171
2172 char ext[_MAX_EXT];
2173
2174 const char *newfile = flu_file_chooser ("Select Data/Experiment File",
2175 "*.str", drvui->Cur_File);
2176
2177 if (newfile) {
2178 _splitpath (newfile, drive, dir, fname, ext); //Windows code
2179 strcpy (drvui->Cur_Dir, drive); // Drive letter
2180 strcat (drvui->Cur_Dir, dir); // and directory
2181 strcpy (drvui->Cur_File, fname); // copy file name
2182 strcat (drvui->Cur_File, ext); // and add extension
2183 #else
2184 int k = 0;
2185
2186 char *newfile =
2187 fl_file_chooser ("Select Data/Experiment File", "*.str", drvui->Cur_File);
2188 if (newfile) {
2189 strcpy (drvui->Cur_File, newfile);
2190 strcpy (drvui->Cur_Dir, newfile);
2191 for (i = strlen (drvui->Cur_Dir); i > 0; --i) { // Find final / in file name
2192 if (drvui->Cur_Dir[i - 1] == '/') {
2193 drvui->Cur_Dir[i] = 0;
2194 break;
2195 }
2196 }
2197 for (i = strlen (drvui->Cur_Dir); newfile[i] != 0; i++) {
2198 drvui->Cur_File[k++] = newfile[i]; // copy file name to Cur_File
2199 }
2200 drvui->Cur_File[k] = 0;
2201 #endif
2202
2203 Clean_Up_Files (); // get rid of the temporary files
2204 Destroy_Open_Windows ();
2205
2206 if (FourierPt) {
2207 free (FourierPt);
2208 FourierPt = NULL;
2209 }
2210 for (i = 0; i < 4; i++) {
2211 cur_atom[i] = 0;
2212 strcpy (cur_name[i], "");
2213 }
2214 cur_show = 0;
2215 ReadFourMap = 0;
2216 strcpy (FourierFileName, "");
2217 drvui->Cursor_pos->value ("");
2218 drvui->labels_inited = 0; // make sure the labels get reinited
2219
2220 chdir (drvui->Cur_Dir); // switch to that directory
2221 WriteConfig (); // update configuration file
2222 drvui->CurFile->value (drvui->Cur_File); // update main screen widgets
2223 drvui->CurDir->value (drvui->Cur_Dir);
2224 if (!(inp = fopen (drvui->Cur_File, "r"))) {
2225 char string[256];
2226
2227 sprintf (string, "The file you selected ('%s') cannot be read\n"
2228 "Do you wish to continue?", drvui->Cur_File);
2229 if (fl_choice (string, "No", "Yes", NULL)) {
2230 inp = fopen (drvui->Cur_File, "w");
2231 fclose (inp);
2232 Edit_STR_cb (NULL, &one);
2233 }
2234 } else {
2235 fclose (inp);
2236 }
2237 vzero (drvui->Trans);
2238 drvui->origin1_flag = 0;
2239 gl_size = 0.0f;
2240 Process_Inp (2);
2241 Rotq = XYZ_Rot_to_Q (Xrot, Yrot, Zrot);
2242 Add_Frame_Main ();
2243 Fl::flush ();
2244 Generate_Drawing (0); // generate this structure
2245 Fl::redraw (); // and draw it
2246 }
2247 }
2248
2249 void
2250 show_slab_ovl (void)
2251 {
2252 glPushMatrix ();
2253
2254 glDisable (GL_LIGHTING);
2255 glLineWidth (3);
2256 glColor3f (0., 1., 0.);
2257 glBegin (GL_LINES);
2258
2259 glVertex3f (slabx1, slaby1, slabz1);
2260 glVertex3f (slabx2, slaby2, slabz2);
2261
2262 glVertex3f (slabx3, slaby3, slabz3);
2263 glVertex3f (slabx1, slaby1, slabz1);
2264
2265 glVertex3f (slabx3, slaby3, slabz3);
2266 glVertex3f (slabx2 + (slabx3 - slabx1), slaby2 + (slaby3 - slaby1),
2267 slabz2 + (slabz3 - slabz1));
2268
2269 glVertex3f (slabx2, slaby2, slabz2);
2270 glVertex3f (slabx2 + (slabx3 - slabx1), slaby2 + (slaby3 - slaby1),
2271 slabz2 + (slabz3 - slabz1));
2272
2273 glVertex3f (slabx1, slaby1, slabz1);
2274 glVertex3f (slabx4, slaby4, slabz4);
2275
2276
2277 glVertex3f (slabx3, slaby3, slabz3);
2278 glVertex3f (slabx3 + (slabx4 - slabx1), slaby3 + (slaby4 - slaby1),
2279 slabz3 + (slabz4 - slabz1));
2280
2281 glVertex3f (slabx4, slaby4, slabz4);
2282 glVertex3f (slabx3 + (slabx4 - slabx1), slaby3 + (slaby4 - slaby1),
2283 slabz3 + (slabz4 - slabz1));
2284
2285 glVertex3f (slabx2, slaby2, slabz2);
2286 glVertex3f (slabx2 + (slabx4 - slabx1), slaby2 + (slaby4 - slaby1),
2287 slabz2 + (slabz4 - slabz1));
2288
2289
2290 glVertex3f (slabx2 + (slabx4 - slabx1), slaby2 + (slaby4 - slaby1),
2291 slabz2 + (slabz4 - slabz1));
2292 glVertex3f (slabx4, slaby4, slabz4);
2293
2294 glVertex3f (slabx2 + (slabx4 - slabx1), slaby2 + (slaby4 - slaby1),
2295 slabz2 + (slabz4 - slabz1));
2296 glVertex3f (slabx2 + (slabx4 - slabx1) + slabx3 - slabx1,
2297 slaby2 + (slaby4 - slaby1) + slaby3 - slaby1,
2298 slabz2 + (slabz4 - slabz1) + slabz3 - slabz1);
2299
2300
2301 glVertex3f (slabx3 + (slabx4 - slabx1), slaby3 + (slaby4 - slaby1),
2302 slabz3 + (slabz4 - slabz1));
2303 glVertex3f (slabx2 + (slabx4 - slabx1) + slabx3 - slabx1,
2304 slaby2 + (slaby4 - slaby1) + slaby3 - slaby1,
2305 slabz2 + (slabz4 - slabz1) + slabz3 - slabz1);
2306
2307 glVertex3f (slabx2 + (slabx3 - slabx1), slaby2 + (slaby3 - slaby1),
2308 slabz2 + (slabz3 - slabz1));
2309 glVertex3f (slabx2 + (slabx4 - slabx1) + slabx3 - slabx1,
2310 slaby2 + (slaby4 - slaby1) + slaby3 - slaby1,
2311 slabz2 + (slabz4 - slabz1) + slabz3 - slabz1);
2312 glEnd ();
2313 glPushMatrix ();
2314 glLoadName (1);
2315 glTranslatef (slabx1, slaby1, slabz1);
2316 glutSolidCube (0.004 * Scale);
2317 glPopMatrix ();
2318 glPushMatrix ();
2319 glLoadName (2);
2320 glTranslatef (slabx2, slaby2, slabz2);
2321 glutSolidCube (0.004 * Scale);
2322 glPopMatrix ();
2323 glPushMatrix ();
2324 glLoadName (3);
2325 glTranslatef (slabx3, slaby3, slabz3);
2326 glutSolidCube (0.004 * Scale);
2327 glPopMatrix ();
2328 glPushMatrix ();
2329 glLoadName (4);
2330 glTranslatef (slabx4, slaby4, slabz4);
2331 glutSolidCube (0.004 * Scale);
2332 glPopMatrix ();
2333
2334 glEnable (GL_LIGHTING);
2335 glPopMatrix ();
2336 glLineWidth (1);
2337 }
2338
2339 void
2340 start_picking (int x, int y, int w, int h)
2341 {
2342 GLint viewport[4];
2343
2344 int hits;
2345
2346 float cpx, cpy, cpz;
2347
2348 float m[16];
2349
2350 int n, i;
2351
2352 float ratio = 1.0f * (float) w / (float) h;
2353
2354 memset (selectBuf, 0, BUFSIZE);
2355 glGetIntegerv (GL_VIEWPORT, viewport);
2356
2357 glPushMatrix ();
2358 glSelectBuffer (BUFSIZE, selectBuf);
2359 glRenderMode (GL_SELECT);
2360 glMatrixMode (GL_PROJECTION);
2361 glLoadIdentity ();
2362
2363 gluPickMatrix (x, viewport[3] - y, viewport[2] / 100, viewport[3] / 100, viewport);
2364
2365 if (M_cameras == 0) {
2366 if (w <= h)
2367 glOrtho (-gl_size, gl_size, -gl_size / ratio, gl_size / ratio, -10000.,
2368 10000.);
2369 else
2370 glOrtho (-gl_size * ratio, gl_size * ratio, -gl_size, gl_size, -10000.,
2371 10000.);
2372 } else {
2373 gluPerspective (17, ratio, 0.01, 1000.); // view angle, aspect,near/far clip
2374 }
2375 glMatrixMode (GL_MODELVIEW);
2376 glLoadIdentity ();
2377
2378 glInitNames ();
2379 glPushName (~0);
2380
2381 cpx = (POV_Max[0] + POV_Min[0]) / 2.0f;
2382 cpy = (POV_Max[1] + POV_Min[1]) / 2.0f;
2383 cpz = (POV_Max[2] + POV_Min[2]) / 2.0f;
2384
2385 gluLookAt (cpx, cpy, Scale * .50, // camera position
2386 cpx, cpy, -1.0, // camera lookat point
2387 0.0f, 1.0f, 0.0f); // camera "up" vector
2388
2389 glTranslatef (drvui->Trans[0], drvui->Trans[1], drvui->Trans[2]);
2390
2391 quaternion_to_rotmatrix (&Rotq, m);
2392
2393 glMultMatrixf (m);
2394
2395 glCallList (drvui->crystalDL);
2396
2397 glPopMatrix ();
2398
2399 hits = glRenderMode (GL_RENDER);
2400 glFlush ();
2401
2402 if (hits > 0) {
2403 process_hits (hits, selectBuf);
2404 } else {
2405 hits = pick_label (x, y, Fl::w (), Fl::h ());
2406 if (hits > 0 && hits <= drvui->nlabel) {
2407 if (hits != drvui->triple[0] && hits != drvui->triple[1]
2408 && hits != drvui->triple[2] && hits != drvui->triple[3]) {
2409 for (n = hits; n < drvui->nlabel; n++) { // remove label, but not a, b, c, or origin
2410 drvui->labels[n].label_fn = drvui->labels[n + 1].label_fn;
2411 strcpy (drvui->labels[n].label_label,
2412 drvui->labels[n + 1].label_label);
2413 for (i = 0; i < 3; i++)
2414 drvui->labels[n].label_x[i] = drvui->labels[n + 1].label_x[i];
2415 for (i = 0; i < 4; i++)
2416 if (drvui->triple[i] == n + 1)
2417 drvui->triple[i] = n;
2418 }
2419 drvui->nlabel--;
2420 }
2421 Update_Str (0);
2422 }
2423 }
2424
2425 Fl::redraw ();
2426
2427 }
2428
2429 int
2430 update_box (int hits, GLuint buffer[])
2431 {
2432 int i, j;
2433
2434 GLuint names, *ptr, minZ, *ptrNames = 0, numberOfNames;
2435
2436 numberOfNames = 0;
2437 j = 0;
2438
2439 ptr = (GLuint *) buffer;
2440 minZ = 0xffffffff;
2441 for (i = 0; i < hits; i++) {
2442 names = *ptr;
2443 ptr++;
2444 if (*ptr < minZ && *(ptr + 2) != (GLuint) - 1) {
2445 numberOfNames = names;
2446 minZ = *ptr;
2447 ptrNames = ptr + 2;
2448 }
2449 ptr += names + 2;
2450 }
2451
2452 if (numberOfNames == 0)
2453 return 0;
2454
2455 ptr = ptrNames;
2456 j = *ptr;
2457
2458 return (j);
2459 }
2460
2461 void
2462 Update_Objects (int Frame_No, FILE * out)
2463 {
2464 // Update the objects that belong to this frame
2465 int i;
2466
2467 unsigned int j;
2468
2469 char string[256];
2470
2471 // add bond lines
2472 if (drvui->nbond > 1) {
2473 for (i = 1; i < drvui->nbond; i++) {
2474 char atom1[5], atom2[5];
2475
2476 if (drvui->bonds[i].bond_fn == Frame_No) {
2477 strncpy (string, drvui->bonds[i].col_bond, 39);
2478 string[39] = 0;
2479 for (j = 0; j < strlen (string); j++)
2480 if (string[j] < ' ')
2481 string[j] = 0;
2482 strncpy (atom1, drvui->bonds[i].bond_l1, 4);
2483 strncpy (atom2, drvui->bonds[i].bond_l2, 4);
2484 atom1[4] = 0;
2485 atom2[4] = 0;
2486 if (drvui->bonds[i].bond_style == 0)
2487 fprintf (out, "bond %s %s %6.3f %6.3f %6.3f %s\n", atom1,
2488 atom2, drvui->bonds[i].bond_size, drvui->bonds[i].bond_min,
2489 drvui->bonds[i].bond_max, string);
2490 else {
2491 if (drvui->bonds[i].bond_style != 5)
2492 fprintf (out, "dash %d %s %s %6.3f %6.3f %6.3f %s\n",
2493 drvui->bonds[i].bond_style, atom1,
2494 atom2, drvui->bonds[i].bond_size,
2495 drvui->bonds[i].bond_min, drvui->bonds[i].bond_max,
2496 string);
2497 else
2498 fprintf (out, "dash %s %s %6.3f %6.3f %6.3f %s\n", atom1,
2499 atom2, drvui->bonds[i].bond_size,
2500 drvui->bonds[i].bond_min, drvui->bonds[i].bond_max,
2501 string);
2502 }
2503 }
2504 }
2505 }
2506 // add sphere lines
2507 if (drvui->nsphere > 1) {
2508 for (i = 1; i < drvui->nsphere; i++) {
2509 if (drvui->spheres[i].sphere_fn == Frame_No) {
2510 if (drvui->spheres[i].sphere_n == -1) {
2511 fprintf (out, "sphere %s %6.3f %s\n", drvui->spheres[i].sphere_l,
2512 drvui->spheres[i].sphere_size, drvui->spheres[i].sphere_col);
2513 } else {
2514 fprintf (out, "sphere %s %d %6.3f %s\n", drvui->spheres[i].sphere_l,
2515 drvui->spheres[i].sphere_n, drvui->spheres[i].sphere_size,
2516 drvui->spheres[i].sphere_col);
2517 }
2518 }
2519 }
2520 }
2521 // add magnetic arrow commands
2522 if (drvui->nmag > 0) {
2523 for (i = 0; i < drvui->nmag; i++) {
2524 if (drvui->arrows[i].arrow_fn == Frame_No) {
2525 fprintf (out,
2526 "arrow %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %s\n",
2527 drvui->arrows[i].mag_xp[0], drvui->arrows[i].mag_xp[1],
2528 drvui->arrows[i].mag_xp[2], drvui->arrows[i].mag_xc[0],
2529 drvui->arrows[i].mag_xc[1], drvui->arrows[i].mag_xc[2],
2530 drvui->arrows[i].arrow_length, drvui->arrows[i].arrow_diam,
2531 drvui->arrows[i].col_arrow);
2532 }
2533 }
2534 // add magnetic transformation command
2535 fprintf (out, "mag_trans %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f\n",
2536 drvui->mag_matrix[0][0], drvui->mag_matrix[0][1],
2537 drvui->mag_matrix[0][2], drvui->mag_matrix[1][0],
2538 drvui->mag_matrix[1][1], drvui->mag_matrix[1][2],
2539 drvui->mag_matrix[2][0], drvui->mag_matrix[2][1],
2540 drvui->mag_matrix[2][2]);
2541 }
2542 // add various types of polyhedra commands
2543 if (drvui->npoly > 1) {
2544 for (i = 1; i < drvui->npoly; i++) {
2545 if (drvui->polyhedra[i].poly_fn == Frame_No) {
2546 char atom1[5], atom2[5];
2547
2548 strncpy (string, drvui->polyhedra[i].poly_col, 39);
2549 string[39] = 0;
2550 for (j = 0; j < strlen (string); j++)
2551 if (string[j] < ' ')
2552 string[j] = 0;
2553 strncpy (atom2, drvui->polyhedra[i].poly_t, 4);
2554 strncpy (atom1, drvui->polyhedra[i].poly_l, 4);
2555 atom1[4] = 0;
2556 atom2[4] = 0;
2557 for (j = 0; j < strlen (atom1); j++)
2558 if (atom1[j] <= ' ')
2559 atom1[j] = 0;
2560 for (j = 0; j < strlen (atom2); j++)
2561 if (atom2[j] <= ' ')
2562 atom2[j] = 0;
2563 if (strlen (atom2)) { // polyvert command if 'to' atom
2564 fprintf (out, "polyvert %s %s %6.3f %s\n", atom1,
2565 atom2, drvui->polyhedra[i].poly_size, string);
2566 } else if (drvui->polyhedra[i].poly_min > 0.005) { // shell command if minimum distance specified
2567 fprintf (out, "shell %s %6.3f %6.3f %s\n", atom1,
2568 drvui->polyhedra[i].poly_min, drvui->polyhedra[i].poly_size,
2569 string);
2570 } else { // polysz command
2571 fprintf (out, "polysz %s %6.3f %s\n", atom1,
2572 drvui->polyhedra[i].poly_size, string);
2573 }
2574 }
2575 }
2576 // add polyedge commands
2577 for (i = 1; i < drvui->npoly; i++) {
2578 if (drvui->polyhedra[i].poly_fn == Frame_No) {
2579 if (drvui->polyhedra[i].poly_rad_edge > 0.0f) {
2580 char atom1[5];
2581
2582 strncpy (atom1, drvui->polyhedra[i].poly_l, 4);
2583 atom1[4] = 0;
2584 for (j = 0; j < strlen (atom1); j++)
2585 if (atom1[j] <= ' ')
2586 atom1[j] = 0;
2587 fprintf (out, "polyedge %s %6.3f %s\n", atom1,
2588 drvui->polyhedra[i].poly_rad_edge,
2589 drvui->polyhedra[i].poly_col_edge);
2590 }
2591 }
2592 }
2593 }
2594 // add plane commands
2595 if (drvui->nplane > 1) {
2596 for (i = 1; i < drvui->nplane; i++) {
2597 if (drvui->planes[i].plane_fn == Frame_No) {
2598 char atom1[5];
2599
2600 strncpy (string, drvui->planes[i].plane_col, 39);
2601 string[39] = 0;
2602 for (j = 0; j < strlen (string); j++)
2603 if (string[j] < ' ')
2604 string[j] = 0;
2605 strncpy (atom1, drvui->planes[i].plane_l, 4);
2606 atom1[4] = 0;
2607 for (j = 0; j < strlen (atom1); j++)
2608 if (atom1[j] <= ' ')
2609 atom1[j] = 0;
2610 fprintf (out, "plane %s %6.3f %s\n", atom1, drvui->planes[i].plane_size,
2611 string);
2612 }
2613 }
2614 }
2615 // add lonepair command(s)
2616 if (drvui->ncone > 1) {
2617 for (i = 1; i < drvui->ncone; i++) {
2618 char atom[5];
2619
2620 if (drvui->cones[i].cone_fn == Frame_No) {
2621 strncpy (string, drvui->cones[i].col_cone, 39);
2622 string[39] = 0;
2623 for (j = 0; j < strlen (string); j++)
2624 if (string[j] < ' ')
2625 string[j] = 0;
2626 strncpy (atom, drvui->cones[i].cone_l1, 4);
2627 atom[4] = 0;
2628 for (j = 0; j < strlen (atom); j++)
2629 if (atom[j] <= ' ')
2630 atom[j] = 0;
2631 fprintf (out, "lonepair %s %d %6.3f %6.3f %6.3f %s\n", atom,
2632 drvui->cones[i].numlonepairs, drvui->cones[i].cone_height,
2633 drvui->cones[i].cone_min, drvui->cones[i].cone_max, string);
2634 }
2635 }
2636 }
2637 // add labeltext command(s)
2638 if (drvui->nlabel > 1) {
2639 for (i = 1; i < drvui->nlabel; i++) {
2640 if (drvui->labels[i].label_fn == Frame_No) {
2641 if (!strcmp (drvui->labels[i].label_label, "triple_vect")) {
2642 fprintf (out, "vectors %.3f %.3f %.3f\n", offset[0], offset[1],
2643 offset[2]);
2644 } else {
2645 fprintf (out, "labeltext %6.3f %6.3f %6.3f %s\n",
2646 drvui->labels[i].label_x[0], drvui->labels[i].label_x[1],
2647 drvui->labels[i].label_x[2], drvui->labels[i].label_label);
2648 }
2649 }
2650 }
2651 }
2652 // add pack commands for this frame
2653 if (packflag) {
2654 fprintf (out, "pack %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n",
2655 drvui->frames[Frame_No].cryst_lim[0],
2656 drvui->frames[Frame_No].cryst_lim[3],
2657 drvui->frames[Frame_No].cryst_lim[1],
2658 drvui->frames[Frame_No].cryst_lim[4],
2659 drvui->frames[Frame_No].cryst_lim[2],
2660 drvui->frames[Frame_No].cryst_lim[5]);
2661 }
2662 // add clip commands for this frame
2663 if (clipflag) {
2664 fprintf (out, "clip %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n",
2665 drvui->frames[Frame_No].clip_lim[0], drvui->frames[Frame_No].clip_lim[3],
2666 drvui->frames[Frame_No].clip_lim[1], drvui->frames[Frame_No].clip_lim[4],
2667 drvui->frames[Frame_No].clip_lim[2],
2668 drvui->frames[Frame_No].clip_lim[5]);
2669 }
2670 if (Map_Info.info_valid) {
2671 if (drvui->modulated != 0)
2672 fprintf (out, "mapregion %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f\n",
2673 drvui->frames[Frame_No].map_lim[0], drvui->frames[Frame_No].map_lim[3],
2674 drvui->frames[Frame_No].map_lim[1], drvui->frames[Frame_No].map_lim[4],
2675 drvui->frames[Frame_No].map_lim[2], drvui->frames[Frame_No].map_lim[5],
2676 drvui->frames[Frame_No].map_lim[6], drvui->frames[Frame_No].map_lim[7],
2677 drvui->frames[Frame_No].map_lim[8]);
2678 else
2679 fprintf (out, "mapregion %.4f %.4f %.4f %.4f %.4f %.4f\n",
2680 drvui->frames[Frame_No].map_lim[0], drvui->frames[Frame_No].map_lim[3],
2681 drvui->frames[Frame_No].map_lim[1], drvui->frames[Frame_No].map_lim[4],
2682 drvui->frames[Frame_No].map_lim[2], drvui->frames[Frame_No].map_lim[5]);
2683 if (drvui->frames[Frame_No].slice >0)
2684 fprintf (out, "mapslice %.3f %.3f %.3f %.3f %.3f %.3f %d\n",
2685 drvui->frames[Frame_No].mapslice[0], drvui->frames[Frame_No].mapslice[1],
2686 drvui->frames[Frame_No].mapslice[2], drvui->frames[Frame_No].mapnorm[0],
2687 drvui->frames[Frame_No].mapnorm[1], drvui->frames[Frame_No].mapnorm[2],
2688 drvui->frames[Frame_No].slice);
2689 }
2690
2691 // add atomic property value lines
2692 if (drvui->natprop > 1) {
2693 for (i = 1; i < drvui->natprop; i++) {
2694 if (drvui->atprops[i].atprop_fn == Frame_No) {
2695 if (drvui->atprops[i].atprop_n == -1) {
2696 fprintf (out, "values %s * %6.3f\n", drvui->atprops[i].atprop_l,
2697 drvui->atprops[i].radius);
2698 } else {
2699 fprintf (out, "values %s %d %6.3f\n", drvui->atprops[i].atprop_l,
2700 drvui->atprops[i].atprop_n, drvui->atprops[i].radius);
2701 }
2702 }
2703 }
2704 }
2705 }
2706
2707 void
2708 Update_Str (int overwrite)
2709 {
2710 // routine to update the tmp file with the new values from the widgets
2711 // if 'overwrite' is true, delete the str file and move (rename) the tmp file to str
2712 FILE *inp;
2713
2714 FILE *out;
2715
2716 char string[256];
2717
2718 char temp_out[256];
2719
2720 static const char *surftypes[3] = { "mesh", "solid", "dots"};
2721
2722 int i;
2723
2724 int Upd_magnification = 1;
2725
2726 int Upd_depthcue = 1;
2727
2728 int Upd_molcomp = 1;
2729
2730 int Upd_ellipsoids = 1;
2731
2732 int Upd_cutout = 1;
2733
2734 int Upd_list = 1;
2735
2736 int Upd_vrml = 1;
2737
2738 int Upd_orthographic = 1;
2739
2740 int Upd_axislines = 1;
2741
2742 int Upd_box = 1;
2743
2744 int Upd_edges = 1;
2745
2746 int Upd_polytolerance = 1;
2747
2748 int Upd_background = 1;
2749
2750 int Frame_No;
2751
2752 int Upd_finish = 1;
2753
2754 int Upd_xyzoff = 1;
2755
2756 int copy_end = 0;
2757
2758 Frame_No = 1;
2759 inp = fopen (drvui->Cur_Temp, "r"); // open the existing file
2760 if (!inp)
2761 return;
2762
2763 strcpy (temp_out, drvui->Cur_Temp);
2764 strcat (temp_out, "a");
2765 if (!(out = fopen (temp_out, "w"))) { // open a temp file
2766 fclose (inp);
2767 Error_Box ("Unable to open temporary file.");
2768 return;
2769 }
2770 while (1) {
2771 fgets (string, 256, inp);
2772 trim_string (string, 256);
2773 if (feof (inp) != 0)
2774 break;
2775
2776 /* see if we need to preserve the terminal END of an inlined dataset */
2777 if (strstr (string, "inline") || strstr (string, "INLINE")) {
2778 if (strstr (string, "shelx")
2779 || strstr (string, "shakal")
2780 || strstr (string, "schakal"))
2781 copy_end = 1;
2782 if (strstr (string, "SHELX")
2783 || strstr (string, "SHAKAL")
2784 || strstr (string, "SCHAKAL"))
2785 copy_end = 1;
2786 }
2787 if (copy_end == 1) { // for shelx data, hklf is as good as end
2788 if (strstr (string, "HKLF") || strstr (string, "hklf"))
2789 copy_end = 0;
2790 }
2791 if (!strncmp (string, "end", 3) || !strncmp (string, "END", 3)) {
2792 if (copy_end == 0)
2793 strcpy (string, "");
2794 else
2795 copy_end = 0;
2796 }
2797 if (strncmp (string, "frame", 5) == 0) {
2798 Update_Objects (Frame_No, out); // update stuff for this frame
2799 Frame_No++;
2800 }
2801 //
2802 // update lines containing information contained in widgets
2803 // magnification, depthcue, molcomp, ellipsoids, cutout, list, pack
2804 // view, vrml, orthographic, vectors, axislines, box, edges
2805 // phong, origin, polytolerance, background, clip, bond, special
2806 // polysz, plane, polyvert, shell, sphere, lonepair, slab, noshadow
2807 // arrow, mag_trans, ellipcolor, dash, phong, mapcontour, mapcontour2d,
2808 // labeltext, mapread, mapregion, xyzoff, labelscale, import cif,
2809 // lookat -> view
2810
2811 if (strncmp (string, "magnification", 13) == 0) {
2812 if (fabs (Magnification - 1.0) > 0.001) {
2813 sprintf (string, "magnification %6.2f", Magnification);
2814 Upd_magnification = 0;
2815 } else {
2816 strcpy (string, "");
2817 }
2818 }
2819 if (strncmp (string, "depthcue", 8) == 0) {
2820 if (DepthCue > 0.001) {
2821 sprintf (string, "depthcue %6.3f", DepthCue);
2822 Upd_depthcue = 0;
2823 } else {
2824 strcpy (string, "");
2825 }
2826 }
2827 if (strncmp (string, "molcomp", 7) == 0) {
2828 if (drvui->mol_d > 0.0f) {
2829 sprintf (string, "molcomp %6.2f", drvui->mol_d);
2830 Upd_molcomp = 0;
2831 } else
2832 strcpy (string, "");
2833 }
2834 if (strncmp (string, "ellipsoids", 10) == 0) {
2835 if (drvui->do_ellipsoids)
2836 sprintf (string, "ellipsoids %6.2f", drvui->Ellipsoid_Prob);
2837 else
2838 strcpy (string, "");
2839 Upd_ellipsoids = 0;
2840 }
2841 if (strncmp (string, "cutout", 6) == 0) {
2842 if (strlen (drvui->Cutout_color) != 0) {
2843 sprintf (string, "cutout %s", drvui->Cutout_color);
2844 Upd_cutout = 0;
2845 } else
2846 strcpy (string, "");
2847 }
2848 if (strncmp (string, "list", 4) == 0) {
2849 if (fabs (printdist - 3.5) > 0.001) {
2850 sprintf (string, "list %6.2f", printdist);
2851 Upd_list = 0;
2852 } else
2853 strcpy (string, "");
2854 }
2855 if (strncmp (string, "pack", 4) == 0) {
2856 strcpy (string, "");
2857 }
2858 if (strncmp (string, "slab", 4) == 0) {
2859 strcpy (string, "");
2860 }
2861 if (strncmp (string, "view", 4) == 0) {
2862 strcpy (string, "");
2863 }
2864 if (strncmp (string, "vrml", 4) == 0) {
2865 Upd_vrml = 0;
2866 if (Vrml2 == 0)
2867 sprintf (string, "vrml1");
2868 else
2869 sprintf (string, "vrml97");
2870 }
2871 if (strncmp (string, "orthographic", 12) == 0) {
2872 if (M_cameras == 0) {
2873 sprintf (string, "orthographic");
2874 Upd_orthographic = 0;
2875 } else
2876 strcpy (string, "");
2877 }
2878 if (strncmp (string, "vectors", 7) == 0) {
2879 strcpy (string, "");
2880 }
2881 if (strncmp (string, "polyedge", 8) == 0) {
2882 strcpy (string, "");
2883 }
2884 if (strncmp (string, "axislines", 9) == 0) {
2885 sprintf (string, "axislines %6.2f %s", drvui->Ellipaxis_width,
2886 drvui->Ellipaxis_color);
2887 Upd_axislines = 0;
2888 }
2889 if (strncmp (string, "box", 3) == 0) {
2890 sprintf (string, "box %6.3f %s", rad_cell, drvui->col_cell);
2891 Upd_box = 0;
2892 }
2893 if (strncmp (string, "edges", 5) == 0) {
2894 if (edges) {
2895 sprintf (string, "edges %6.2f %s", drvui->rad_edge, drvui->col_edge);
2896 Upd_edges = 0;
2897 } else
2898 strcpy (string, "");
2899 }
2900 if (strncmp (string, "origin", 6) == 0)
2901 strcpy (string, "");
2902 if (strncmp (string, "polytolerance", 13) == 0) {
2903 if (drvui->polylimit > 0.105) {
2904 sprintf (string, "polytolerance %6.2f", drvui->polylimit);
2905 Upd_polytolerance = 0;
2906 } else
2907 strcpy (string, "");
2908 }
2909 if (strncmp (string, "background", 10) == 0) {
2910 sprintf (string, "background %s", drvui->col_bg);
2911 Upd_background = 0;
2912 }
2913 if (strncmp (string, "finish", 6) == 0) {
2914 sprintf (string, "finish %6.2f %6.2f %6.2f %6.2f", drvui->ambient,
2915 drvui->diffuse, drvui->specular, drvui->roughness);
2916 Upd_finish = 0;
2917 }
2918 if (strncmp (string, "clip", 4) == 0)
2919 strcpy (string, "");
2920 if (strncmp (string, "bond", 4) == 0)
2921 strcpy (string, "");
2922 if (strncmp (string, "dash", 4) == 0)
2923 strcpy (string, "");
2924 if (strncmp (string, "special", 7) == 0)
2925 strcpy (string, "");
2926 if (strncmp (string, "polysz", 6) == 0)
2927 strcpy (string, "");
2928 if (strncmp (string, "plane", 5) == 0)
2929 strcpy (string, "");
2930 if (strncmp (string, "polyvert", 8) == 0)
2931 strcpy (string, "");
2932 if (strncmp (string, "shell", 5) == 0)
2933 strcpy (string, "");
2934 if (strncmp (string, "sphere", 6) == 0)
2935 strcpy (string, "");
2936 if (strncmp (string, "lonepair", 8) == 0)
2937 strcpy (string, "");
2938 if (strncmp (string, "noshadow", 8) == 0)
2939 strcpy (string, "");
2940 if (strncmp (string, "arrow", 5) == 0)
2941 strcpy (string, "");
2942 if (strncmp (string, "mag_trans", 9) == 0)
2943 strcpy (string, "");
2944 if (strncmp (string, "ellipcolor", 10) == 0)
2945 strcpy (string, "");
2946 if (strncmp (string, "phong", 5) == 0)
2947 strcpy (string, "");
2948 if (strncmp (string, "mapcontour", 10) == 0)
2949 strcpy (string, "");
2950 if (strncmp (string, "labeltext", 9) == 0)
2951 strcpy (string, "");
2952 if (strncmp (string, "mapread", 7) == 0)
2953 strcpy (string, "");
2954 if (strncmp (string, "mapregion", 9) == 0)
2955 strcpy (string, "");
2956 if (strncmp (string, "mapslice", 8) == 0)
2957 strcpy (string, "");
2958 if (strncmp (string, "xyzoff", 6) == 0) {
2959 Upd_xyzoff = 0;
2960 drvui->origin1_flag = 0;
2961 }
2962 if (strncmp (string, "labelscale", 10) == 0) {
2963 strcpy (string, "");
2964 }
2965 if (strncmp (string, "lookat", 6) == 0) {
2966 strcpy (string, "");
2967 }
2968 if (strncmp (string, "nolabels", 8) == 0) {
2969 strcpy (string, "");
2970 }
2971 if (strncmp (string, "average", 7) == 0) {
2972 strcpy (string, "");
2973 }
2974 if (strncmp (string, "phaseshift", 10) == 0) {
2975 strcpy (string, "");
2976 }
2977 if (strncmp (string, "occupancy", 9) == 0) {
2978 strcpy (string, "");
2979 }
2980 if (strncmp (string, "aimsurf", 7) == 0) {
2981 strcpy (string, "");
2982 }
2983 if (strncmp (string, "voids", 5) == 0) {
2984 strcpy (string, "");
2985 }
2986 if (strncmp (string, "values", 6) == 0) {
2987 strcpy (string, "");
2988 }
2989 if (strncmp (string, "import", 6) == 0 && strstr (string, "cif")) {
2990 char string2[5];
2991
2992 i = strlen (string) - 1;
2993 if (isdigit (string[i])) { // if number at end
2994 for (int j = i; j > i - 6; j--) {
2995 if (isspace (string[j])) { // strip off number
2996 string[j] = '\0';
2997 break;
2998 }
2999 if (isalpha (string[j]))
3000 break; // unless it is attached to filename
3001 }
3002 }
3003 sprintf (string2, " %d", Block_CIF);
3004 strcat (string, string2); // add block number for CIF
3005 }
3006 if (strncmp (string, "rem xyzoff", 10) == 0)
3007 strcpy (string, "");
3008 if (strncmp (string, "rem - following lines indicate", 30) == 0)
3009 strcpy (string, "");
3010 if ((i = strlen (string)) > 0)
3011 if (string[i - 1] <= 13)
3012 string[i - 1] = 0;
3013 if ((i = strlen (string)) > 0) {
3014 if (string[i - 1] <= 13)
3015 string[i - 1] = 0;
3016 fprintf (out, "%s\n", string);
3017 }
3018 }
3019 fclose (inp);
3020 Update_Objects (Frame_No, out); // update last frame stuff
3021 //
3022 // Add parameters that are or may be generated by widgets but NOT in input file
3023 //
3024 if (drvui->noshadow)
3025 fprintf (out, "noshadow\n");
3026 if (Labels == 0)
3027 fprintf (out, "nolabels\n");
3028 if (fabs (Magnification - 1.0) > 0.001 && Upd_magnification)
3029 fprintf (out, "magnification %6.2f\n", Magnification);
3030 if (DepthCue > 0.001 && Upd_depthcue)
3031 fprintf (out, "depthcue %6.3f\n", DepthCue);
3032 if (drvui->mol_d > 0.0f && Upd_molcomp)
3033 fprintf (out, "molcomp %6.2f\n", drvui->mol_d);
3034 if (drvui->do_ellipsoids && Upd_ellipsoids)
3035 fprintf (out, "ellipsoids %6.2f\n", drvui->Ellipsoid_Prob);
3036 if (strlen (drvui->Cutout_color) != 0 && Upd_cutout)
3037 fprintf (out, "cutout %s\n", drvui->Cutout_color);
3038 if (fabs (printdist - 3.5) > 0.001 && Upd_list)
3039 fprintf (out, "list %6.2f\n", printdist);
3040 if (fabs (drvui->label_scale - 1.0) > 0.001)
3041 fprintf (out, "labelscale %.3f\n", drvui->label_scale);
3042 if (drvui->slab_con[0] > 0.)
3043 fprintf (out, "slab %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f "
3044 "%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %d\n",
3045 drvui->slab_con[0], drvui->slab_con[1], drvui->slab_con[2],
3046 drvui->slab_con[3], drvui->slab_con[4], drvui->slab_con[5],
3047 drvui->slab_off[0], drvui->slab_off[1], drvui->slab_off[2],
3048 drvui->slab_rot[0], drvui->slab_rot[1], drvui->slab_rot[2], slabmode);
3049 fprintf (out, "view %6.1f %6.1f %6.1f\n", Xrot, Yrot, Zrot);
3050 if (Vrml2 == 0 && Upd_vrml == 1)
3051 fprintf (out, "vrml1\n");
3052 if (M_cameras == 0 && Upd_orthographic)
3053 fprintf (out, "orthographic\n");
3054 if ((drvui->Phong_Size != 1.0f) || (drvui->Phong_Value != 0.2f))
3055 fprintf (out, "phong %6.2f %6.2f\n", drvui->Phong_Value, drvui->Phong_Size);
3056 if (Upd_axislines)
3057 fprintf (out, "axislines %6.2f %s\n", drvui->Ellipaxis_width,
3058 drvui->Ellipaxis_color);
3059 if (Upd_box)
3060 fprintf (out, "box %6.3f %s\n", rad_cell, drvui->col_cell);
3061 if (edges && Upd_edges)
3062 fprintf (out, "edges %6.2f %s\n", drvui->rad_edge, drvui->col_edge);
3063 if ((fabs (origin[0] - 0.5) > 0.0001) || (fabs (origin[1] - 0.5) > 0.0001) ||
3064 (fabs (origin[2] - 0.5) > 0.0001))
3065 fprintf (out, "origin %6.2f %6.2f %6.2f\n", origin[0], origin[1], origin[2]);
3066 if (drvui->polylimit > 0.105 && Upd_polytolerance)
3067 fprintf (out, "polytolerance %6.2f\n", drvui->polylimit);
3068 if (Upd_background)
3069 fprintf (out, "background %s\n", drvui->col_bg);
3070 if (Upd_finish)
3071 fprintf (out, "finish %6.2f %6.2f %6.2f %6.2f\n", drvui->ambient,
3072 drvui->diffuse, drvui->specular, drvui->roughness);
3073 if (drvui->do_ellipsoids) {
3074 for (i = 1; i < drvui->n_ellips; i++) {
3075 if (drvui->ellips[i].ell_type > 1000) {
3076 if (drvui->ellips[i].save_el_number != -1)
3077 fprintf (out, "ellipcolor %s %d %s\n", drvui->ellips[i].ellips_l,
3078 drvui->ellips[i].ellips_n, drvui->ellips[i].ellips_col);
3079 else {
3080 int j, haveit;
3081
3082 haveit = 0;
3083 for (j = 1; j < i; j++)
3084 if (check_atom_name
3085 (drvui->ellips[i].ellips_l, drvui->ellips[j].ellips_l))
3086 haveit = 1;
3087 if (haveit == 0)
3088 fprintf (out, "ellipcolor %s * %s\n", drvui->ellips[i].ellips_l,
3089 drvui->ellips[i].ellips_col);
3090 }
3091 }
3092 }
3093 }
3094 // add mapcontour and mapcontour2d commands
3095 if (drvui->numOfFourierContours) {
3096 for (i = 1; i <= drvui->numOfFourierContours; i++) {
3097 char type[6];
3098
3099 if (drvui->Fourier2d) {
3100 fprintf (out, "mapcontour2d %.3f %.3f %.3f %s",
3101 drvui->fourier[i].FourierContourLevel,
3102 drvui->fourier[i].FourierContourStep,
3103 drvui->fourier[i].FourierContourTop,
3104 drvui->fourier[i].FourierContourColor);
3105 if (strlen(drvui->fourier[i].FourierBackColor))
3106 fprintf(out," %s\n",drvui->fourier[i].FourierBackColor);
3107 else
3108 fprintf(out, "\n");
3109 } else {
3110 if (drvui->fourier[i].FourierContourSolid)
3111 strcpy (type, "solid");
3112 else
3113 strcpy (type, "mesh");
3114 fprintf (out, "mapcontour %.3f %s %s\n",
3115 drvui->fourier[i].FourierContourLevel, type,
3116 drvui->fourier[i].FourierContourColor);
3117 }
3118 }
3119 }
3120 // add mapread command if needed
3121 switch (FourierMapType) {
3122 case 1:
3123 strcpy (string, "mapread grd ");
3124 break;
3125 case 2:
3126 strcpy (string, "mapread stf ");
3127 break;
3128 case 3:
3129 strcpy (string, "mapread w2k ");
3130 break;
3131 case 4:
3132 strcpy (string, "mapread vsp ");
3133 break;
3134 case 5:
3135 strcpy (string, "mapread flp ");
3136 break;
3137 case 6:
3138 strcpy (string, "mapread fcf ");
3139 break;
3140 case 7:
3141 strcpy (string, "mapread dn6 ");
3142 break;
3143 case 8:
3144 strcpy (string, "mapread m80 ");
3145 break;
3146 case 9:
3147 strcpy (string, "mapread exc ");
3148 break;
3149 case 10:
3150 strcpy (string, "mapread m81 ");
3151 break;
3152 case 11:
3153 strcpy (string, "mapread xsf ");
3154 break;
3155 default:
3156 strcpy (string, "");
3157 break;
3158 }
3159 if (strlen (string) > 0) {
3160 char res[20];
3161 strcat (string, FourierFileName);
3162 if (FourierMapType == 6 || FourierMapType == 8) { // add calc type
3163 if (Map_Info.map_type == 1)
3164 strcat (string, " Fc");
3165 else if (Map_Info.map_type == 2)
3166 strcat (string, " Fo-Fc");
3167 else if (Map_Info.map_type == 3)
3168 strcat (string, " 2Fo-Fc");
3169 else if (Map_Info.map_type == 4)
3170 strcat (string, " Fo2");
3171 else
3172 strcat (string, " Fo");
3173 }
3174 sprintf(res, " %i", Map_Info.res);
3175 strcat(string, res);
3176 fprintf (out, "%s\n", string);
3177 }
3178 // add options and parameters related to modulation
3179 if (drvui->modulated != 0) {
3180 if (drvui->modulated < 0)
3181 fprintf (out, "average\n");
3182 if (drvui->phaseshift[0] + drvui->phaseshift[1] + drvui->phaseshift[2] > 0.0)
3183 fprintf (out, "phaseshift %.4f %.4f %.4f\n",
3184 drvui->phaseshift[0], drvui->phaseshift[1], drvui->phaseshift[2]);
3185 for (i = 0; i < natom; i++)
3186 if (drvui->atoms[i].min_occ > 0.)
3187 fprintf (out, "occupancy %s %d %.2f %.2f\n", drvui->atoms[i].atom_l,
3188 drvui->atoms[i].sv_atom_n, drvui->atoms[i].occupancy,
3189 drvui->atoms[i].min_occ);
3190 }
3191 // add surface-related options and parameters
3192 if (drvui->nsurf >1 ) {
3193 for (i = 1; i < drvui->nsurf; i++)
3194 fprintf(out,"aimsurf %s %d %s %s %s\n", drvui->surfatom[i], drvui->surfnum[i],
3195 drvui->surffile[i], surftypes[drvui->surftype[i]], drvui->surfcolor[i]);
3196 }
3197 if (drvui->voidflag != 0) {
3198 fprintf (out,"voids %d %.4f %d %d %d %s\n", drvui->voidflag, drvui->probesize,
3199 drvui->voidgrid[0], drvui->voidgrid[1], drvui->voidgrid[2], drvui->voidcolor);
3200 }
3201 // add special command (if needed)
3202 if (Omit->nomits > 0) {
3203 for (i = 0; i < Omit->nomits; i++) {
3204 fprintf (out, "special %d %d\n", Omit->omit1[i], Omit->omit2[i]);
3205 }
3206 }
3207 if (Upd_xyzoff && drvui->origin1_flag)
3208 fprintf (out, "rem xyzoff %.3f %.3f %.3f\n", -drvui->origin_offset[0],
3209 -drvui->origin_offset[1], -drvui->origin_offset[2]);
3210 if (fabs (drvui->Old_Xrot - Xrot) > 0.1)
3211 drvui->Str_File_Changed = 1;
3212 if (fabs (drvui->Old_Yrot - Yrot) > 0.1)
3213 drvui->Str_File_Changed = 1;
3214 if (fabs (drvui->Old_Zrot - Zrot) > 0.1)
3215 drvui->Str_File_Changed = 1;
3216 fprintf (out, "end\n");
3217
3218 if (fclose (out) != 0) {
3219 Error_Box ("Unable to update the working file!");
3220 return;
3221 }
3222
3223 if (!overwrite) {
3224 unlink (drvui->Cur_Temp); // delete the input file
3225 if (rename (temp_out, drvui->Cur_Temp)) { // rename temporary to working
3226 Error_Box ("Unable to update working file!");
3227 return;
3228 }
3229 } else {
3230 unlink (drvui->Cur_File); // delete the str file
3231 if (rename (temp_out, drvui->Cur_File)) { // rename tmp to str
3232 Error_Box ("Unable to create revised str file!");
3233 return;
3234 }
3235 drvui->Str_File_Changed = 0;
3236 }
3237 }
3238
3239 void
3240 WriteConfig (void)
3241 {
3242 // write updated configuration file
3243 FILE *fname;
3244
3245 char filename[256];
3246
3247 #ifdef WIN32
3248 char profile[100];
3249
3250 OSVERSIONINFOEX osvi;
3251
3252 memset (&osvi, 0, sizeof (OSVERSIONINFOEX));
3253 osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
3254 GetVersionEx ((OSVERSIONINFO *) & osvi);
3255 if (osvi.dwMajorVersion == 4)
3256 strcpy (profile, "c:");
3257 else
3258 strcpy (profile, getenv ("USERPROFILE"));
3259 strcpy (filename, profile);
3260 strcat (filename, "\\");
3261 strcat (filename, Configure_file);
3262 #else
3263 fl_filename_expand (filename, Configure_file);
3264 #endif
3265 fname = fopen (filename, "w");
3266 if (!fname) {
3267 return;
3268 }
3269 fprintf (fname, "%s\n%s\n", drvui->DRAWxtl_Path, drvui->POV_Path);
3270 fprintf (fname, "%s\n%s\n", drvui->VRML_Path, drvui->EditName);
3271 fprintf (fname, "%s\n%s\n", drvui->FileViewName, drvui->POV_Options);
3272 fprintf (fname, "%s\n%s\n", drvui->Cur_File, drvui->Cur_Dir);
3273 fprintf (fname, "%s\n", drvui->POV_Include);
3274 fprintf (fname, "%s\n", drvui->LoadOnStartup);
3275 fprintf (fname, "%s\n", drvui->DefaultFinish);
3276 fprintf (fname, "%s\n", drvui->ProgramPath);
3277 if (drvui->autolabel == 0)
3278 fprintf (fname, "noautolabel\n");
3279 else
3280 fprintf (fname, "autolabel\n");
3281 fprintf (fname, "%d %d %.3f\n", drvui->Stereo, drvui->cross_eyed, drvui->stereo_base);
3282 fprintf (fname, "%d %d %d %d\n", drvui->mainWindow->x (), drvui->mainWindow->y (),
3283 drvui->mainWindow->w (), drvui->mainWindow->h ());
3284 fprintf (fname, "povray %d vrml %d asy %d\n", doPOV, doVrml, doAsy);
3285 fprintf (fname, "%s\n", drvui->MSMS_Path);
3286 fprintf (fname, "%s\n", drvui->Mencoder_Path);
3287 fprintf (fname, "%s\n", drvui->FFmpeg_Path);
3288 fclose (fname);
3289 }
3290
3291 QUAT
3292 XYZ_Rot_to_Q (double Xrot, double Yrot, double Zrot)
3293 {
3294 // routine to convert the X,Y,Z rotations into a quaternion
3295 float *axis;
3296
3297 QUAT q1, q2, q3, qtemp, Rotq;
3298
3299 axis = (float *) zalloc (3 * sizeof (float));
3300 axis[0] = 1.0f;
3301 axis_to_quaternion (axis, (float) (Xrot / RAD), &q1);
3302 axis[0] = axis[2] = 0.0;
3303 axis[1] = 1.0f;
3304 axis_to_quaternion (axis, (float) (Yrot / RAD), &q2);
3305 axis[2] = 1.0f;
3306 axis[1] = axis[0] = 0.0;
3307 axis_to_quaternion (axis, (float) (Zrot / RAD), &q3);
3308 qmult (&q3, &q2, &qtemp);
3309 qmult (&qtemp, &q1, &Rotq);
3310 free (axis);
3311 return Rotq;
3312 }
3313
3314 #if 0
3315 void
3316 moveto_atom (int x, int y, int w, int h)
3317 {
3318 // picks the sphere at the current cursor position, moves the crosshair to it
3319 // and updates distance and angle from previous atom(s)
3320
3321 int i, j;
3322
3323 GLint viewport[4];
3324
3325 GLuint names, *ptr, minZ;
3326
3327 GLuint *ptrNames = 0, numberOfNames = 0;
3328
3329 int hits;
3330
3331 int sphere, num;
3332
3333 float cpx, cpy, cpz;
3334
3335 float m[16];
3336
3337 float dot;
3338
3339 char atnum[5];
3340
3341 int ellips;
3342
3343 char cur_name_t[10];
3344
3345 float ratio = 1.0f * (float) w / (float) h;
3346
3347 memset (selectBuf, 0, BUFSIZE);
3348 glGetIntegerv (GL_VIEWPORT, viewport);
3349 glPushMatrix ();
3350
3351 glSelectBuffer (BUFSIZE, selectBuf);
3352 glRenderMode (GL_SELECT);
3353 glMatrixMode (GL_PROJECTION);
3354 glLoadIdentity ();
3355
3356 gluPickMatrix (x, viewport[3] - y, viewport[2] / 100, viewport[3] / 100, viewport);
3357
3358 if (M_cameras == 0) {
3359 if (w <= h)
3360 glOrtho (-gl_size, gl_size, -gl_size / ratio, gl_size / ratio, -10000.,
3361 10000.);
3362 else
3363 glOrtho (-gl_size * ratio, gl_size * ratio, -gl_size, gl_size, -10000.,
3364 10000.);
3365 } else {
3366 gluPerspective (17, ratio, 0.01, 1000.); // view angle, aspect,near/far clip
3367 }
3368 glMatrixMode (GL_MODELVIEW);
3369
3370 glInitNames ();
3371 glPushName (~0);
3372
3373 glTranslatef (drvui->Trans[0], drvui->Trans[1], drvui->Trans[2]);
3374
3375 quaternion_to_rotmatrix (&Rotq, m);
3376
3377 glMultMatrixf (m);
3378 cpx = (POV_Max[0] + POV_Min[0]) / 2.0f;
3379 cpy = (POV_Max[1] + POV_Min[1]) / 2.0f;
3380 cpz = (POV_Max[2] + POV_Min[2]) / 2.0f;
3381
3382
3383 glCallList (drvui->crystalDL);
3384
3385 glPopMatrix ();
3386
3387 hits = glRenderMode (GL_RENDER);
3388 glFlush ();
3389
3390 if (hits == 0)
3391 return;
3392
3393 ptr = (GLuint *) selectBuf;
3394 minZ = 0xffffffff;
3395 for (i = 0; i < hits; i++) {
3396 names = *ptr;
3397 ptr++;
3398 if (*ptr < minZ && *(ptr + 2) != (GLuint) - 1) {
3399 numberOfNames = names;
3400 minZ = *ptr;
3401 ptrNames = ptr + 2;
3402 }
3403 ptr += names + 2;
3404 }
3405 if (numberOfNames == 0)
3406 return;
3407
3408 ptr = ptrNames;
3409
3410 sphere = *ptr;
3411 ptr++;
3412 num = *ptr;
3413
3414 ellips = 0;
3415
3416 if (sphere > 90000 && sphere / 100000 < drvui->n_ellips) {
3417 ellips = 1;
3418 sphere /= 100000;
3419 } else if (sphere >= drvui->nsphere)
3420 return; // not a sphere
3421
3422
3423 nvert = 0; // clear the vertex list
3424 for (j = 0; j < natom; ++j) { // loop through atoms
3425 if (drvui->atoms[j].atom_fn != drvui->frame_no)
3426 continue;
3427 if ((drvui->atoms[j].atom_n & 255) == sphere
3428 || ((drvui->atoms[j].atom_n >> 24) & 255) == sphere)
3429 find_all_in_box (j);
3430 }
3431
3432 if (nvert == 0)
3433 return;
3434
3435 cur_cen[0] = o_vert[3 * num];
3436 cur_cen[1] = o_vert[3 * num + 1];
3437 cur_cen[2] = o_vert[3 * num + 2];
3438 if (cur_atom[3] > 0) {
3439 cur_atom[0] = cur_atom[1];
3440 cur_atom[1] = cur_atom[2];
3441 cur_atom[2] = cur_atom[3];
3442 strcpy (cur_name[0], cur_name[1]);
3443 strcpy (cur_name[1], cur_name[2]);
3444 strcpy (cur_name[2], cur_name[3]);
3445 }
3446 i = 0;
3447 if (ellips == 0) {
3448 for (j = 0; j < 4; j++) {
3449 if (drvui->spheres[sphere].sphere_l[j] != ' ')
3450 cur_name_t[i++] = drvui->spheres[sphere].sphere_l[j];
3451 }
3452 } else {
3453 for (j = 0; j < 4; j++) {
3454 if (drvui->ellips[sphere].ellips_l[j] != ' ')
3455 cur_name_t[i++] = drvui->ellips[sphere].ellips_l[j];
3456 }
3457 }
3458 cur_name_t[i] = '\0';
3459 sprintf (atnum, "%d", drvui->atoms[drvui->orig_atom_no[num]].sv_atom_n);
3460 strcat (cur_name_t, atnum);
3461
3462 if (cur_atom[0] <= 0) {
3463 cur_atom[0] = i;
3464 strcpy (cur_name[0], cur_name_t);
3465 } else if (cur_atom[1] <= 0) {
3466 cur_atom[1] = i;
3467 dist12 = dist (cur_atom[0], cur_atom[1]);
3468 strcpy (cur_name[1], cur_name_t);
3469 } else if (cur_atom[2] <= 0) {
3470 cur_atom[2] = i;
3471 strcpy (cur_name[2], cur_name_t);
3472 dist12 = dist (cur_atom[0], cur_atom[1]);
3473 dist23 = dist (cur_atom[1], cur_atom[2]);
3474 if (dist12 == 0.0f || dist23 == 0.0f || cur_atom[2] == cur_atom[0]) {
3475 ang123 = 0.0f;
3476 } else {
3477 dot =
3478 dot0_3d (s_vert[3 * cur_atom[1]], s_vert[3 * cur_atom[1] + 1],
3479 s_vert[3 * cur_atom[1] + 2], s_vert[3 * cur_atom[0]],
3480 s_vert[3 * cur_atom[0] + 1], s_vert[3 * cur_atom[0] + 2],
3481 s_vert[3 * cur_atom[2]], s_vert[3 * cur_atom[2] + 1],
3482 s_vert[3 * cur_atom[2] + 2]);
3483 float temp = dot / (dist12 * dist23);
3484
3485 if (temp > 1.0f)
3486 temp = 1.0f;
3487 if (temp < -1.0f)
3488 temp = -1.0f;
3489 ang123 = (float) (acos (temp) * RAD);
3490 }
3491 } else {
3492 float v1[3], v2[3], v0[3], p1[3], p2[3];
3493
3494 int j;
3495
3496 cur_atom[3] = i;
3497 strcpy (cur_name[3], cur_name_t);
3498 dist23 = dist (cur_atom[1], cur_atom[2]);
3499 dist34 = dist (cur_atom[2], i);
3500 for (j = 0; j < 3; j++) {
3501 v0[j] = s_vert[3 * cur_atom[0] + j] - s_vert[3 * cur_atom[1] + j];
3502 v1[j] = s_vert[3 * cur_atom[1] + j] - s_vert[3 * cur_atom[2] + j];
3503 v2[j] = s_vert[3 * cur_atom[2] + j] - s_vert[3 * cur_atom[3] + j];
3504 }
3505 if (dist23 == 0.0f || dist34 == 0.0f)
3506 ang234 = 0.0f;
3507 else {
3508 dot = vdot (v1, v2);
3509 float temp = -dot / (dist23 * dist34);
3510
3511 if (temp > 1.0f)
3512 temp = 1.0f;
3513 if (temp < -1.0f)
3514 temp = -1.0f;
3515 ang234 = (float) (acos (temp) * RAD);
3516 }
3517 vcross (v0, v1, p1);
3518 vcross (v2, v1, p2);
3519 if (vlength (p1) < 0.1f || vlength (p2) < 0.1f) {
3520 torsion_ang = 0.0f;
3521 return;
3522 }
3523 torsion_ang = -vdot (p1, p2) / (vlength (p1) * vlength (p2));
3524 if (torsion_ang < -1.0f)
3525 torsion_ang = -1.0f;
3526 if (torsion_ang > 1.0f)
3527 torsion_ang = 1.0f;
3528 torsion_ang = (float) (acos (torsion_ang) * RAD);
3529 if (vdot (p1, v2) > 0.0f) // set the sign
3530 torsion_ang *= -1.0f;
3531 }
3532
3533 Fl::redraw ();
3534 }
3535 #endif
3536
3537 int
3538 pick_label (int x, int y, int w, int h)
3539 {
3540 // picks the label at the current cursor position
3541
3542 int i;
3543
3544 GLint viewport[4];
3545
3546 GLuint names, *ptr, minZ;
3547
3548 GLuint *ptrNames = 0, numberOfNames = 0;
3549
3550 int hits;
3551
3552 int label;
3553
3554 float m[16];
3555
3556 int offset;
3557
3558 float ratio = 1.0f * (float) w / (float) h;
3559
3560 memset (selectBuf, 0, BUFSIZE);
3561 glGetIntegerv (GL_VIEWPORT, viewport);
3562 glPushMatrix ();
3563
3564 glSelectBuffer (BUFSIZE, selectBuf);
3565 glRenderMode (GL_SELECT);
3566 glMatrixMode (GL_PROJECTION);
3567 glLoadIdentity ();
3568
3569 offset = (int) (100.0f / gl_size);
3570 gluPickMatrix (x + offset, viewport[3] - y + offset, 25, 25, viewport);
3571
3572 if (M_cameras == 0) {
3573 if (w <= h)
3574 glOrtho (-gl_size, gl_size, -gl_size / ratio, gl_size / ratio, -10000.,
3575 10000.);
3576 else
3577 glOrtho (-gl_size * ratio, gl_size * ratio, -gl_size, gl_size, -10000.,
3578 10000.);
3579 } else {
3580 gluPerspective (17, ratio, 0.01, 1000.); // view angle, aspect,near/far clip
3581 }
3582 glMatrixMode (GL_MODELVIEW);
3583
3584 glInitNames ();
3585 glPushName (~0);
3586
3587 glTranslatef (drvui->Trans[0], drvui->Trans[1], drvui->Trans[2]);
3588
3589 quaternion_to_rotmatrix (&Rotq, m);
3590
3591 glMultMatrixf (m);
3592
3593 for (drvui->frame_no = 1; drvui->frame_no <= drvui->max_frame; drvui->frame_no++)
3594 generate_gl_texts ();
3595 drvui->frame_no = drvui->max_frame;
3596
3597 glPopMatrix ();
3598
3599 hits = glRenderMode (GL_RENDER);
3600 glFlush ();
3601
3602 if (hits == 0)
3603 return (0);
3604
3605 ptr = (GLuint *) selectBuf;
3606 minZ = 0xffffffff;
3607 for (i = 0; i < hits; i++) {
3608 names = *ptr;
3609 ptr++;
3610 if (*ptr < minZ && *(ptr + 2) != (GLuint) - 1) {
3611 numberOfNames = names;
3612 minZ = *ptr;
3613 ptrNames = ptr + 2;
3614 }
3615 ptr += names + 2;
3616 }
3617 if (numberOfNames == 0)
3618 return (0);
3619
3620 ptr = ptrNames;
3621
3622 label = *ptr;
3623
3624 //fprintf(stderr,"picked label no %d\n",label);
3625
3626 if (label >= drvui->nlabel)
3627 return (0); // not a label ?
3628
3629
3630 //cur_cen[0]= drvui->label_x[label][0];
3631 //cur_cen[1]= drvui->label_x[label][1];
3632 //cur_cen[2]= drvui->label_x[label][2];
3633
3634 //Fl::redraw();
3635
3636 return (label);
3637 }
3638