http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.00.tar.gz
[xscreensaver] / hacks / crystal.c
1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* crystal --- polygons moving according to plane group rules */
3
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)crystal.c     4.12 98/09/10 xlockmore";
6
7 #endif
8
9 /*-
10  * Copyright (c) 1997 by Jouk Jansen <joukj@crys.chem.uva.nl>
11  *
12  * Permission to use, copy, modify, and distribute this software and its
13  * documentation for any purpose and without fee is hereby granted,
14  * provided that the above copyright notice appear in all copies and that
15  * both that copyright notice and this permission notice appear in
16  * supporting documentation.
17  *
18  * This file is provided AS IS with no warranties of any kind.  The author
19  * shall have no liability with respect to the infringement of copyrights,
20  * trade secrets or any patents by this file or any part thereof.  In no
21  * event will the author be liable for any lost revenue or profits or
22  * other special, indirect and consequential damages.
23  *
24  * The author should like to be notified if changes have been made to the
25  * routine.  Response will only be guaranteed when a VMS version of the 
26  * program is available.
27  *
28  * A moving polygon-mode. The polygons obey 2D-planegroup symmetry.
29  *
30  * The groupings of the cells fall in 3 categories:
31  *   oblique groups 1 and 2 where the angle gamma ranges from 60 to 120 degrees
32  *   square groups 3 through 11 where the angle gamma is 90 degrees
33  *   hexagonal groups 12 through 17 where the angle gamma is 120 degrees
34  *
35  * Revision History:
36  * 03-Dec-98: Random inversion of y-axis included to simulate hexagonal groups
37  *             with an angle of 60 degrees.
38  * 10-Sep-98: new colour scheme
39  * 24-Feb-98: added option centre which turns on/off forcing the centre of
40  *              the screen to be used
41  *            added option maxsize which forces the dimensions to be chasen
42  *              in such ua way that the largest possible part of the screen is
43  *              used 
44  *            When only one unit cell is drawn, it is chosen at random
45  * 18-Feb-98: added support for negative numbers with -nx and -ny meaning
46  *            "random" choice with given maximum
47  *            added +/-grid option. If -cell is specified this option
48  *            determines if one or all unit cells are drawn.
49  *            -batchcount is now a parameter for all the objects on the screen
50  *            instead of the number of "unique" objects
51  *            The maximum size of the objects now scales with the part
52  *            of the screen used.
53  *            fixed "size" problem. Now very small non-vissable objects
54  *            are not allowed
55  * 13-Feb-98: randomized the unit cell size
56  *            runtime options -/+cell (turn on/off unit cell drawing)
57  *             -nx num (number of translational symmetries in x-direction
58  *             -ny num (idem y-direction but ignored for square and
59  *               hexagonal space groups
60  *               i.e. try xlock -mode crystal -nx 3 -ny 2
61  *            Fullrandom overrules the -/+cell option.
62  * 05-Feb-98: Revision + bug repairs
63  *            shows unit cell
64  *            use part of the screen for unit cell
65  *            in hexagonal and square groups a&b axis forced to be equal
66  *            cell angle for oblique groups randomly chosen between 60 and 120
67  *   bugs solved: planegroups with cell angles <> 90.0 now work properly
68  * 19-Sep-97: Added remaining hexagonal groups
69  * 12-Jun-97: Created
70  */
71
72 #ifdef STANDALONE
73 # define PROGCLASS              "Crystal"
74 # define HACK_INIT              init_crystal
75 # define HACK_DRAW              draw_crystal
76 # define crystal_opts   xlockmore_opts
77 # define DEFAULTS               "*delay:                60000   \n" \
78                                                  "*count:                -500   \n" \
79                                                  "*cycles:                200   \n" \
80                                                  "*size:                  -15   \n" \
81                                                  "*ncolors:               100   \n" \
82                                                  "*fullrandom:   True   \n" \
83                                                  "*verbose:             False   \n"
84 # include "xlockmore.h"         /* in xscreensaver distribution */
85 #else /* STANDALONE */
86 # include "xlock.h"                     /* in xlockmore distribution */
87 # include "color.h"
88 #endif /* STANDALONE */
89
90 #define DEF_CELL "True"         /* Draw unit cell */
91 #define DEF_GRID "False"        /* Draw unit all cell if DEF_CELL is True */
92 #define DEF_NX "-3"             /* number of unit cells in x-direction */
93 #define DEF_NX1 1               /* number of unit cells in x-direction */
94 #define DEF_NY "-3"             /* number of unit cells in y-direction */
95 #define DEF_NY1 1               /* number of unit cells in y-direction */
96 #define DEF_CENTRE "False"
97 #define DEF_MAXSIZE "False"
98 #define DEF_CYCLE "True"
99
100 #define min(a,b) ((a) <= (b) ? (a) : (b))
101
102 #ifdef STANDALONE
103 void release_crystal(ModeInfo * mi);
104 #endif
105
106 static int  nx, ny;
107
108 static Bool unit_cell, grid_cell, centre, maxsize, cycle_p;
109
110 static XrmOptionDescRec opts[] =
111 {
112         {"-nx", "crystal.nx", XrmoptionSepArg, (caddr_t) NULL},
113         {"-ny", "crystal.ny", XrmoptionSepArg, (caddr_t) NULL},
114         {"-centre", ".crystal.centre", XrmoptionNoArg, (caddr_t) "on"},
115         {"+centre", ".crystal.centre", XrmoptionNoArg, (caddr_t) "off"},
116         {"-maxsize", ".crystal.maxsize", XrmoptionNoArg, (caddr_t) "on"},
117         {"+maxsize", ".crystal.maxsize", XrmoptionNoArg, (caddr_t) "off"},
118         {"-cell", ".crystal.cell", XrmoptionNoArg, (caddr_t) "on"},
119         {"+cell", ".crystal.cell", XrmoptionNoArg, (caddr_t) "off"},
120         {"-grid", ".crystal.grid", XrmoptionNoArg, (caddr_t) "on"},
121         {"+grid", ".crystal.grid", XrmoptionNoArg, (caddr_t) "off"},
122         {"-shift", ".crystal.shift", XrmoptionNoArg, (caddr_t) "on"},
123         {"+shift", ".crystal.shift", XrmoptionNoArg, (caddr_t) "off"}
124 };
125
126 static argtype vars[] =
127 {
128         {(caddr_t *) & nx, "nx", "nx", DEF_NX, t_Int},
129         {(caddr_t *) & ny, "ny", "ny", DEF_NY, t_Int},
130         {(caddr_t *) & centre, "centre", "Centre", DEF_CENTRE, t_Bool},
131         {(caddr_t *) & maxsize, "maxsize", "Maxsize", DEF_MAXSIZE, t_Bool},
132         {(caddr_t *) & unit_cell, "cell", "Cell", DEF_CELL, t_Bool},
133         {(caddr_t *) & grid_cell, "grid", "Grid", DEF_GRID, t_Bool},
134         {(caddr_t *) & cycle_p, "shift", "Shift", DEF_CYCLE, t_Bool}
135 };
136 static OptionStruct desc[] =
137 {
138         {"-nx num", "Number of unit cells in x-direction"},
139         {"-ny num", "Number of unit cells in y-direction"},
140         {"-/+centre", "turn on/off centering on screen"},
141         {"-/+maxsize", "turn on/off use of maximum part of screen"},
142         {"-/+cell", "turn on/off drawing of unit cell"},
143    {"-/+grid", "turn on/off drawing of grid of unit cells (if -cell is on)"},
144         {"-/+shift", "turn on/off colour cycling"}
145 };
146
147 ModeSpecOpt crystal_opts =
148 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
149
150 #ifdef USE_MODULES
151 ModStruct   crystal_description =
152 {"crystal", "init_crystal", "draw_crystal", "release_crystal",
153  "refresh_crystal", "init_crystal", NULL, &crystal_opts,
154  60000, -40, 200, -15, 64, 1.0, "",
155  "Shows polygons in 2D plane groups", 0, NULL};
156
157 #endif
158
159 #define DEF_NUM_ATOM 10
160
161 #define DEF_SIZ_ATOM 10
162
163 #define PI_RAD (M_PI / 180.0)
164
165 static Bool centro[17] =
166 {
167         False,
168         True,
169         False,
170         False,
171         False,
172         True,
173         True,
174         True,
175         True,
176         True,
177         True,
178         True,
179         False,
180         False,
181         False,
182         True,
183         True
184 };
185
186 static Bool primitive[17] =
187 {
188         True,
189         True,
190         True,
191         True,
192         False,
193         True,
194         True,
195         True,
196         False,
197         True,
198         True,
199         True,
200         True,
201         True,
202         True,
203         True,
204         True
205 };
206
207 static short numops[34] =
208 {
209         1, 0,
210         1, 0,
211         9, 7,
212         2, 0,
213         9, 7,
214         9, 7,
215         4, 2,
216         5, 3,
217         9, 7,
218         8, 6,
219         10, 6,
220         8, 4,
221         16, 13,
222         19, 13,
223         16, 10,
224         19, 13,
225         19, 13
226 };
227
228 static short operation[114] =
229 {
230         1, 0, 0, 1, 0, 0,
231         -1, 0, 0, 1, 0, 1,
232         -1, 0, 0, 1, 1, 0,
233         1, 0, 0, 1, 0, 0,
234         -1, 0, 0, 1, 1, 1,
235         1, 0, 0, 1, 1, 1,
236         0, -1, 1, 0, 0, 0,
237         1, 0, 0, 1, 0, 0,
238         -1, 0, 0, 1, 0, 0,
239         0, 1, 1, 0, 0, 0,
240         -1, 0, -1, 1, 0, 0,
241         1, -1, 0, -1, 0, 0,
242         0, 1, 1, 0, 0, 0,
243         0, -1, 1, -1, 0, 0,
244         -1, 1, -1, 0, 0, 0,
245         1, 0, 0, 1, 0, 0,
246         0, -1, -1, 0, 0, 0,
247         -1, 1, 0, 1, 0, 0,
248         1, 0, 1, -1, 0, 0
249 };
250
251 typedef struct {
252         unsigned long colour;
253         int         x0, y0, velocity[2];
254         float       angle, velocity_a;
255         int         num_point, at_type, size_at;
256         XPoint      xy[5];
257 } crystalatom;
258
259 typedef struct {
260         Bool        painted;
261         int         win_width, win_height, num_atom;
262         int         planegroup, a, b, offset_w, offset_h, nx, ny;
263         float       gamma;
264         crystalatom *atom;
265         GC          gc;
266         Bool        unit_cell, grid_cell;
267         Colormap    cmap;
268         XColor     *colors;
269         int         ncolors;
270         Bool        cycle_p, mono_p, no_colors;
271         unsigned long blackpixel, whitepixel, fg, bg;
272         int         direction, invert;
273 } crystalstruct;
274
275 static crystalstruct *crystals = NULL;
276
277 static void
278 trans_coor(XPoint * xyp, XPoint * new_xyp, int num_points,
279            float gamma)
280 {
281         int         i;
282
283         for (i = 0; i <= num_points; i++) {
284                 new_xyp[i].x = xyp[i].x +
285                         (int) (xyp[i].y * sin((gamma - 90.0) * PI_RAD));
286                 new_xyp[i].y = (int) (xyp[i].y / cos((gamma - 90.0) * PI_RAD));
287         }
288 }
289
290 static void
291 trans_coor_back(XPoint * xyp, XPoint * new_xyp,
292                 int num_points, float gamma, int offset_w, int offset_h ,
293                 int winheight , int invert )
294 {
295         int         i;
296
297         for (i = 0; i <= num_points; i++) {
298                 new_xyp[i].y = (int) (xyp[i].y * cos((gamma - 90) * PI_RAD)) +
299                         offset_h;
300                 new_xyp[i].x = xyp[i].x - (int) (xyp[i].y * sin((gamma - 90.0)
301                                                        * PI_RAD)) + offset_w;
302            if ( invert ) new_xyp[i].y = winheight - new_xyp[i].y;
303         }
304 }
305
306 static void
307 crystal_setupatom(crystalatom * atom0, float gamma)
308 {
309         XPoint      xy[5];
310         int         x0, y0;
311
312         y0 = (int) (atom0->y0 * cos((gamma - 90) * PI_RAD));
313         x0 = atom0->x0 - (int) (atom0->y0 * sin((gamma - 90.0) * PI_RAD));
314         switch (atom0->at_type) {
315                 case 0: /* rectangles */
316                         xy[0].x = x0 + (int) (2 * atom0->size_at *
317                                               cos(atom0->angle)) +
318                                 (int) (atom0->size_at * sin(atom0->angle));
319                         xy[0].y = y0 + (int) (atom0->size_at *
320                                               cos(atom0->angle)) -
321                                 (int) (2 * atom0->size_at * sin(atom0->angle));
322                         xy[1].x = x0 + (int) (2 * atom0->size_at *
323                                               cos(atom0->angle)) -
324                                 (int) (atom0->size_at * sin(atom0->angle));
325                         xy[1].y = y0 - (int) (atom0->size_at *
326                                               cos(atom0->angle)) -
327                                 (int) (2 * atom0->size_at * sin(atom0->angle));
328                         xy[2].x = x0 - (int) (2 * atom0->size_at *
329                                               cos(atom0->angle)) -
330                                 (int) (atom0->size_at * sin(atom0->angle));
331                         xy[2].y = y0 - (int) (atom0->size_at *
332                                               cos(atom0->angle)) +
333                                 (int) (2 * atom0->size_at * sin(atom0->angle));
334                         xy[3].x = x0 - (int) (2 * atom0->size_at *
335                                               cos(atom0->angle)) +
336                                 (int) (atom0->size_at * sin(atom0->angle));
337                         xy[3].y = y0 + (int) (atom0->size_at *
338                                               cos(atom0->angle)) +
339                                 (int) (2 * atom0->size_at *
340                                        sin(atom0->angle));
341                         xy[4].x = xy[0].x;
342                         xy[4].y = xy[0].y;
343                         trans_coor(xy, atom0->xy, 4, gamma);
344                         return;
345                 case 1: /* squares */
346                         xy[0].x = x0 + (int) (1.5 * atom0->size_at *
347                                               cos(atom0->angle)) +
348                                 (int) (1.5 * atom0->size_at *
349                                        sin(atom0->angle));
350                         xy[0].y = y0 + (int) (1.5 * atom0->size_at *
351                                               cos(atom0->angle)) -
352                                 (int) (1.5 * atom0->size_at *
353                                        sin(atom0->angle));
354                         xy[1].x = x0 + (int) (1.5 * atom0->size_at *
355                                               cos(atom0->angle)) -
356                                 (int) (1.5 * atom0->size_at *
357                                        sin(atom0->angle));
358                         xy[1].y = y0 - (int) (1.5 * atom0->size_at *
359                                               cos(atom0->angle)) -
360                                 (int) (1.5 * atom0->size_at *
361                                        sin(atom0->angle));
362                         xy[2].x = x0 - (int) (1.5 * atom0->size_at *
363                                               cos(atom0->angle)) -
364                                 (int) (1.5 * atom0->size_at *
365                                        sin(atom0->angle));
366                         xy[2].y = y0 - (int) (1.5 * atom0->size_at *
367                                               cos(atom0->angle)) +
368                                 (int) (1.5 * atom0->size_at *
369                                        sin(atom0->angle));
370                         xy[3].x = x0 - (int) (1.5 * atom0->size_at *
371                                               cos(atom0->angle)) +
372                                 (int) (1.5 * atom0->size_at *
373                                        sin(atom0->angle));
374                         xy[3].y = y0 + (int) (1.5 * atom0->size_at *
375                                               cos(atom0->angle)) +
376                                 (int) (1.5 * atom0->size_at *
377                                        sin(atom0->angle));
378                         xy[4].x = xy[0].x;
379                         xy[4].y = xy[0].y;
380                         trans_coor(xy, atom0->xy, 4, gamma);
381                         return;
382                 case 2: /* triangles */
383                         xy[0].x = x0 + (int) (1.5 * atom0->size_at *
384                                               sin(atom0->angle));
385                         xy[0].y = y0 + (int) (1.5 * atom0->size_at *
386                                               cos(atom0->angle));
387                         xy[1].x = x0 + (int) (1.5 * atom0->size_at *
388                                               cos(atom0->angle)) -
389                                 (int) (1.5 * atom0->size_at *
390                                        sin(atom0->angle));
391                         xy[1].y = y0 - (int) (1.5 * atom0->size_at *
392                                               cos(atom0->angle)) -
393                                 (int) (1.5 * atom0->size_at *
394                                        sin(atom0->angle));
395                         xy[2].x = x0 - (int) (1.5 * atom0->size_at *
396                                               cos(atom0->angle)) -
397                                 (int) (1.5 * atom0->size_at *
398                                        sin(atom0->angle));
399                         xy[2].y = y0 - (int) (1.5 * atom0->size_at *
400                                               cos(atom0->angle)) +
401                                 (int) (1.5 * atom0->size_at *
402                                        sin(atom0->angle));
403                         xy[3].x = xy[0].x;
404                         xy[3].y = xy[0].y;
405                         trans_coor(xy, atom0->xy, 3, gamma);
406                         return;
407         }
408 }
409
410 static void
411 crystal_drawatom(ModeInfo * mi, crystalatom * atom0)
412 {
413         crystalstruct *cryst;
414         Display    *display = MI_DISPLAY(mi);
415         Window      window = MI_WINDOW(mi);
416         int         j, k, l, m;
417
418         cryst = &crystals[MI_SCREEN(mi)];
419         for (j = numops[2 * cryst->planegroup + 1];
420              j < numops[2 * cryst->planegroup]; j++) {
421                 XPoint      xy[5], new_xy[5];
422                 XPoint      xy_1[5];
423                 int         xtrans, ytrans;
424
425                 xtrans = operation[j * 6] * atom0->x0 + operation[j * 6 + 1] *
426                         atom0->y0 + (int) (operation[j * 6 + 4] * cryst->a /
427                                            2.0);
428                 ytrans = operation[j * 6 + 2] * atom0->x0 + operation[j * 6 +
429                                3] * atom0->y0 + (int) (operation[j * 6 + 5] *
430                                                        cryst->b / 2.0);
431                 if (xtrans < 0) {
432                         if (xtrans < -cryst->a)
433                                 xtrans = 2 * cryst->a;
434                         else
435                                 xtrans = cryst->a;
436                 } else if (xtrans >= cryst->a)
437                         xtrans = -cryst->a;
438                 else
439                         xtrans = 0;
440                 if (ytrans < 0)
441                         ytrans = cryst->b;
442                 else if (ytrans >= cryst->b)
443                         ytrans = -cryst->b;
444                 else
445                         ytrans = 0;
446                 for (k = 0; k < atom0->num_point; k++) {
447                         xy[k].x = operation[j * 6] * atom0->xy[k].x +
448                                 operation[j * 6 + 1] *
449                                 atom0->xy[k].y + (int) (operation[j * 6 + 4] *
450                                                         cryst->a / 2.0) +
451                                 xtrans;
452                         xy[k].y = operation[j * 6 + 2] * atom0->xy[k].x +
453                                 operation[j * 6 + 3] *
454                                 atom0->xy[k].y + (int) (operation[j * 6 + 5] *
455                                                         cryst->b / 2.0) +
456                                 ytrans;
457                 }
458                 xy[atom0->num_point].x = xy[0].x;
459                 xy[atom0->num_point].y = xy[0].y;
460                 for (l = 0; l < cryst->nx; l++) {
461                         for (m = 0; m < cryst->ny; m++) {
462
463                                 for (k = 0; k <= atom0->num_point; k++) {
464                                         xy_1[k].x = xy[k].x + l * cryst->a;
465                                         xy_1[k].y = xy[k].y + m * cryst->b;
466                                 }
467                                 trans_coor_back(xy_1, new_xy, atom0->num_point,
468                                                 cryst->gamma, cryst->offset_w,
469                                                 cryst->offset_h ,
470                                                 cryst->win_height,
471                                                 cryst->invert);
472                                 XFillPolygon(display, window, cryst->gc, new_xy,
473                                   atom0->num_point, Convex, CoordModeOrigin);
474                         }
475                 }
476                 if (centro[cryst->planegroup] == True) {
477                         for (k = 0; k <= atom0->num_point; k++) {
478                                 xy[k].x = cryst->a - xy[k].x;
479                                 xy[k].y = cryst->b - xy[k].y;
480                         }
481                         for (l = 0; l < cryst->nx; l++) {
482                                 for (m = 0; m < cryst->ny; m++) {
483
484                                         for (k = 0; k <= atom0->num_point; k++) {
485                                                 xy_1[k].x = xy[k].x + l * cryst->a;
486                                                 xy_1[k].y = xy[k].y + m * cryst->b;
487                                         }
488                                         trans_coor_back(xy_1, new_xy, atom0->num_point,
489                                                         cryst->gamma,
490                                                         cryst->offset_w,
491                                                         cryst->offset_h ,
492                                                         cryst->win_height ,
493                                                         cryst->invert);
494                                         XFillPolygon(display, window, cryst->gc,
495                                                      new_xy,
496                                                      atom0->num_point, Convex,
497                                                      CoordModeOrigin);
498                                 }
499                         }
500                 }
501                 if (primitive[cryst->planegroup] == False) {
502                         if (xy[atom0->num_point].x >= (int) (cryst->a / 2.0))
503                                 xtrans = (int) (-cryst->a / 2.0);
504                         else
505                                 xtrans = (int) (cryst->a / 2.0);
506                         if (xy[atom0->num_point].y >= (int) (cryst->b / 2.0))
507                                 ytrans = (int) (-cryst->b / 2.0);
508                         else
509                                 ytrans = (int) (cryst->b / 2.0);
510                         for (k = 0; k <= atom0->num_point; k++) {
511                                 xy[k].x = xy[k].x + xtrans;
512                                 xy[k].y = xy[k].y + ytrans;
513                         }
514                         for (l = 0; l < cryst->nx; l++) {
515                                 for (m = 0; m < cryst->ny; m++) {
516
517                                         for (k = 0; k <= atom0->num_point; k++) {
518                                                 xy_1[k].x = xy[k].x + l * cryst->a;
519                                                 xy_1[k].y = xy[k].y + m * cryst->b;
520                                         }
521                                         trans_coor_back(xy_1, new_xy, atom0->num_point,
522                                                         cryst->gamma,
523                                                         cryst->offset_w,
524                                                         cryst->offset_h ,
525                                                         cryst->win_height,
526                                                         cryst->invert);
527                                         XFillPolygon(display, window, cryst->gc,
528                                                      new_xy,
529                                                      atom0->num_point, Convex,
530                                                      CoordModeOrigin);
531                                 }
532                         }
533                         if (centro[cryst->planegroup] == True) {
534                                 XPoint      xy1[5];
535
536                                 for (k = 0; k <= atom0->num_point; k++) {
537                                         xy1[k].x = cryst->a - xy[k].x;
538                                         xy1[k].y = cryst->b - xy[k].y;
539                                 }
540                                 for (l = 0; l < cryst->nx; l++) {
541                                         for (m = 0; m < cryst->ny; m++) {
542
543                                                 for (k = 0; k <= atom0->num_point; k++) {
544                                                         xy_1[k].x = xy1[k].x + l * cryst->a;
545                                                         xy_1[k].y = xy1[k].y + m * cryst->b;
546                                                 }
547                                                 trans_coor_back(xy_1, new_xy, atom0->num_point,
548                                                                 cryst->gamma,
549                                                                 cryst->offset_w,
550                                                                 cryst->offset_h ,
551                                                                 cryst->win_height,
552                                                                 cryst->invert);
553                                                 XFillPolygon(display, window,
554                                                              cryst->gc,
555                                                     new_xy, atom0->num_point,
556                                                     Convex, CoordModeOrigin);
557                                         }
558                                 }
559                         }
560                 }
561         }
562 }
563
564 void
565 draw_crystal(ModeInfo * mi)
566 {
567         Display    *display = MI_DISPLAY(mi);
568         crystalstruct *cryst = &crystals[MI_SCREEN(mi)];
569         int         i;
570
571         if (cryst->no_colors) {
572                 release_crystal(mi);
573                 init_crystal(mi);
574                 return;
575         }
576         cryst->painted = True;
577         MI_IS_DRAWN(mi) = True;
578         XSetFunction(display, cryst->gc, GXxor);
579
580 /* Rotate colours */
581         if (cryst->cycle_p) {
582                 rotate_colors(display, cryst->cmap, cryst->colors, cryst->ncolors,
583                               cryst->direction);
584                 if (!(LRAND() % 1000))
585                         cryst->direction = -cryst->direction;
586         }
587         for (i = 0; i < cryst->num_atom; i++) {
588                 crystalatom *atom0;
589
590                 atom0 = &cryst->atom[i];
591
592                 if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
593                         XSetForeground(display, cryst->gc, cryst->colors[atom0->colour].pixel);
594                 } else {
595                         XSetForeground(display, cryst->gc, atom0->colour);
596                 }
597                 crystal_drawatom(mi, atom0);
598                 atom0->velocity[0] += NRAND(3) - 1;
599                 atom0->velocity[0] = MAX(-20, MIN(20, atom0->velocity[0]));
600                 atom0->velocity[1] += NRAND(3) - 1;
601                 atom0->velocity[1] = MAX(-20, MIN(20, atom0->velocity[1]));
602                 atom0->x0 += atom0->velocity[0];
603                 /*if (cryst->gamma == 90.0) { */
604                 if (atom0->x0 < 0)
605                         atom0->x0 += cryst->a;
606                 else if (atom0->x0 >= cryst->a)
607                         atom0->x0 -= cryst->a;
608                 atom0->y0 += atom0->velocity[1];
609                 if (atom0->y0 < 0)
610                         atom0->y0 += cryst->b;
611                 else if (atom0->y0 >= cryst->b)
612                         atom0->y0 -= cryst->b;
613                 /*} */
614                 atom0->velocity_a += ((float) NRAND(1001) - 500.0) / 2000.0;
615                 atom0->angle += atom0->velocity_a;
616                 crystal_setupatom(atom0, cryst->gamma);
617                 crystal_drawatom(mi, atom0);
618         }
619         XSetFunction(display, cryst->gc, GXcopy);
620 }
621
622 void
623 refresh_crystal(ModeInfo * mi)
624 {
625         Display    *display = MI_DISPLAY(mi);
626         Window      window = MI_WINDOW(mi);
627         crystalstruct *cryst = &crystals[MI_SCREEN(mi)];
628         int         i;
629
630         if (!cryst->painted)
631                 return;
632         MI_CLEARWINDOW(mi);
633         XSetFunction(display, cryst->gc, GXxor);
634
635         if (cryst->unit_cell) {
636            int y_coor1 , y_coor2;
637            
638                 if (MI_NPIXELS(mi) > 2)
639                         XSetForeground(display, cryst->gc, MI_PIXEL(mi, NRAND(MI_NPIXELS(mi))));
640                 else
641                         XSetForeground(display, cryst->gc, MI_WHITE_PIXEL(mi));
642                 if (cryst->grid_cell) {
643                         int         inx, iny;
644
645                    if ( cryst->invert )
646                      y_coor1 = y_coor2 = cryst->win_height - cryst->offset_h;
647                    else
648                      y_coor1 = y_coor2 = cryst->offset_h;
649                         XDrawLine(display, window, cryst->gc, cryst->offset_w,
650                                   y_coor1, cryst->offset_w + cryst->nx * cryst->a,
651                                   y_coor2);
652                    if ( cryst->invert )
653                      {
654                         y_coor1 = cryst->win_height - cryst->offset_h;
655                         y_coor2 = cryst->win_height - (int) (cryst->ny *
656                                                              cryst->b *
657                                          cos((cryst->gamma - 90) * PI_RAD)) -
658                           cryst->offset_h;
659                      }
660                    else
661                      {
662                         y_coor1 = cryst->offset_h;
663                         y_coor2 = (int) (cryst->ny * cryst->b *
664                                          cos((cryst->gamma - 90) * PI_RAD)) +
665                           cryst->offset_h;
666                      }
667                         XDrawLine(display, window, cryst->gc, cryst->offset_w,
668                                   y_coor1, (int) (cryst->offset_w - cryst->ny * cryst->b *
669                                           sin((cryst->gamma - 90) * PI_RAD)),
670                                   y_coor2);
671                         inx = cryst->nx;
672                         for (iny = 1; iny <= cryst->ny; iny++) {
673                    if ( cryst->invert )
674                      {
675                         y_coor1 = cryst->win_height -
676                           (int) (iny * cryst->b * cos((cryst->gamma - 90) *
677                                                   PI_RAD)) - cryst->offset_h;
678                         y_coor2 = cryst->win_height -
679                           (int) (iny * cryst->b * cos((cryst->gamma - 90) *
680                                                       PI_RAD)) -
681                           cryst->offset_h;
682                      }
683                    else
684                      {
685                         y_coor1 = (int) (iny * cryst->b * cos((cryst->gamma - 90) *
686                                                   PI_RAD)) + cryst->offset_h;
687                         y_coor2 = (int) (iny * cryst->b * cos((cryst->gamma - 90) * PI_RAD)) +
688                                           cryst->offset_h;
689                      }
690                                 XDrawLine(display, window, cryst->gc,
691                                           (int) (cryst->offset_w +
692                                      inx * cryst->a - (int) (iny * cryst->b *
693                                          sin((cryst->gamma - 90) * PI_RAD))),
694                                           y_coor1,
695                                     (int) (cryst->offset_w - iny * cryst->b *
696                                            sin((cryst->gamma - 90) * PI_RAD)),
697                                           y_coor2);
698                         }
699                         iny = cryst->ny;
700                         for (inx = 1; inx <= cryst->nx; inx++) {
701                            if ( cryst->invert )
702                              {
703                                 y_coor1 =cryst->win_height -
704                                   (int) (iny * cryst->b *
705                                                 cos((cryst->gamma - 90) *
706                                                     PI_RAD)) - cryst->offset_h;
707                                 y_coor2 =cryst->win_height - cryst->offset_h;
708                              }
709                            else
710                              {
711                                 y_coor1 =(int) (iny * cryst->b *
712                                                 cos((cryst->gamma - 90) *
713                                                     PI_RAD)) + cryst->offset_h;
714                                 y_coor2 =cryst->offset_h;
715                              }
716                                 XDrawLine(display, window, cryst->gc,
717                                           (int) (cryst->offset_w +
718                                      inx * cryst->a - (int) (iny * cryst->b *
719                                          sin((cryst->gamma - 90) * PI_RAD))),
720                                           y_coor1,
721                                           cryst->offset_w + inx * cryst->a,
722                                           y_coor2);
723                         }
724                 } else {
725                         int         inx, iny;
726
727                         inx = NRAND(cryst->nx);
728                         iny = NRAND(cryst->ny);
729                    if ( cryst->invert )
730                      {
731                         y_coor1 =cryst->win_height -
732                           (int) (iny * cryst->b *
733                                                   cos((cryst->gamma - 90) *
734                                                       PI_RAD)) -
735                           cryst->offset_h;
736                         y_coor2 =cryst->win_height -
737                           (int) ( ( iny + 1 ) * cryst->b *
738                                                   cos((cryst->gamma - 90) *
739                                                       PI_RAD)) -
740                           cryst->offset_h;
741                      }
742                    else
743                      {
744                         y_coor1 =(int) (iny * cryst->b *
745                                                   cos((cryst->gamma - 90) *
746                                                       PI_RAD)) +
747                           cryst->offset_h;
748                         y_coor2 =(int) (( iny + 1 ) * cryst->b *
749                                                   cos((cryst->gamma - 90) *
750                                                       PI_RAD)) +
751                           cryst->offset_h;
752                      }
753                         XDrawLine(display, window, cryst->gc,
754                                   cryst->offset_w + inx * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
755                                   y_coor1,
756                                   cryst->offset_w + (inx + 1) * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
757                                   y_coor1);
758                         XDrawLine(display, window, cryst->gc,
759                                   cryst->offset_w + inx * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
760                                   y_coor1,
761                                   cryst->offset_w + inx * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
762                                   y_coor2);
763                         XDrawLine(display, window, cryst->gc,
764                                   cryst->offset_w + (inx + 1) * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
765                                   y_coor1,
766                                   cryst->offset_w + (inx + 1) * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
767                                   y_coor2);
768                         XDrawLine(display, window, cryst->gc,
769                                   cryst->offset_w + inx * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
770                                   y_coor2,
771                                   cryst->offset_w + (inx + 1) * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
772                                   y_coor2);
773                 }
774         }
775         for (i = 0; i < cryst->num_atom; i++) {
776                 crystalatom *atom0;
777
778                 atom0 = &cryst->atom[i];
779                 if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
780                         XSetForeground(display, cryst->gc, cryst->colors[atom0->colour].pixel);
781                 } else {
782                         XSetForeground(display, cryst->gc, atom0->colour);
783                 }
784                 crystal_drawatom(mi, atom0);
785         }
786         XSetFunction(display, cryst->gc, GXcopy);
787 }
788
789 void
790 release_crystal(ModeInfo * mi)
791 {
792         Display    *display = MI_DISPLAY(mi);
793
794         if (crystals != NULL) {
795                 int         screen;
796
797                 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
798                         crystalstruct *cryst = &crystals[screen];
799
800                         if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
801                                 MI_WHITE_PIXEL(mi) = cryst->whitepixel;
802                                 MI_BLACK_PIXEL(mi) = cryst->blackpixel;
803 #ifndef STANDALONE
804                                 MI_FG_PIXEL(mi) = cryst->fg;
805                                 MI_BG_PIXEL(mi) = cryst->bg;
806 #endif
807                                 if (cryst->colors && cryst->ncolors && !cryst->no_colors)
808                                         free_colors(display, cryst->cmap, cryst->colors, cryst->ncolors);
809                                 if (cryst->colors)
810                                         (void) free((void *) cryst->colors);
811 #if 0 /* #### wrong! -jwz */
812                                 XFreeColormap(display, cryst->cmap);
813 #endif
814                         }
815                         if (cryst->gc != NULL)
816                                 XFreeGC(display, cryst->gc);
817                         if (cryst->atom != NULL)
818                                 (void) free((void *) cryst->atom);
819                 }
820                 (void) free((void *) crystals);
821                 crystals = NULL;
822         }
823 }
824
825 void
826 init_crystal(ModeInfo * mi)
827 {
828         Display    *display = MI_DISPLAY(mi);
829         Window      window = MI_WINDOW(mi);
830         crystalstruct *cryst;
831         int         i, max_atoms, size_atom, neqv;
832         int         cell_min;
833
834 #define MIN_CELL 200
835
836 /* initialize */
837         if (crystals == NULL) {
838                 if ((crystals = (crystalstruct *) calloc(MI_NUM_SCREENS(mi),
839                                             sizeof (crystalstruct))) == NULL)
840                         return;
841         }
842         cryst = &crystals[MI_SCREEN(mi)];
843
844         if (!cryst->gc) {
845                 if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
846                         XColor      color;
847
848 #ifndef STANDALONE
849                         extern char *background;
850                         extern char *foreground;
851
852                         cryst->fg = MI_FG_PIXEL(mi);
853                         cryst->bg = MI_BG_PIXEL(mi);
854 #endif
855                         cryst->blackpixel = MI_BLACK_PIXEL(mi);
856                         cryst->whitepixel = MI_WHITE_PIXEL(mi);
857 #if 0 /* #### wrong! -jwz */
858                         cryst->cmap = XCreateColormap(display, window,
859                                                    MI_VISUAL(mi), AllocNone);
860                         XSetWindowColormap(display, window, cryst->cmap);
861 #else
862             cryst->cmap = mi->xgwa.colormap;
863 #endif
864                         (void) XParseColor(display, cryst->cmap, "black", &color);
865                         (void) XAllocColor(display, cryst->cmap, &color);
866                         MI_BLACK_PIXEL(mi) = color.pixel;
867                         (void) XParseColor(display, cryst->cmap, "white", &color);
868                         (void) XAllocColor(display, cryst->cmap, &color);
869                         MI_WHITE_PIXEL(mi) = color.pixel;
870 #ifndef STANDALONE
871                         (void) XParseColor(display, cryst->cmap, background, &color);
872                         (void) XAllocColor(display, cryst->cmap, &color);
873                         MI_BG_PIXEL(mi) = color.pixel;
874                         (void) XParseColor(display, cryst->cmap, foreground, &color);
875                         (void) XAllocColor(display, cryst->cmap, &color);
876                         MI_FG_PIXEL(mi) = color.pixel;
877 #endif
878                         cryst->colors = 0;
879                         cryst->ncolors = 0;
880                 }
881                 if ((cryst->gc = XCreateGC(display, MI_WINDOW(mi),
882                              (unsigned long) 0, (XGCValues *) NULL)) == None)
883                         return;
884         }
885 /* Clear Display */
886         MI_CLEARWINDOW(mi);
887         cryst->painted = False;
888         XSetFunction(display, cryst->gc, GXxor);
889
890
891 /*Set up crystal data */
892         cryst->direction = (LRAND() & 1) ? 1 : -1;
893         if (MI_IS_FULLRANDOM(mi)) {
894                 if (LRAND() & 1)
895                         cryst->unit_cell = True;
896                 else
897                         cryst->unit_cell = False;
898         } else
899                 cryst->unit_cell = unit_cell;
900         if (cryst->unit_cell) {
901                 if (MI_IS_FULLRANDOM(mi)) {
902                         if (LRAND() & 1)
903                                 cryst->grid_cell = True;
904                         else
905                                 cryst->grid_cell = False;
906                 } else
907                         cryst->grid_cell = grid_cell;
908         }
909         cryst->win_width = MI_WIDTH(mi);
910         cryst->win_height = MI_HEIGHT(mi);
911         cell_min = min(cryst->win_width / 2 + 1, MIN_CELL);
912         cell_min = min(cell_min, cryst->win_height / 2 + 1);
913         cryst->planegroup = NRAND(17);
914         cryst->invert = NRAND(2);
915         if (MI_IS_VERBOSE(mi))
916                 (void) fprintf(stdout, "Selected plane group no %d\n",
917                                cryst->planegroup + 1);
918         if (cryst->planegroup > 11)
919                 cryst->gamma = 120.0;
920         else if (cryst->planegroup < 2)
921                 cryst->gamma = 60.0 + NRAND(60);
922         else
923                 cryst->gamma = 90.0;
924         neqv = numops[2 * cryst->planegroup] - numops[2 * cryst->planegroup + 1];
925         if (centro[cryst->planegroup] == True)
926                 neqv = 2 * neqv;
927         if (primitive[cryst->planegroup] == False)
928                 neqv = 2 * neqv;
929
930
931         if (nx > 0)
932                 cryst->nx = nx;
933         else if (nx < 0)
934                 cryst->nx = NRAND(-nx) + 1;
935         else
936                 cryst->nx = DEF_NX1;
937         if (cryst->planegroup > 8)
938                 cryst->ny = cryst->nx;
939         else if (ny > 0)
940                 cryst->ny = ny;
941         else if (ny < 0)
942                 cryst->ny = NRAND(-ny) + 1;
943         else
944                 cryst->ny = DEF_NY1;
945         neqv = neqv * cryst->nx * cryst->ny;
946
947         cryst->num_atom = MI_COUNT(mi);
948         max_atoms = MI_COUNT(mi);
949         if (cryst->num_atom == 0) {
950                 cryst->num_atom = DEF_NUM_ATOM;
951                 max_atoms = DEF_NUM_ATOM;
952         } else if (cryst->num_atom < 0) {
953                 max_atoms = -cryst->num_atom;
954                 cryst->num_atom = NRAND(-cryst->num_atom) + 1;
955         }
956         if (neqv > 1)
957                 cryst->num_atom = cryst->num_atom / neqv + 1;
958
959         if (cryst->atom == NULL)
960                 cryst->atom = (crystalatom *) calloc(max_atoms, sizeof (
961                                                                crystalatom));
962
963         if (maxsize) {
964                 if (cryst->planegroup < 13) {
965                         cryst->gamma = 90.0;
966                         cryst->offset_w = 0;
967                         cryst->offset_h = 0;
968                         if (cryst->planegroup < 10) {
969                                 cryst->b = cryst->win_height;
970                                 cryst->a = cryst->win_width;
971                         } else {
972                                 cryst->b = min(cryst->win_height, cryst->win_width);
973                                 cryst->a = cryst->b;
974                         }
975                 } else {
976                         cryst->gamma = 120.0;
977                         cryst->a = (int) (cryst->win_width * 2.0 / 3.0);
978                         cryst->b = cryst->a;
979                         cryst->offset_h = (int) (cryst->b * 0.25 *
980                                           cos((cryst->gamma - 90) * PI_RAD));
981                         cryst->offset_w = (int) (cryst->b * 0.5);
982                 }
983         } else {
984                 cryst->offset_w = -1;
985                 while (cryst->offset_w < 4 || (int) (cryst->offset_w - cryst->b *
986                                     sin((cryst->gamma - 90) * PI_RAD)) < 4) {
987                         cryst->b = NRAND((int) (cryst->win_height / (cos((cryst->gamma - 90) *
988                                             PI_RAD))) - cell_min) + cell_min;
989                         if (cryst->planegroup > 8)
990                                 cryst->a = cryst->b;
991                         else
992                                 cryst->a = NRAND(cryst->win_width - cell_min) + cell_min;
993                         cryst->offset_w = (int) ((cryst->win_width - (cryst->a - cryst->b *
994                                                     sin((cryst->gamma - 90) *
995                                                         PI_RAD))) / 2.0);
996                 }
997                 cryst->offset_h = (int) ((cryst->win_height - cryst->b * cos((
998                                         cryst->gamma - 90) * PI_RAD)) / 2.0);
999                 if (!centre) {
1000                         if (cryst->offset_h > 0)
1001                                 cryst->offset_h = NRAND(2 * cryst->offset_h);
1002                         cryst->offset_w = (int) (cryst->win_width - cryst->a -
1003                                                  cryst->b *
1004                                     fabs(sin((cryst->gamma - 90) * PI_RAD)));
1005                         if (cryst->gamma > 90.0) {
1006                                 if (cryst->offset_w > 0)
1007                                         cryst->offset_w = NRAND(cryst->offset_w) +
1008                                                 (int) (cryst->b * sin((cryst->gamma - 90) * PI_RAD));
1009                                 else
1010                                         cryst->offset_w = (int) (cryst->b * sin((cryst->gamma - 90) *
1011                                                                     PI_RAD));
1012                         } else if (cryst->offset_w > 0)
1013                                 cryst->offset_w = NRAND(cryst->offset_w);
1014                         else
1015                                 cryst->offset_w = 0;
1016                 }
1017         }
1018
1019         size_atom = min((int) ((float) (cryst->a) / 40.) + 1,
1020                         (int) ((float) (cryst->b) / 40.) + 1);
1021         if (MI_SIZE(mi) < size_atom) {
1022                 if (MI_SIZE(mi) < -size_atom)
1023                         size_atom = -size_atom;
1024                 else
1025                         size_atom = MI_SIZE(mi);
1026         }
1027         cryst->a = cryst->a / cryst->nx;
1028         cryst->b = cryst->b / cryst->ny;
1029         if (cryst->unit_cell) {
1030            int y_coor1 , y_coor2;
1031            
1032                 if (MI_NPIXELS(mi) > 2)
1033                         XSetForeground(display, cryst->gc, MI_PIXEL(mi, NRAND(MI_NPIXELS(mi))));
1034                 else
1035                         XSetForeground(display, cryst->gc, MI_WHITE_PIXEL(mi));
1036                 if (cryst->grid_cell) {
1037                         int         inx, iny;
1038
1039                    if ( cryst->invert )
1040                      y_coor1 = y_coor2 = cryst->win_height - cryst->offset_h;
1041                    else
1042                      y_coor1 = y_coor2 = cryst->offset_h;
1043                         XDrawLine(display, window, cryst->gc, cryst->offset_w,
1044                                   y_coor1, cryst->offset_w + cryst->nx * cryst->a,
1045                                   y_coor2);
1046                    if ( cryst->invert )
1047                      {
1048                         y_coor1 = cryst->win_height - cryst->offset_h;
1049                         y_coor2 = cryst->win_height - (int) (cryst->ny *
1050                                                              cryst->b *
1051                                          cos((cryst->gamma - 90) * PI_RAD)) -
1052                           cryst->offset_h;
1053                      }
1054                    else
1055                      {
1056                         y_coor1 = cryst->offset_h;
1057                         y_coor2 = (int) (cryst->ny * cryst->b *
1058                                          cos((cryst->gamma - 90) * PI_RAD)) +
1059                           cryst->offset_h;
1060                      }
1061                         XDrawLine(display, window, cryst->gc, cryst->offset_w,
1062                                   y_coor1, (int) (cryst->offset_w - cryst->ny * cryst->b *
1063                                           sin((cryst->gamma - 90) * PI_RAD)),
1064                                   y_coor2);
1065                         inx = cryst->nx;
1066                         for (iny = 1; iny <= cryst->ny; iny++) {
1067                    if ( cryst->invert )
1068                      {
1069                         y_coor1 = cryst->win_height -
1070                           (int) (iny * cryst->b * cos((cryst->gamma - 90) *
1071                                                   PI_RAD)) - cryst->offset_h;
1072                         y_coor2 = cryst->win_height -
1073                           (int) (iny * cryst->b * cos((cryst->gamma - 90) *
1074                                                       PI_RAD)) -
1075                           cryst->offset_h;
1076                      }
1077                    else
1078                      {
1079                         y_coor1 = (int) (iny * cryst->b * cos((cryst->gamma - 90) *
1080                                                   PI_RAD)) + cryst->offset_h;
1081                         y_coor2 = (int) (iny * cryst->b * cos((cryst->gamma - 90) * PI_RAD)) +
1082                                           cryst->offset_h;
1083                      }
1084                                 XDrawLine(display, window, cryst->gc,
1085                                           (int) (cryst->offset_w +
1086                                      inx * cryst->a - (int) (iny * cryst->b *
1087                                          sin((cryst->gamma - 90) * PI_RAD))),
1088                                           y_coor1,
1089                                     (int) (cryst->offset_w - iny * cryst->b *
1090                                            sin((cryst->gamma - 90) * PI_RAD)),
1091                                           y_coor2);
1092                         }
1093                         iny = cryst->ny;
1094                         for (inx = 1; inx <= cryst->nx; inx++) {
1095                            if ( cryst->invert )
1096                              {
1097                                 y_coor1 =cryst->win_height -
1098                                   (int) (iny * cryst->b *
1099                                                 cos((cryst->gamma - 90) *
1100                                                     PI_RAD)) - cryst->offset_h;
1101                                 y_coor2 =cryst->win_height - cryst->offset_h;
1102                              }
1103                            else
1104                              {
1105                                 y_coor1 =(int) (iny * cryst->b *
1106                                                 cos((cryst->gamma - 90) *
1107                                                     PI_RAD)) + cryst->offset_h;
1108                                 y_coor2 =cryst->offset_h;
1109                              }
1110                                 XDrawLine(display, window, cryst->gc,
1111                                           (int) (cryst->offset_w +
1112                                      inx * cryst->a - (int) (iny * cryst->b *
1113                                          sin((cryst->gamma - 90) * PI_RAD))),
1114                                           y_coor1,
1115                                           cryst->offset_w + inx * cryst->a,
1116                                           y_coor2);
1117                         }
1118                 } else {
1119                         int         inx, iny;
1120
1121                         inx = NRAND(cryst->nx);
1122                         iny = NRAND(cryst->ny);
1123                    if ( cryst->invert )
1124                      {
1125                         y_coor1 =cryst->win_height -
1126                           (int) (iny * cryst->b *
1127                                                   cos((cryst->gamma - 90) *
1128                                                       PI_RAD)) -
1129                           cryst->offset_h;
1130                         y_coor2 =cryst->win_height -
1131                           (int) ( ( iny + 1 ) * cryst->b *
1132                                                   cos((cryst->gamma - 90) *
1133                                                       PI_RAD)) -
1134                           cryst->offset_h;
1135                      }
1136                    else
1137                      {
1138                         y_coor1 =(int) (iny * cryst->b *
1139                                                   cos((cryst->gamma - 90) *
1140                                                       PI_RAD)) +
1141                           cryst->offset_h;
1142                         y_coor2 =(int) (( iny + 1 ) * cryst->b *
1143                                                   cos((cryst->gamma - 90) *
1144                                                       PI_RAD)) +
1145                           cryst->offset_h;
1146                      }
1147                         XDrawLine(display, window, cryst->gc,
1148                                   cryst->offset_w + inx * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
1149                                   y_coor1,
1150                                   cryst->offset_w + (inx + 1) * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
1151                                   y_coor1);
1152                         XDrawLine(display, window, cryst->gc,
1153                                   cryst->offset_w + inx * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
1154                                   y_coor1,
1155                                   cryst->offset_w + inx * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
1156                                   y_coor2);
1157                         XDrawLine(display, window, cryst->gc,
1158                                   cryst->offset_w + (inx + 1) * cryst->a - (int) (iny * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
1159                                   y_coor1,
1160                                   cryst->offset_w + (inx + 1) * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
1161                                   y_coor2);
1162                         XDrawLine(display, window, cryst->gc,
1163                                   cryst->offset_w + inx * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
1164                                   y_coor2,
1165                                   cryst->offset_w + (inx + 1) * cryst->a - (int) ((iny + 1) * cryst->b * sin((cryst->gamma - 90) * PI_RAD)),
1166                                   y_coor2);
1167                 }
1168         }
1169         if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
1170 /* Set up colour map */
1171                 if (cryst->colors && cryst->ncolors && !cryst->no_colors)
1172                         free_colors(display, cryst->cmap, cryst->colors, cryst->ncolors);
1173                 if (cryst->colors)
1174                         (void) free((void *) cryst->colors);
1175                 cryst->colors = 0;
1176                 cryst->ncolors = MI_NCOLORS(mi);
1177                 if (cryst->ncolors < 2)
1178                         cryst->ncolors = 2;
1179                 if (cryst->ncolors <= 2)
1180                         cryst->mono_p = True;
1181                 else
1182                         cryst->mono_p = False;
1183
1184                 if (cryst->mono_p)
1185                         cryst->colors = 0;
1186                 else
1187                         cryst->colors = (XColor *) malloc(sizeof (*cryst->colors) * (cryst->ncolors + 1));
1188                 cryst->cycle_p = has_writable_cells(mi->xgwa.screen, MI_VISUAL(mi));
1189                 if (cryst->cycle_p) {
1190                         if (MI_IS_FULLRANDOM(mi)) {
1191                                 if (!NRAND(8))
1192                                         cryst->cycle_p = False;
1193                                 else
1194                                         cryst->cycle_p = True;
1195                         } else {
1196                                 cryst->cycle_p = cycle_p;
1197                         }
1198                 }
1199                 if (!cryst->mono_p) {
1200                         if (!(LRAND() % 10))
1201                                 make_random_colormap(MI_DISPLAY(mi), MI_VISUAL(mi), cryst->cmap, cryst->colors, &cryst->ncolors,
1202                                                 True, True, &cryst->cycle_p, True);
1203                         else if (!(LRAND() % 2))
1204                                 make_uniform_colormap(MI_DISPLAY(mi), MI_VISUAL(mi), cryst->cmap, cryst->colors, &cryst->ncolors,
1205                                                       True, &cryst->cycle_p, True);
1206                         else
1207                                 make_smooth_colormap(MI_DISPLAY(mi), MI_VISUAL(mi), cryst->cmap, cryst->colors, &cryst->ncolors,
1208                                                      True, &cryst->cycle_p, True);
1209                 }
1210 #if 0 /* #### wrong! -jwz */
1211                 XInstallColormap(display, cryst->cmap);
1212 #endif
1213                 if (cryst->ncolors < 2) {
1214                         cryst->ncolors = 2;
1215                         cryst->no_colors = True;
1216                 } else
1217                         cryst->no_colors = False;
1218                 if (cryst->ncolors <= 2)
1219                         cryst->mono_p = True;
1220
1221                 if (cryst->mono_p)
1222                         cryst->cycle_p = False;
1223
1224         }
1225         for (i = 0; i < cryst->num_atom; i++) {
1226                 crystalatom *atom0;
1227
1228                 atom0 = &cryst->atom[i];
1229                 if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
1230                         if (cryst->ncolors > 2)
1231                                 atom0->colour = NRAND(cryst->ncolors - 2) + 2;
1232                         else
1233                                 atom0->colour = 1;      /* Just in case */
1234                         XSetForeground(display, cryst->gc, cryst->colors[atom0->colour].pixel);
1235                 } else {
1236                         if (MI_NPIXELS(mi) > 2)
1237                                 atom0->colour = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)));
1238                         else
1239                                 atom0->colour = 1;      /*Xor'red so WHITE may not be appropriate */
1240                         XSetForeground(display, cryst->gc, atom0->colour);
1241                 }
1242                 atom0->x0 = NRAND(cryst->a);
1243                 atom0->y0 = NRAND(cryst->b);
1244                 atom0->velocity[0] = NRAND(7) - 3;
1245                 atom0->velocity[1] = NRAND(7) - 3;
1246                 atom0->velocity_a = (NRAND(7) - 3) * PI_RAD;
1247                 atom0->angle = NRAND(90) * PI_RAD;
1248                 atom0->at_type = NRAND(3);
1249                 if (size_atom == 0)
1250                         atom0->size_at = DEF_SIZ_ATOM;
1251                 else if (size_atom > 0)
1252                         atom0->size_at = size_atom;
1253                 else
1254                         atom0->size_at = NRAND(-size_atom) + 1;
1255                 atom0->size_at++;
1256                 if (atom0->at_type == 2)
1257                         atom0->num_point = 3;
1258                 else
1259                         atom0->num_point = 4;
1260                 crystal_setupatom(atom0, cryst->gamma);
1261                 crystal_drawatom(mi, atom0);
1262         }
1263         XSync(display, False);
1264         XSetFunction(display, cryst->gc, GXcopy);
1265 }