Merge branch release-4-6
[alexxy/gromacs.git] / src / programs / view / dialogs.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, 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 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #include "smalloc.h"
42 #include "sysstuff.h"
43 #include "macros.h"
44 #include "string2.h"
45 #include "x11.h"
46 #include "xdlghi.h"
47 #include "xmb.h"
48 #include "dialogs.h"
49 #include "names.h"
50 #include "nmol.h"
51 #include "manager.h"
52 #include "gromacs/fileio/futil.h"
53 #include "gmx_fatal.h"
54
55 #define MBFLAGS /* MB_APPLMODAL | */ MB_DONTSHOW
56
57 void write_gmx(t_x11 *x11, t_gmx *gmx, int mess)
58 {
59     XEvent letter;
60
61     letter.type                 = ClientMessage;
62     letter.xclient.display      = x11->disp;
63     letter.xclient.window       = gmx->wd->self;
64     letter.xclient.message_type = 0;
65     letter.xclient.format       = 32;
66     letter.xclient.data.l[0]    = mess;
67     letter.xclient.data.l[1]    = Button1;
68     XSendEvent(x11->disp, letter.xclient.window, True, 0, &letter);
69 }
70
71 static void shell_comm(const char *title, const char *script, int nsleep)
72 {
73     FILE *tfil;
74     char  command[STRLEN];
75     char  tmp[32];
76
77     strcpy(tmp, "dialogXXXXXX");
78     gmx_tmpnam(tmp);
79
80     if ((tfil = fopen(tmp, "w")) == NULL)
81     {
82         sprintf(tmp, "%ctmp%cdialogXXXXXX", DIR_SEPARATOR, DIR_SEPARATOR);
83         gmx_tmpnam(tmp);
84     }
85     else
86     {
87         fclose(tfil);
88     }
89     if ((tfil = fopen(tmp, "w")) == NULL)
90     {
91         gmx_fatal(FARGS, "Can not open tmp file %s", tmp);
92     }
93
94     fprintf(tfil, "%s\n", script);
95     fprintf(tfil, "sleep %d\n", nsleep);
96     fclose(tfil);
97
98     sprintf(command, "xterm -title %s -e sh %s", title, tmp);
99 #ifdef DEBUG
100     fprintf(stderr, "command: %s\n", command);
101 #endif
102
103 #ifdef GMX_NO_SYSTEM
104     printf("Warning-- No calls to system(3) supported on this platform.");
105     printf("Warning-- Skipping execution of 'system(\"%s\")'.", buf);
106 #else
107     if (0 != system(command))
108     {
109         gmx_fatal(FARGS, "Failed to execute command: %s", command);
110     }
111 #endif
112
113 #ifdef DEBUG
114     unlink(tmp)
115 #endif
116 }
117
118 void show_mb(t_gmx *gmx, int mb)
119 {
120     if (mb >= 0 && mb < emNR)
121     {
122         gmx->which_mb = mb;
123         ShowDlg(gmx->mboxes[mb]);
124     }
125 }
126
127 static void hide_mb(t_gmx *gmx)
128 {
129     if (gmx->which_mb >= 0 && gmx->which_mb < emNR)
130     {
131         HideDlg(gmx->mboxes[gmx->which_mb]);
132         gmx->which_mb = -1;
133     }
134 }
135
136 static void MBCallback(t_x11 * /*x11*/, int dlg_mess, int /*item_id*/,
137                        char * /*set*/, void *data)
138 {
139     t_gmx *gmx;
140
141     gmx = (t_gmx *)data;
142     if (dlg_mess == DLG_EXIT)
143     {
144         hide_mb(gmx);
145     }
146 }
147
148 static t_dlg *about_mb(t_x11 *x11, t_gmx *gmx)
149 {
150     const char *lines[] = {
151         "         G R O M A C S",
152         " Machine for Simulating Chemistry",
153         "       Copyright (c) 1992-2013",
154         "  Berk Hess, David van der Spoel, Erik Lindahl",
155         "        and many collaborators!"
156     };
157
158     return MessageBox(x11, gmx->wd->self, gmx->wd->text,
159                       asize(lines), lines, MB_OK | MB_ICONGMX | MBFLAGS,
160                       MBCallback, gmx);
161 }
162
163 static void QuitCB(t_x11 *x11, int dlg_mess, int /*item_id*/,
164                    char *set, void *data)
165 {
166     t_gmx  *gmx;
167     gmx = (t_gmx *)data;
168
169     hide_mb(gmx);
170     if (dlg_mess == DLG_EXIT)
171     {
172         if (gmx_strcasecmp("yes", set) == 0)
173         {
174             write_gmx(x11, gmx, IDTERM);
175         }
176     }
177 }
178
179 static t_dlg *quit_mb(t_x11 *x11, t_gmx *gmx)
180 {
181     const char *lines[] = {
182         " Do you really want to Quit ?"
183     };
184
185     return MessageBox(x11, gmx->wd->self, gmx->wd->text,
186                       asize(lines), lines,
187                       MB_YESNO | MB_ICONSTOP | MBFLAGS,
188                       QuitCB, gmx);
189 }
190
191 static t_dlg *help_mb(t_x11 *x11, t_gmx *gmx)
192 {
193     const char *lines[] = {
194         " Help will soon be added"
195     };
196
197     return MessageBox(x11, gmx->wd->self, gmx->wd->text,
198                       asize(lines), lines,
199                       MB_OK | MB_ICONINFORMATION | MBFLAGS,
200                       MBCallback, gmx);
201 }
202
203 static t_dlg *ni_mb(t_x11 *x11, t_gmx *gmx)
204 {
205     const char *lines[] = {
206         " This feature has not been",
207         " implemented yet."
208     };
209
210     return MessageBox(x11, gmx->wd->self, gmx->wd->text,
211                       asize(lines), lines,
212                       MB_OK | MB_ICONEXCLAMATION | MBFLAGS,
213                       MBCallback, gmx);
214 }
215
216 enum {
217     eExE, eExGrom, eExPdb, eExConf, eExNR
218 };
219
220 static void ExportCB(t_x11 *x11, int dlg_mess, int item_id,
221                      char *set, void *data)
222 {
223     bool       bOk;
224     t_gmx     *gmx;
225     t_dlg     *dlg;
226
227     gmx = (t_gmx *)data;
228     dlg = gmx->dlgs[edExport];
229     switch (dlg_mess)
230     {
231         case DLG_SET:
232             switch (item_id)
233             {
234                 case eExGrom:
235                     gmx->ExpMode = eExpGromos;
236                     break;
237                 case eExPdb:
238                     gmx->ExpMode = eExpPDB;
239                     break;
240                 default:
241                     break;
242             }
243 #ifdef DEBUG
244             fprintf(stderr, "exportcb: item_id=%d\n", item_id);
245 #endif
246             break;
247         case DLG_EXIT:
248             if ((bOk = gmx_strcasecmp("ok", set)) == 0)
249             {
250                 strcpy(gmx->confout, EditText(dlg, eExConf));
251             }
252             HideDlg(dlg);
253             if (bOk)
254             {
255                 write_gmx(x11, gmx, IDDOEXPORT);
256             }
257             break;
258     }
259 }
260
261 enum {
262     eg0, egTOPOL, egCONFIN, egPARAM, eg1, eg1PROC, eg32PROC
263 };
264
265 static void Extract(t_dlg *dlg, int ID, char *buf)
266 {
267     char *et;
268
269     et = EditText(dlg, ID);
270     if (et)
271     {
272         strcpy(buf, et);
273     }
274 }
275
276 enum bond_set {
277     ebShowH = 11, ebDPlus, ebRMPBC, ebCue, ebSkip, ebWait
278 };
279
280 static void BondsCB(t_x11 *x11, int dlg_mess, int item_id,
281                     char *set, void *data)
282 {
283     static int ebond = -1;
284     static int ebox  = -1;
285     bool       bOk, bBond = false;
286     int        nskip, nwait;
287     t_gmx     *gmx;
288     char      *endptr;
289
290     gmx = (t_gmx *)data;
291     if (ebond == -1)
292     {
293         ebond = gmx->man->molw->bond_type;
294         ebox  = gmx->man->molw->boxtype;
295     }
296     switch (dlg_mess)
297     {
298         case DLG_SET:
299             if (item_id <= eBNR)
300             {
301                 ebond = item_id-1;
302                 bBond = false;
303             }
304             else if (item_id <= eBNR+esbNR+1)
305             {
306                 ebox  = item_id-eBNR-2;
307                 bBond = true;
308             }
309             else
310             {
311
312 #define DO_NOT(b) (b) = (!(b))
313
314                 switch (item_id)
315                 {
316                     case ebShowH:
317                         toggle_hydrogen(x11, gmx->man->molw);
318                         break;
319                     case ebDPlus:
320                         DO_NOT(gmx->man->bPlus);
321 #ifdef DEBUG
322                         fprintf(stderr, "gmx->man->bPlus=%s\n",
323                                 gmx->man->bPlus ? "true" : "false");
324 #endif
325                         break;
326                     case ebRMPBC:
327                         toggle_pbc(gmx->man);
328                         break;
329                     case ebCue:
330                         DO_NOT(gmx->man->bSort);
331 #ifdef DEBUG
332                         fprintf(stderr, "gmx->man->bSort=%s\n",
333                                 gmx->man->bSort ? "true" : "false");
334 #endif
335                         break;
336                     case ebSkip:
337                         nskip = strtol(set, &endptr, 10);
338                         if (endptr != set)
339                         {
340 #ifdef DEBUG
341                             fprintf(stderr, "nskip: %d frames\n", nskip);
342 #endif
343                             if (nskip >= 0)
344                             {
345                                 gmx->man->nSkip = nskip;
346                             }
347                         }
348                         break;
349                     case ebWait:
350                         nwait = strtol(set, &endptr, 10);
351                         if (endptr != set)
352                         {
353 #ifdef DEBUG
354                             fprintf(stderr, "wait: %d ms\n", nwait);
355 #endif
356                             if (nwait >= 0)
357                             {
358                                 gmx->man->nWait = nwait;
359                             }
360                         }
361                     default:
362 #ifdef DEBUG
363                         fprintf(stderr, "item_id: %d, set: %s\n", item_id, set);
364 #endif
365                         break;
366                 }
367             }
368             break;
369         case DLG_EXIT:
370             bOk = (gmx_strcasecmp("ok", set) == 0);
371             HideDlg(gmx->dlgs[edBonds]);
372             if (bOk)
373             {
374                 if (bBond)
375                 {
376                     switch (ebond)
377                     {
378                         case eBThin:
379                             write_gmx(x11, gmx, IDTHIN);
380                             break;
381                         case eBFat:
382                             write_gmx(x11, gmx, IDFAT);
383                             break;
384                         case eBVeryFat:
385                             write_gmx(x11, gmx, IDVERYFAT);
386                             break;
387                         case eBSpheres:
388                             write_gmx(x11, gmx, IDBALLS);
389                             break;
390                         default:
391                             gmx_fatal(FARGS, "Invalid bond type %d at %s, %d",
392                                       ebond, __FILE__, __LINE__);
393                     }
394                 }
395                 else
396                 {
397                     switch (ebox)
398                     {
399                         case esbNone:
400                             write_gmx(x11, gmx, IDNOBOX);
401                             break;
402                         case esbRect:
403                             write_gmx(x11, gmx, IDRECTBOX);
404                             break;
405                         case esbTri:
406                             write_gmx(x11, gmx, IDTRIBOX);
407                             break;
408                         case esbTrunc:
409                             write_gmx(x11, gmx, IDTOBOX);
410                             break;
411                         default:
412                             gmx_fatal(FARGS, "Invalid box type %d at %s, %d",
413                                       ebox, __FILE__, __LINE__);
414                     }
415                 }
416             }
417             break;
418     }
419 }
420
421 enum {
422     esFUNCT = 1, esBSHOW, esINFIL, esINDEXFIL, esLSQ, esSHOW, esPLOTFIL
423 };
424
425 static bool in_set(int i, int n, int set[])
426 {
427     int j;
428     for (j = 0; (j < n); j++)
429     {
430         if (set[j] == i)
431         {
432             return true;
433         }
434     }
435     return false;
436 }
437
438 typedef t_dlg *t_mmb (t_x11 *x11, t_gmx *gmx);
439
440 typedef struct {
441     const char  *dlgfile;
442     DlgCallback *cb;
443 } t_dlginit;
444
445 void init_dlgs(t_x11 *x11, t_gmx *gmx)
446 {
447     static t_dlginit di[] = {
448         { "export.dlg",   ExportCB },
449         { "bonds.dlg",    BondsCB  }
450     };
451     static t_mmb *mi[emNR] = { quit_mb,    help_mb,    about_mb,   ni_mb };
452     unsigned int i;
453
454     snew(gmx->dlgs, edNR);
455     for (i = 0; (i < asize(di)); i++)
456     {
457         gmx->dlgs[i] = ReadDlg(x11, gmx->wd->self, di[i].dlgfile,
458                                di[i].dlgfile,
459                                0, 0, true, false, di[i].cb, gmx);
460     }
461
462     gmx->dlgs[edFilter] = select_filter(x11, gmx);
463
464     snew(gmx->mboxes, emNR);
465     for (i = 0; (i < emNR); i++)
466     {
467         gmx->mboxes[i] = mi[i](x11, gmx);
468     }
469     gmx->which_mb = -1;
470 }
471
472 void done_dlgs(t_gmx *gmx)
473 {
474     int i;
475
476     for (i = 0; (i < edNR); i++)
477     {
478         FreeDlg(gmx->dlgs[i]);
479     }
480     for (i = 0; (i < emNR); i++)
481     {
482         FreeDlg(gmx->mboxes[i]);
483     }
484 }
485
486 void edit_file(const char *fn)
487 {
488     if (fork() == 0)
489     {
490         char script[256];
491
492         sprintf(script, "vi  %s", fn);
493         shell_comm(fn, script, 0);
494         exit(0);
495     }
496 }