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