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