source: trunk/third/xscreensaver/hacks/crystal.c @ 20148

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