fddc62c4d0c934c1c94d98272276940cd38c7990
[alexxy/gromacs.git] / src / ngmx / g_showcol.c
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
9  *                        VERSION 3.2.0
10  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12  * Copyright (c) 2001-2004, The GROMACS development team,
13  * check out http://www.gromacs.org for more information.
14
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * If you want to redistribute modifications, please consider that
21  * scientific software is very special. Version control is crucial -
22  * bugs must be traceable. We will be happy to consider code for
23  * inclusion in the official distribution, but derived work must not
24  * be called official GROMACS. Details are found in the README & COPYING
25  * files - if they are missing, get the official version at www.gromacs.org.
26  *
27  * To help us fund GROMACS development, we humbly ask that you cite
28  * the papers on the package - you can find them in the top README file.
29  *
30  * For more info, check our website at http://www.gromacs.org
31  *
32  * And Hey:
33  * Gyas ROwers Mature At Cryogenic Speed
34  */
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #include <math.h>
40 #include <smalloc.h>
41 #include <sysstuff.h>
42 #include <string2.h>
43 #include <Xstuff.h>
44 #include "xutil.h"
45 #include "futil.h"
46
47 typedef struct {
48     XColor    xc;
49     t_windata wd;
50 } t_col;
51
52 typedef struct {
53     t_windata  wd;
54     t_windata  but;
55     int        ncol;
56     t_col     *col;
57 } t_sc;
58
59 static gmx_bool ColCallBack(struct t_x11 *x11, XEvent *event, Window w, void *data)
60 {
61     t_col     *col;
62     XColor    *xc;
63     int        r, g, b;
64     t_windata *wd;
65
66     col = (t_col *)data;
67     xc  = &(col->xc);
68     wd  = &(col->wd);
69     switch (event->type)
70     {
71         case ButtonPress:
72             r = xc->red >> 8;
73             g = xc->green >> 8;
74             b = xc->blue >> 8;
75             printf("%6d%6d%6d\t\t%-20s\n", r, g, b, wd->text);
76             break;
77     }
78     return FALSE;
79 }
80
81 static gmx_bool BCallBack(struct t_x11 *x11, XEvent *event, Window w, void *data)
82 {
83     t_sc  *sc;
84
85     sc = (t_sc *)data;
86     switch (event->type)
87     {
88         case Expose:
89             XSetForeground(x11->disp, x11->gc, sc->col[sc->ncol-1].xc.pixel);
90             TextInWin(x11, &sc->but, sc->but.text, eXCenter, eYCenter);
91             break;
92         case ConfigureNotify:
93             sc->but.width  = event->xconfigure.width;
94             sc->but.height = event->xconfigure.height;
95             break;
96         case EnterNotify:
97             LightBorder(x11->disp, sc->but.self, sc->col[sc->ncol-1].xc.pixel);
98             break;
99         case LeaveNotify:
100             LightBorder(x11->disp, sc->but.self, sc->col[0].xc.pixel);
101             break;
102         case ButtonPress:
103             x11->UnRegisterCallback(x11, sc->wd.self);
104             x11->UnRegisterCallback(x11, sc->but.self);
105             return TRUE;
106     }
107     return FALSE;
108 }
109
110 static gmx_bool scCallBack(struct t_x11 *x11, XEvent *event, Window w, void *data)
111 {
112     t_sc  *sc;
113     int    i;
114     int    nx, ny, X, Y, Dx, Dy, th;
115     float  x, y, dx, dy;
116
117     th = XTextHeight(x11->font)+6;
118     sc = (t_sc *)data;
119     switch (event->type)
120     {
121         case ConfigureNotify:
122             x = sc->wd.width = event->xconfigure.width;
123             y = sc->wd.height = event->xconfigure.height-th;
124             if ((x >= 100) && (y >= 100))
125             {
126 #ifdef DEBUG
127                 printf("Disp: %x, But: %x, Font: %x x: %d, th: %d\n",
128                        x11->disp, sc->but.self, x11->font, (int)x, th);
129 #endif
130                 XResizeWindow(x11->disp, sc->but.self, (int)x-4, th-4);
131                 nx = sqrt(sc->ncol);
132                 ny = sc->ncol/nx;
133                 while (nx*ny < sc->ncol)
134                 {
135                     ny++;
136                 }
137                 dx = ((float)x) / nx;
138                 dy = ((float)y) / ny;
139                 for (i = 0; (i < sc->ncol); i++)
140                 {
141                     X  = x = (i%nx) * dx;
142                     Y  = y = (i/nx) * dy;
143                     Dx = (int)(x+dx)-X;
144                     Dy = (int)(y+dy)-Y;
145                     XMoveWindow(x11->disp, sc->col[i].wd.self, X, th+Y);
146                     XResizeWindow(x11->disp, sc->col[i].wd.self, Dx, Dy);
147                 }
148             }
149             break;
150     }
151     return FALSE;
152 }
153
154 static int col_comp(const void *c1, const void *c2)
155 {
156     XColor *x1, *x2;
157     int     dr, dg;
158     int     diff;
159
160     x1 = &(((t_col *)c1)->xc);
161     x2 = &(((t_col *)c2)->xc);
162
163     /* sort on intensity */
164     diff = (x1->red+x1->green+x1->blue)-(x2->red+x2->green+x2->blue);
165
166     if (diff == 0)
167     {
168         if ((dr = (x1->red-x2->red)) != 0)
169         {
170             return dr;
171         }
172         if ((dg = (x1->green-x2->green)) != 0)
173         {
174             return dg;
175         }
176         return x1->blue-x2->blue;
177     }
178     else
179     {
180         return diff;
181     }
182 }
183
184 static void read_col(t_x11 *x11, t_sc *sc, char *rgb)
185 {
186     FILE   *fp;
187     char    buf[STRLEN], name[STRLEN], *dummy;
188     int     i, j;
189     int     r, g, b;
190     XColor  xc, exact;
191     t_col  *cols;
192
193     if ((fp = fopen(rgb, "r")) == NULL)
194     {
195         perror(rgb);
196         exit(1);
197     }
198     do
199     {
200         dummy = NULL;
201         if (fscanf(fp, "%d%d%d", &r, &g, &b) == 3)
202         {
203             dummy = fgets2(buf, STRLEN-1, fp);
204             if (dummy)
205             {
206                 trim(buf);
207                 /* Filter out colours with names of two words */
208                 sscanf(buf, "%s", name);
209                 /* Filter out duplicate colours (grey and gray) */
210                 if (strstr(name, "gray") == 0)
211                 {
212                     if (XAllocNamedColor(x11->disp, x11->cmap, name, &xc, &exact))
213                     {
214                         srenew(sc->col, ++sc->ncol);
215                         sc->col[sc->ncol-1].xc = xc;
216 #ifdef DEBUG
217                         printf("color %3d: %s\n", sc->ncol, buf);
218 #endif
219                         InitWin(&(sc->col[sc->ncol-1].wd), 0, 0, 1, 1, 0, name);
220                     }
221                 }
222             }
223         }
224     }
225     while (dummy);
226     fclose(fp);
227     if (sc->ncol)
228     {
229         qsort(sc->col, sc->ncol, sizeof(sc->col[0]), col_comp);
230     }
231     /* Now filter out doubles */
232     cols = &(sc->col[0]);
233     for (i = 1, j = 0; (i < sc->ncol); i++)
234     {
235         if ((cols[i].xc.red   != cols[j].xc.red) ||
236             (cols[i].xc.green != cols[j].xc.green) ||
237             (cols[i].xc.blue  != cols[j].xc.blue))
238         {
239             j++;
240             cols[j] = cols[i];
241         }
242     }
243     sc->ncol = j;
244 }
245
246 static t_sc *init_sc(t_x11 *x11, Window Parent, char *rgb)
247 {
248     t_sc   *sc;
249     Window  w;
250     int     i;
251
252     snew(sc, 1);
253     InitWin(&sc->wd, 0, 0, 400, 300, 1, "Show Colours");
254     sc->wd.self = XCreateSimpleWindow(x11->disp, Parent, sc->wd.x, sc->wd.y,
255                                       sc->wd.width, sc->wd.height,
256                                       sc->wd.bwidth, WHITE, BLACK);
257     x11->RegisterCallback(x11, sc->wd.self, Parent, scCallBack, sc);
258     x11->SetInputMask(x11, sc->wd.self, ButtonPressMask | ExposureMask |
259                       StructureNotifyMask);
260     InitWin(&sc->but, 0, 0, sc->wd.width-2, XTextHeight(x11->font)+2, 1, "Quit");
261     sc->but.self = XCreateSimpleWindow(x11->disp, sc->wd.self, sc->but.x, sc->but.y,
262                                        sc->but.width, sc->but.height,
263                                        sc->but.bwidth, BLACK, BLACK);
264     x11->RegisterCallback(x11, sc->but.self, sc->but.self, BCallBack, sc);
265     x11->SetInputMask(x11, sc->but.self, ButtonPressMask | ExposureMask |
266                       StructureNotifyMask | EnterWindowMask |
267                       LeaveWindowMask);
268
269     read_col(x11, sc, rgb);
270     fprintf(stderr, "%d colors found\n", sc->ncol);
271     fprintf(stderr, "%6s%6s%6s\t\t%-20s\n", "Red", "Green", "Blue", "name");
272     for (i = 0; (i < sc->ncol); i++)
273     {
274         sc->col[i].wd.self = w = XCreateSimpleWindow(x11->disp, sc->wd.self, 0, 0, 1, 1, 0,
275                                                      BLACK, sc->col[i].xc.pixel);
276         x11->RegisterCallback(x11, w, sc->wd.self, ColCallBack, &(sc->col[i]));
277         x11->SetInputMask(x11, w, ButtonPressMask);
278     }
279
280     return sc;
281 }
282
283 int
284 main(int argc, char *argv[])
285 {
286     t_x11 *x11;
287     t_sc  *sc;
288     char  *fn;
289
290     x11 = GetX11(&argc, argv);
291     if (argc > 1)
292     {
293         fn = argv[1];
294     }
295     else
296     {
297         fn = "/usr/lib/X11/rgb.txt";
298     }
299     if (!gmx_fexist(fn))
300     {
301         fprintf(stderr, "Usage: %s rgb.txt\n", argv[0]);
302         fprintf(stderr, "rgb.txt is usually somewhere in your X windows directories.\n");
303         exit(1);
304     }
305     sc = init_sc(x11, x11->root, fn);
306     XMapWindow(x11->disp, sc->wd.self);
307     XMapSubwindows(x11->disp, sc->wd.self);
308     x11->MainLoop(x11);
309     x11->CleanUp(x11);
310
311     return 0;
312 }