17d2081c04b2ffbc723f4643691a6fcce69c24a4
[alexxy/gromacs.git] / src / programs / view / xutil.cpp
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-2013, The GROMACS development team.
6  * Copyright (c) 2013,2014,2015,2017,2019, by the GROMACS development team, led by
7  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8  * and including many others, as listed in the AUTHORS file in the
9  * top-level source directory and at http://www.gromacs.org.
10  *
11  * GROMACS is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation; either version 2.1
14  * of the License, or (at your option) any later version.
15  *
16  * GROMACS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with GROMACS; if not, see
23  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25  *
26  * If you want to redistribute modifications to GROMACS, please
27  * consider that scientific software is very special. Version
28  * control is crucial - bugs must be traceable. We will be happy to
29  * consider code for inclusion in the official distribution, but
30  * derived work must not be called official GROMACS. Details are found
31  * in the README & COPYING files - if they are missing, get the
32  * official version at http://www.gromacs.org.
33  *
34  * To help us fund GROMACS development, we humbly ask that you cite
35  * the research papers on the package. Check out http://www.gromacs.org.
36  */
37 #include "gmxpre.h"
38
39 #include "xutil.h"
40
41 #include <cstdio>
42 #include <cstring>
43
44 #include "gromacs/utility/cstringutil.h"
45 #include "gromacs/utility/smalloc.h"
46
47 #include "Xstuff.h"
48
49 int CheckWin(Window win, const char* file, int line)
50 {
51     typedef struct
52     {
53         Window      n;
54         const char* s;
55     } t_winerr;
56     t_winerr winerr[] = { { BadAlloc, "Bad Alloc" },   { BadColor, "Bad Color" },
57                           { BadCursor, "Bad Cursor" }, { BadMatch, "Bad Match" },
58                           { BadPixmap, "Bad Pixmap" }, { BadValue, "Bad Value" },
59                           { BadWindow, "Bad Window" } };
60 #define NERR (sizeof(winerr) / sizeof(winerr[0]))
61     unsigned int i;
62
63     for (i = 0; (i < NERR); i++)
64     {
65         if (win == winerr[i].n)
66         {
67             std::fprintf(stderr, "%s", winerr[i].s);
68             break;
69         }
70     }
71     if (i == NERR)
72     {
73         return 1;
74     }
75
76     std::fprintf(stderr, " in file %s, line %d\n", file, line);
77     return 0;
78 }
79
80 void LightBorder(Display* disp, Window win, unsigned long color)
81 {
82     XSetWindowAttributes attributes;
83
84     attributes.border_pixel = color;
85     XChangeWindowAttributes(disp, win, CWBorderPixel, &attributes);
86 }
87
88 void SpecialTextInRect(t_x11*       x11,
89                        XFontStruct* font,
90                        Drawable     win,
91                        const char*  s,
92                        int          x,
93                        int          y,
94                        int          width,
95                        int          height,
96                        eXPos        eX,
97                        eYPos        eY)
98 {
99     int          fw, fh, x0, y0;
100     XFontStruct* f;
101
102     if (font)
103     {
104         XSetFont(x11->disp, x11->gc, font->fid);
105         f = font;
106     }
107     else
108     {
109         f = x11->font;
110     }
111
112     fw = XTextWidth(f, s, std::strlen(s));
113     fh = XTextHeight(f);
114     switch (eX)
115     {
116         case eXLeft: x0 = x; break;
117         case eXRight: x0 = x + width - fw; break;
118         case eXCenter:
119         default: x0 = x + (width - fw) / 2; break;
120     }
121     switch (eY)
122     {
123         case eYTop: y0 = y + f->ascent; break;
124         case eYBottom: y0 = y + height - f->descent; break;
125         case eYCenter:
126         default: y0 = y + (height - fh) / 2 + f->ascent; break;
127     }
128     XDrawString(x11->disp, win, x11->gc, x0, y0, s, std::strlen(s));
129     if (font)
130     {
131         XSetFont(x11->disp, x11->gc, x11->font->fid);
132     }
133 }
134
135 void TextInRect(t_x11* x11, Drawable win, const char* s, int x, int y, int width, int height, eXPos eX, eYPos eY)
136 {
137     SpecialTextInRect(x11, nullptr, win, s, x, y, width, height, eX, eY);
138 }
139
140 void TextInWin(t_x11* x11, t_windata* win, const char* s, eXPos eX, eYPos eY)
141 {
142     TextInRect(x11, win->self, s, 0, 0, win->width, win->height, eX, eY);
143 }
144
145 void InitWin(t_windata* win, int x0, int y0, int w, int h, int bw, const char* text)
146 {
147     win->self   = 0;
148     win->color  = 0;
149     win->x      = x0;
150     win->y      = y0;
151     win->width  = w;
152     win->height = h;
153     win->bwidth = bw;
154     win->bFocus = false;
155     win->cursor = 0;
156     if (text)
157     {
158         win->text = gmx_strdup(text);
159     }
160     else
161     {
162         win->text = nullptr;
163     }
164 #ifdef DEBUG
165     std::printf("%s: %d x %d at %d, %d\n", text, w, h, x0, y0);
166 #endif
167 }
168
169 void FreeWin(Display* disp, t_windata* win)
170 {
171     if (win->text)
172     {
173         sfree(win->text);
174     }
175     if (win->cursor)
176     {
177         XFreeCursor(disp, win->cursor);
178     }
179 }
180
181 void ExposeWin(Display* disp, Window win)
182 {
183     XEvent event;
184
185     event.type               = Expose;
186     event.xexpose.send_event = True;
187     event.xexpose.window     = win;
188     event.xexpose.x          = 0;
189     event.xexpose.y          = 0;
190     event.xexpose.width      = 1000;
191     event.xexpose.height     = 1000;
192     event.xexpose.count      = 0;
193     XSendEvent(disp, win, False, ExposureMask, &event);
194 }
195
196 void XDrawRoundRect(Display* disp, Window win, GC gc, int x, int y, int w, int h)
197 {
198 #define RAD (OFFS_X / 2)
199 #define SetPoint(pn, x0, y0) \
200     pn.x = x0;               \
201     pn.y = y0
202
203     if ((w < 10) || (h < 10))
204     {
205         XDrawRectangle(disp, win, gc, x, y, w, h);
206     }
207     else
208     {
209         XPoint p[9];
210
211         SetPoint(p[0], x + RAD, y);
212         SetPoint(p[1], w - 2 * RAD, 0);
213         SetPoint(p[2], RAD, RAD);
214         SetPoint(p[3], 0, h - 2 * RAD);
215         SetPoint(p[4], -RAD, RAD);
216         SetPoint(p[5], 2 * RAD - w, 0);
217         SetPoint(p[6], -RAD, -RAD);
218         SetPoint(p[7], 0, 2 * RAD - h);
219         SetPoint(p[8], RAD, -RAD);
220         XDrawLines(disp, win, gc, p, 9, CoordModePrevious);
221     }
222 }
223
224 void RoundRectWin(Display* disp, GC gc, t_windata* win, int offsx, int offsy, unsigned long color)
225 {
226     XSetLineAttributes(disp, gc, 1, LineOnOffDash, CapButt, JoinRound);
227     XSetForeground(disp, gc, color);
228     XDrawRoundRect(disp, win->self, gc, offsx, offsy, win->width - 2 * offsx - 1,
229                    win->height - 2 * offsy - 1);
230     XSetLineAttributes(disp, gc, 1, LineSolid, CapButt, JoinRound);
231 }
232
233 void RectWin(Display* disp, GC gc, t_windata* win, unsigned long color)
234 {
235     int bw = 1; /*2*w.bwidth;*/
236
237     XSetForeground(disp, gc, color);
238     XDrawRoundRect(disp, win->self, gc, 0, 0, win->width - bw, win->height - bw);
239 }
240
241 typedef struct t_mpos
242 {
243     int            x, y;
244     struct t_mpos* prev;
245 } t_mpos;
246
247 static t_mpos* mpos = nullptr;
248
249 void PushMouse(Display* disp, Window dest, int x, int y)
250 {
251     Window       root, child;
252     int          root_x, root_y;
253     int          win_x, win_y;
254     unsigned int keybut;
255     t_mpos*      newpos;
256
257     snew(newpos, 1);
258     XQueryPointer(disp, DefaultRootWindow(disp), &root, &child, &root_x, &root_y, &win_x, &win_y, &keybut);
259     newpos->x    = root_x;
260     newpos->y    = root_y;
261     newpos->prev = mpos;
262     mpos         = newpos;
263     XWarpPointer(disp, None, dest, 0, 0, 0, 0, x, y);
264 #ifdef DEBUG
265     std::fprintf(stderr, "Pushmouse %d, %d\n", x, y);
266 #endif
267 }
268
269 void PopMouse(Display* disp)
270 {
271     t_mpos* old;
272
273     old = mpos;
274     if (!old)
275     {
276         return;
277     }
278
279     XWarpPointer(disp, None, DefaultRootWindow(disp), 0, 0, 0, 0, old->x, old->y);
280 #ifdef DEBUG
281     std::fprintf(stderr, "Popmouse %d, %d\n", old->x, old->y);
282 #endif
283     mpos = old->prev;
284     sfree(old);
285 }
286
287 bool HelpPressed(XEvent* event)
288 {
289 #define BUFSIZE 24
290     char           buf[BUFSIZE + 1];
291     XComposeStatus compose;
292     KeySym         keysym;
293
294     (void)XLookupString(&(event->xkey), buf, BUFSIZE, &keysym, &compose);
295
296     return (keysym == XK_F1);
297 }
298
299 bool GrabOK(FILE* out, int err)
300 {
301     switch (err)
302     {
303         case GrabSuccess: return true;
304         case GrabNotViewable: std::fprintf(out, "GrabNotViewable\n"); break;
305         case AlreadyGrabbed: std::fprintf(out, "AlreadyGrabbed\n"); break;
306         case GrabFrozen: std::fprintf(out, "GrabFrozen\n"); break;
307         case GrabInvalidTime: std::fprintf(out, "GrabInvalidTime\n"); break;
308         default: break;
309     }
310     return false;
311 }