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