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