Don't use POSIX fnmatch() for pattern matching.
[gromacs/qmmm-gamess-us.git] / src / ngmx / xdlg.c
blobf661e566aaeb9aa8052b13820567f9a40c17ae25
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-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
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.
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.
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.
30 * For more info, check our website at http://www.gromacs.org
32 * And Hey:
33 * Gyas ROwers Mature At Cryogenic Speed
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include "string2.h"
43 #include "macros.h"
44 #include "smalloc.h"
45 #include "Xstuff.h"
46 #include "xutil.h"
47 #include "xdlg.h"
48 #include "xmb.h"
49 #include "gmx_fatal.h"
50 /*****************************
52 * Helpful routines
54 ****************************/
55 t_dlgitem *FindItem(t_dlg *dlg, t_id id)
57 int i;
59 for(i=0; (i<dlg->nitem); i++)
60 if (dlg->dlgitem[i]->ID==id)
61 return dlg->dlgitem[i];
62 return NULL;
65 t_dlgitem *FindWin(t_dlg *dlg, Window win)
67 int i;
69 for(i=0; (i<dlg->nitem); i++)
70 if (dlg->dlgitem[i]->win.self==win)
71 return dlg->dlgitem[i];
72 return NULL;
75 /*****************************
77 * Routines to manipulate items on a dialog box
79 ****************************/
80 bool QueryDlgItemSize(t_dlg *dlg,t_id id,int *w,int *h)
82 t_dlgitem *dlgitem;
84 if ((dlgitem=FindItem(dlg,id)) != NULL) {
85 *w=dlgitem->win.width;
86 *h=dlgitem->win.height;
87 return TRUE;
89 return FALSE;
92 bool QueryDlgItemPos(t_dlg *dlg,t_id id,int *x0,int *y0)
94 t_dlgitem *dlgitem;
96 if ((dlgitem=FindItem(dlg,id)) != NULL) {
97 *x0=dlgitem->win.x;
98 *y0=dlgitem->win.y;
99 return TRUE;
101 return FALSE;
104 int QueryDlgItemX(t_dlg *dlg, t_id id)
106 t_dlgitem *dlgitem;
108 if ((dlgitem=FindItem(dlg,id)) != NULL)
109 return dlgitem->win.x;
110 return 0;
113 int QueryDlgItemY(t_dlg *dlg, t_id id)
115 t_dlgitem *dlgitem;
117 if ((dlgitem=FindItem(dlg,id)) != NULL)
118 return dlgitem->win.y;
119 return 0;
122 int QueryDlgItemW(t_dlg *dlg, t_id id)
124 t_dlgitem *dlgitem;
126 if ((dlgitem=FindItem(dlg,id)) != NULL)
127 return dlgitem->win.width;
128 return 0;
131 int QueryDlgItemH(t_dlg *dlg, t_id id)
133 t_dlgitem *dlgitem;
135 if ((dlgitem=FindItem(dlg,id)) != NULL)
136 return dlgitem->win.height;
137 return 0;
140 bool SetDlgItemSize(t_dlg *dlg,t_id id,int w,int h)
142 t_dlgitem *dlgitem;
143 #ifdef DEBUG
144 int old_w, old_h;
145 #endif
147 if ((dlgitem=FindItem(dlg,id)) != NULL) {
148 #ifdef DEBUG
149 old_w=dlgitem->win.width;
150 old_h=dlgitem->win.height;
151 #endif
152 if (w)
153 dlgitem->win.width=w;
154 if (h)
155 dlgitem->win.height=h;
156 #ifdef DEBUG
157 fprintf(dlg->x11->console,
158 "Size window from: %dx%d to %dx%d\n",old_w,old_h,
159 dlgitem->win.width,dlgitem->win.height);
160 dlg->x11->Flush(dlg->x11);
161 #endif
162 if (dlgitem->win.self)
163 XResizeWindow(dlg->x11->disp,dlgitem->win.self,dlgitem->win.width,
164 dlgitem->win.height);
165 if ((w) && (dlgitem->type==edlgGB)) {
166 int i;
167 t_id gid=dlgitem->GroupID;
168 t_id id=dlgitem->ID;
169 for (i=0; (i<dlg->nitem); i++) {
170 t_dlgitem *child=dlg->dlgitem[i];
171 if ((child->GroupID==gid) && (child->ID!=id))
172 SetDlgItemSize(dlg,child->ID,w-4*OFFS_X,0);
175 return TRUE;
177 return FALSE;
180 bool SetDlgItemPos(t_dlg *dlg,t_id id,int x0,int y0)
182 t_dlgitem *dlgitem;
183 int old_x,old_y;
185 if ((dlgitem=FindItem(dlg,id)) != NULL) {
186 old_x=dlgitem->win.x;
187 old_y=dlgitem->win.y;
188 dlgitem->win.x=x0;
189 dlgitem->win.y=y0;
190 #ifdef DEBUG
191 fprintf(dlg->x11->console,
192 "Move window from: %d,%d to %d,%d\n",old_x,old_y,x0,y0);
193 dlg->x11->Flush(dlg->x11);
194 #endif
195 if (dlgitem->win.self)
196 XMoveWindow(dlg->x11->disp,dlgitem->win.self,x0,y0);
197 if (dlgitem->type==edlgGB) {
198 int i,x,y;
199 t_id gid=dlgitem->GroupID;
200 t_id id=dlgitem->ID;
201 x=dlgitem->win.x+2*OFFS_X-old_x;
202 y=dlgitem->win.y+2*OFFS_Y-old_y;
203 for (i=0; (i<dlg->nitem); i++) {
204 t_dlgitem *child=dlg->dlgitem[i];
205 if ((child->GroupID==gid) && (child->ID!=id))
206 SetDlgItemPos(dlg,child->ID,child->win.x+x,child->win.y+y);
209 return TRUE;
211 return FALSE;
214 /*****************************
216 * Routines to extract information from the dlg proc
217 * after dlg is exec'ed
219 ****************************/
220 bool IsCBChecked(t_dlg *dlg,t_id id)
222 t_dlgitem *dlgitem;
224 if ((dlgitem=FindItem(dlg,id)) != NULL)
225 if (dlgitem->type==edlgCB)
226 return dlgitem->u.checkbox.bChecked;
228 return FALSE;
231 t_id RBSelected(t_dlg *dlg,int gid)
233 int i;
235 for(i=0; (i<dlg->nitem); i++)
236 if ((dlg->dlgitem[i]->type==edlgRB) &&
237 (dlg->dlgitem[i]->u.radiobutton.bSelect) &&
238 (dlg->dlgitem[i]->GroupID==gid))
239 return dlg->dlgitem[i]->ID;
241 return -1;
244 int EditTextLen(t_dlg *dlg,t_id id)
246 t_dlgitem *dlgitem;
248 if ((dlgitem=FindItem(dlg,id)) != NULL)
249 if (dlgitem->type==edlgET)
250 return strlen(dlgitem->u.edittext.buf);
252 return 0;
255 char *EditText(t_dlg *dlg,t_id id)
257 t_dlgitem *dlgitem;
259 if ((dlgitem=FindItem(dlg,id)) != NULL)
260 if (dlgitem->type==edlgET)
261 return dlgitem->u.edittext.buf;
263 return NULL;
266 /*****************************
268 * Exececute the dialog box procedure
269 * Returns when a button is pushed.
270 * return value is the ID of the button
272 ****************************/
273 void ShowDlg(t_dlg *dlg)
275 int i;
276 t_dlgitem *dlgitem;
278 XMapWindow(dlg->x11->disp,dlg->win.self);
279 XMapSubwindows(dlg->x11->disp,dlg->win.self);
280 for (i=0; (i<dlg->nitem); i++)
281 LightBorder(dlg->x11->disp,dlg->dlgitem[i]->win.self,dlg->bg);
282 XSetForeground(dlg->x11->disp,dlg->x11->gc,dlg->x11->fg);
283 for(i=0; (i<dlg->nitem); i++) {
284 dlgitem=dlg->dlgitem[i];
285 if ((dlgitem->type==edlgBN) &&
286 (dlgitem->u.button.bDefault)) {
287 PushMouse(dlg->x11->disp,dlgitem->win.self,
288 dlgitem->win.width/2,dlgitem->win.height/2);
289 dlg->bPop=TRUE;
290 break;
293 dlg->bGrab=FALSE;
296 void HideDlg(t_dlg *dlg)
298 if (dlg->bPop)
299 PopMouse(dlg->x11->disp);
301 XUnmapSubwindows(dlg->x11->disp,dlg->win.self);
302 XUnmapWindow(dlg->x11->disp,dlg->win.self);
305 void NoHelp(t_dlg *dlg)
307 char **lines=NULL;
309 snew(lines,2);
310 lines[0]=strdup("Error");
311 lines[1]=strdup("No help for this item");
312 MessageBox(dlg->x11,dlg->wDad,"No Help",2,lines,
313 MB_OK | MB_ICONSTOP | MB_APPLMODAL,NULL,NULL);
314 sfree(lines[0]);
315 sfree (lines[1]);
316 sfree(lines);
319 void HelpDlg(t_dlg *dlg)
321 char *lines[] = {
322 "Place the cursor over one of the items",
323 "and press the F1 key to get more help.",
324 "First press the OK button."
326 MessageBox(dlg->x11,dlg->win.self,"Help Dialogbox",
327 3,lines,MB_OK | MB_ICONINFORMATION | MB_APPLMODAL,NULL,NULL);
330 void HelpNow(t_dlg *dlg, t_dlgitem *dlgitem)
332 char buf[80];
333 bool bCont=TRUE;
334 int i,nlines=0;
335 char **lines=NULL;
337 if (!dlgitem->help) {
338 NoHelp(dlg);
339 return;
342 printf("%s\n",dlgitem->help);
343 do {
344 fgets2(buf,79,stdin);
345 #ifdef DEBUG
346 fprintf(dlg->x11->console,"buffer: '%s'\n",buf);
347 dlg->x11->Flush(dlg->x11);
348 #endif
349 if (strcasecmp(buf,"nok")==0) {
350 /* An error occurred */
351 for(i=0; (i<nlines); i++)
352 sfree(lines[i]);
353 sfree(lines);
354 NoHelp(dlg);
355 return;
357 else {
358 bCont=(strcasecmp(buf,"ok") != 0);
359 if (bCont) {
360 srenew(lines,++nlines);
361 lines[nlines-1]=strdup(buf);
364 } while (bCont);
365 MessageBox(dlg->x11,dlg->wDad,"Help",
366 nlines,lines,MB_OK | MB_ICONINFORMATION | MB_APPLMODAL,NULL,NULL);
367 for(i=0; (i<nlines); i++)
368 sfree(lines[i]);
369 sfree(lines);
372 static void EnterDlg(t_dlg *dlg)
374 if (dlg->flags & DLG_APPLMODAL)
375 dlg->bGrab=GrabOK(dlg->x11->console,
376 XGrabPointer(dlg->x11->disp,dlg->win.self,
377 True,0,GrabModeAsync,GrabModeAsync,
378 dlg->win.self,None,CurrentTime));
379 dlg->x11->Flush(dlg->x11);
382 static void ExitDlg(t_dlg *dlg)
384 if (dlg->bGrab) {
385 XUngrabPointer(dlg->x11->disp,CurrentTime);
386 dlg->bGrab=FALSE;
388 HideDlg(dlg);
389 if (dlg->flags & DLG_FREEONBUTTON)
390 FreeDlg(dlg);
393 static bool DlgCB(t_x11 *x11,XEvent *event, Window w, void *data)
395 t_dlg *dlg=(t_dlg *)data;
396 int i,nWndProc;
397 t_dlgitem *dlgitem;
399 if ((dlgitem=FindWin(dlg,w))!=NULL) {
400 nWndProc=(dlgitem->WndProc)(x11,dlgitem,event);
401 #ifdef DEBUG
402 fprintf(x11->console,
403 "window: %s, nWndProc: %d\n",dlgitem->win.text,nWndProc);
404 x11->Flush(x11);
405 #endif
406 switch (nWndProc) {
407 case ENTERPRESSED:
408 if ((dlgitem->type==edlgBN) && (dlgitem->u.button.bDefault)) {
409 if (dlg->cb)
410 dlg->cb(x11,DLG_EXIT,dlgitem->ID,dlgitem->win.text,dlg->data);
411 else
412 ExitDlg(dlg);
414 else {
415 for(i=0; (i<dlg->nitem); i++)
416 if ((dlg->dlgitem[i]->type==edlgBN) &&
417 (dlg->dlgitem[i]->u.button.bDefault)) {
418 PushMouse(x11->disp,dlg->dlgitem[i]->win.self,
419 dlg->dlgitem[i]->win.width/2,
420 dlg->dlgitem[i]->win.height/2);
421 break;
424 break;
425 case BNPRESSED:
426 if (dlg->cb)
427 dlg->cb(x11,DLG_EXIT,dlgitem->ID,dlgitem->win.text,dlg->data);
428 else
429 ExitDlg(dlg);
430 break;
431 case RBPRESSED: {
432 int gid=dlgitem->GroupID;
433 t_id tid=RBSelected(dlg,gid);
434 #ifdef DEBUG
435 fprintf(stderr,"RBPRESSED\n");
436 #endif
437 if (tid != -1) {
438 t_dlgitem *dit=FindItem(dlg,tid);
439 dit->u.radiobutton.bSelect=FALSE;
440 ExposeWin(x11->disp,dit->win.self);
442 else
443 gmx_fatal(FARGS,"No RB Selected initially!\n");
444 dlgitem->u.radiobutton.bSelect=TRUE;
445 ExposeWin(x11->disp,dlgitem->win.self);
446 if (dlg->cb)
447 dlg->cb(x11,DLG_SET,dlgitem->ID,dlgitem->win.text,dlg->data);
448 break;
450 case CBPRESSED:
451 ExposeWin(x11->disp,dlgitem->win.self);
452 if (dlg->cb)
453 dlg->cb(x11,DLG_SET,dlgitem->ID,dlgitem->set,dlg->data);
454 break;
455 case ETCHANGED:
456 ExposeWin(x11->disp,dlgitem->win.self);
457 if (dlg->cb)
458 dlg->cb(x11,DLG_SET,dlgitem->ID,dlgitem->u.edittext.buf,dlg->data);
459 break;
460 case HELPPRESSED:
461 HelpNow(dlg,dlgitem);
462 break;
463 case ITEMOK:
464 break;
465 default:
466 gmx_fatal(FARGS,"Invalid return code (%d) from wndproc\n",nWndProc);
469 else if (w==dlg->win.self) {
470 switch(event->type) {
471 case Expose:
472 EnterDlg(dlg);
473 break;
474 case ButtonPress:
475 case KeyPress:
476 if (HelpPressed(event))
477 HelpDlg(dlg);
478 else
479 XBell(x11->disp,50);
480 break;
481 default:
482 break;
485 return FALSE;
488 /*****************************
490 * Routine to add an item to the dialog box
491 * The pointer to the item is copied to the dlg struct,
492 * the item itself may not be freed until the dlg is done with
494 ****************************/
495 void DoCreateDlg(t_dlg *dlg)
497 XSizeHints hints;
498 XSetWindowAttributes attr;
499 unsigned long Val;
501 attr.border_pixel=dlg->x11->fg;
502 attr.background_pixel=dlg->bg;
503 attr.override_redirect=False;
504 attr.save_under=True;
505 attr.cursor=XCreateFontCursor(dlg->x11->disp,XC_hand2);
506 Val=CWBackPixel | CWBorderPixel | CWOverrideRedirect | CWSaveUnder |
507 CWCursor;
508 dlg->win.self=XCreateWindow(dlg->x11->disp,dlg->wDad,
509 dlg->win.x,dlg->win.y,
510 dlg->win.width,dlg->win.height,
511 dlg->win.bwidth,CopyFromParent,
512 InputOutput,CopyFromParent,
513 Val,&attr);
514 dlg->x11->RegisterCallback(dlg->x11,dlg->win.self,dlg->wDad,
515 DlgCB,dlg);
516 dlg->x11->SetInputMask(dlg->x11,dlg->win.self,
517 ExposureMask | ButtonPressMask | KeyPressMask);
519 if (!CheckWindow(dlg->win.self))
520 exit(1);
521 hints.x=dlg->win.x;
522 hints.y=dlg->win.y;
523 hints.flags=PPosition;
524 XSetStandardProperties(dlg->x11->disp,dlg->win.self,dlg->title,
525 dlg->title,None,NULL,0,&hints);
528 void AddDlgItem(t_dlg *dlg, t_dlgitem *item)
530 #define EnterLeaveMask (EnterWindowMask | LeaveWindowMask)
531 #define UserMask (ButtonPressMask | KeyPressMask)
532 static unsigned long InputMask[edlgNR] = {
533 ExposureMask | UserMask | EnterLeaveMask, /* edlgBN */
534 ExposureMask | UserMask | EnterLeaveMask, /* edlgRB */
535 ExposureMask, /* edlgGB */
536 ExposureMask | UserMask | EnterLeaveMask, /* edlgCB */
537 0, /* edlgPM */
538 ExposureMask, /* edlgST */
539 ExposureMask | UserMask | EnterLeaveMask /* edlgET */
542 if (!dlg->win.self)
543 DoCreateDlg(dlg);
544 srenew(dlg->dlgitem,dlg->nitem+1);
545 if (!item)
546 gmx_fatal(FARGS,"dlgitem not allocated");
547 item->win.self=
548 XCreateSimpleWindow(dlg->x11->disp,dlg->win.self,item->win.x,item->win.y,
549 item->win.width,item->win.height,
550 item->win.bwidth,dlg->x11->fg,dlg->x11->bg);
551 CheckWindow(item->win.self);
553 dlg->x11->RegisterCallback(dlg->x11,item->win.self,dlg->win.self,
554 DlgCB,dlg);
555 dlg->x11->SetInputMask(dlg->x11,item->win.self,InputMask[item->type]);
557 switch (item->type) {
558 case edlgPM:
559 XSetWindowBackgroundPixmap(dlg->x11->disp,item->win.self,item->u.pixmap.pm);
560 break;
561 default:
562 break;
564 dlg->dlgitem[dlg->nitem]=item;
566 dlg->nitem++;
569 void AddDlgItems(t_dlg *dlg,int nitem,t_dlgitem *item[])
571 int i;
573 for(i=0; (i<nitem); i++) {
574 #ifdef DEBUG
575 fprintf(dlg->x11->console,
576 "Adding item: %d from group %d\n",item[i]->ID,item[i]->GroupID);
577 dlg->x11->Flush(dlg->x11);
578 #endif
579 AddDlgItem(dlg,item[i]);
583 void FreeDlgItem(t_dlg *dlg, t_id id)
585 t_dlgitem *dlgitem;
586 int i;
588 if ((dlgitem=FindItem(dlg,id)) != NULL) {
589 dlg->x11->UnRegisterCallback(dlg->x11,dlgitem->win.self);
590 if (dlgitem->win.self)
591 XDestroyWindow(dlg->x11->disp,dlgitem->win.self);
592 FreeWin(dlg->x11->disp,&(dlgitem->win));
593 switch(dlgitem->type) {
594 case edlgBN:
595 case edlgRB:
596 break;
597 case edlgGB:
598 sfree(dlgitem->u.groupbox.item);
599 break;
600 case edlgCB:
601 break;
602 case edlgPM:
603 XFreePixmap(dlg->x11->disp,dlgitem->u.pixmap.pm);
604 break;
605 case edlgST:
606 for (i=0; (i<dlgitem->u.statictext.nlines); i++)
607 sfree(dlgitem->u.statictext.lines[i]);
608 sfree(dlgitem->u.statictext.lines);
609 break;
610 case edlgET:
611 sfree(dlgitem->u.edittext.buf);
612 break;
613 default:
614 break;
619 void FreeDlg(t_dlg *dlg)
621 int i;
623 if (dlg->dlgitem) {
624 HideDlg(dlg);
625 dlg->x11->UnRegisterCallback(dlg->x11,dlg->win.self);
626 for(i=0; (i<dlg->nitem); i++) {
627 FreeDlgItem(dlg,dlg->dlgitem[i]->ID);
628 if (dlg->dlgitem[i])
629 sfree(dlg->dlgitem[i]);
631 sfree(dlg->dlgitem);
632 if (dlg->win.self)
633 XDestroyWindow(dlg->x11->disp,dlg->win.self);
634 dlg->dlgitem=NULL;
638 /*****************************
640 * Routine to create the DLG structure, returns NULL on failure
642 ****************************/
643 t_dlg *CreateDlg(t_x11 *x11, Window Parent, const char *title,
644 int x0,int y0,int w,int h,int bw, unsigned long fg, unsigned long bg,
645 DlgCallback *cb,void *data)
647 t_dlg *dlg;
648 int x=0,y=0;
650 snew(dlg,1);
651 dlg->x11=x11;
652 dlg->cb=cb;
653 dlg->data=data;
654 if (title)
655 dlg->title=strdup(title);
656 else
657 dlg->title=NULL;
658 if (w==0) w=1;
659 if (h==0) h=1;
660 if (!Parent) {
661 Parent=x11->root;
662 dlg->xmax=DisplayWidth(x11->disp,x11->screen);
663 dlg->ymax=DisplayHeight(x11->disp,x11->screen);
665 else {
666 Window root;
667 unsigned int dum;
669 XGetGeometry(x11->disp,Parent,&root,&x,&y,
670 &(dlg->xmax),&(dlg->ymax),&dum,&dum);
671 #ifdef DEBUG
672 fprintf(x11->console,
673 "Daddy is %d x %d at %d, %d\n",dlg->xmax,dlg->ymax,x,y);
674 dlg->x11->Flush(dlg->x11);
675 #endif
677 if (x0) x=x0;
678 if (y0) y=y0;
679 InitWin(&(dlg->win),x,y,w,h,bw,NULL);
680 SetDlgSize(dlg,w,h,x0 || y0);
682 dlg->wDad=Parent;
683 dlg->fg=x11->fg;
684 dlg->bg=x11->bg;
685 dlg->nitem=0;
686 dlg->dlgitem=NULL;
688 DoCreateDlg(dlg);
689 return dlg;
692 void SetDlgSize(t_dlg *dlg,int w,int h, bool bAutoPosition)
694 if (bAutoPosition) {
695 int x,y;
697 x=(dlg->xmax-w)/2;
698 y=(dlg->ymax-h)/2;
699 dlg->win.x=x;
700 dlg->win.y=y;
702 dlg->win.width=w;
703 dlg->win.height=h;
705 #ifdef DEBUG
706 fprintf(dlg->x11->console,"SetDlgSize: Dialog is %dx%d, at %d,%d\n",
707 dlg->win.width,dlg->win.height,dlg->win.x,dlg->win.y);
708 dlg->x11->Flush(dlg->x11);
709 #endif
710 if (dlg->win.self) {
711 XMoveWindow(dlg->x11->disp,dlg->win.self,dlg->win.x,dlg->win.y);
712 XResizeWindow(dlg->x11->disp,dlg->win.self,w,h);