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