changed reading hint
[gromacs/adressmacs.git] / src / ngmx / xdlg.c
bloba46031075e61a117c6ee76a7bbebe3202ac5ac39
1 /*
2 * $Id$
3 *
4 * This source code is part of
5 *
6 * G R O M A C S
7 *
8 * GROningen MAchine for Chemical Simulations
9 *
10 * VERSION 2.0
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
16 * Please refer to:
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
23 * or e-mail to:
24 * gromacs@chem.rug.nl
26 * And Hey:
27 * Great Red Oystrich Makes All Chemists Sane
29 static char *SRCID_xdlg_c = "$Id$";
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include "string2.h"
35 #include "assert.h"
36 #include "macros.h"
37 #include "smalloc.h"
38 #include "Xstuff.h"
39 #include "xutil.h"
40 #include "xdlg.h"
41 #include "xmb.h"
42 #include "fatal.h"
43 /*****************************
45 * Helpful routines
47 ****************************/
48 t_dlgitem *FindItem(t_dlg *dlg, t_id id)
50 int i;
52 for(i=0; (i<dlg->nitem); i++)
53 if (dlg->dlgitem[i]->ID==id)
54 return dlg->dlgitem[i];
55 return NULL;
58 t_dlgitem *FindWin(t_dlg *dlg, Window win)
60 int i;
62 for(i=0; (i<dlg->nitem); i++)
63 if (dlg->dlgitem[i]->win.self==win)
64 return dlg->dlgitem[i];
65 return NULL;
68 /*****************************
70 * Routines to manipulate items on a dialog box
72 ****************************/
73 bool QueryDlgItemSize(t_dlg *dlg,t_id id,int *w,int *h)
75 t_dlgitem *dlgitem;
77 if ((dlgitem=FindItem(dlg,id)) != NULL) {
78 *w=dlgitem->win.width;
79 *h=dlgitem->win.height;
80 return TRUE;
82 return FALSE;
85 bool QueryDlgItemPos(t_dlg *dlg,t_id id,int *x0,int *y0)
87 t_dlgitem *dlgitem;
89 if ((dlgitem=FindItem(dlg,id)) != NULL) {
90 *x0=dlgitem->win.x;
91 *y0=dlgitem->win.y;
92 return TRUE;
94 return FALSE;
97 int QueryDlgItemX(t_dlg *dlg, t_id id)
99 t_dlgitem *dlgitem;
101 if ((dlgitem=FindItem(dlg,id)) != NULL)
102 return dlgitem->win.x;
103 return 0;
106 int QueryDlgItemY(t_dlg *dlg, t_id id)
108 t_dlgitem *dlgitem;
110 if ((dlgitem=FindItem(dlg,id)) != NULL)
111 return dlgitem->win.y;
112 return 0;
115 int QueryDlgItemW(t_dlg *dlg, t_id id)
117 t_dlgitem *dlgitem;
119 if ((dlgitem=FindItem(dlg,id)) != NULL)
120 return dlgitem->win.width;
121 return 0;
124 int QueryDlgItemH(t_dlg *dlg, t_id id)
126 t_dlgitem *dlgitem;
128 if ((dlgitem=FindItem(dlg,id)) != NULL)
129 return dlgitem->win.height;
130 return 0;
133 bool SetDlgItemSize(t_dlg *dlg,t_id id,int w,int h)
135 t_dlgitem *dlgitem;
136 #ifdef DEBUG
137 int old_w, old_h;
138 #endif
140 if ((dlgitem=FindItem(dlg,id)) != NULL) {
141 #ifdef DEBUG
142 old_w=dlgitem->win.width;
143 old_h=dlgitem->win.height;
144 #endif
145 if (w)
146 dlgitem->win.width=w;
147 if (h)
148 dlgitem->win.height=h;
149 #ifdef DEBUG
150 fprintf(dlg->x11->console,
151 "Size window from: %dx%d to %dx%d\n",old_w,old_h,
152 dlgitem->win.width,dlgitem->win.height);
153 dlg->x11->Flush(dlg->x11);
154 #endif
155 if (dlgitem->win.self)
156 XResizeWindow(dlg->x11->disp,dlgitem->win.self,dlgitem->win.width,
157 dlgitem->win.height);
158 if ((w) && (dlgitem->type==edlgGB)) {
159 int i;
160 t_id gid=dlgitem->GroupID;
161 t_id id=dlgitem->ID;
162 for (i=0; (i<dlg->nitem); i++) {
163 t_dlgitem *child=dlg->dlgitem[i];
164 if ((child->GroupID==gid) && (child->ID!=id))
165 SetDlgItemSize(dlg,child->ID,w-4*OFFS_X,0);
168 return TRUE;
170 return FALSE;
173 bool SetDlgItemPos(t_dlg *dlg,t_id id,int x0,int y0)
175 t_dlgitem *dlgitem;
176 int old_x,old_y;
178 if ((dlgitem=FindItem(dlg,id)) != NULL) {
179 old_x=dlgitem->win.x;
180 old_y=dlgitem->win.y;
181 dlgitem->win.x=x0;
182 dlgitem->win.y=y0;
183 #ifdef DEBUG
184 fprintf(dlg->x11->console,
185 "Move window from: %d,%d to %d,%d\n",old_x,old_y,x0,y0);
186 dlg->x11->Flush(dlg->x11);
187 #endif
188 if (dlgitem->win.self)
189 XMoveWindow(dlg->x11->disp,dlgitem->win.self,x0,y0);
190 if (dlgitem->type==edlgGB) {
191 int i,x,y;
192 t_id gid=dlgitem->GroupID;
193 t_id id=dlgitem->ID;
194 x=dlgitem->win.x+2*OFFS_X-old_x;
195 y=dlgitem->win.y+2*OFFS_Y-old_y;
196 for (i=0; (i<dlg->nitem); i++) {
197 t_dlgitem *child=dlg->dlgitem[i];
198 if ((child->GroupID==gid) && (child->ID!=id))
199 SetDlgItemPos(dlg,child->ID,child->win.x+x,child->win.y+y);
202 return TRUE;
204 return FALSE;
207 /*****************************
209 * Routines to extract information from the dlg proc
210 * after dlg is exec'ed
212 ****************************/
213 bool IsCBChecked(t_dlg *dlg,t_id id)
215 t_dlgitem *dlgitem;
217 if ((dlgitem=FindItem(dlg,id)) != NULL)
218 if (dlgitem->type==edlgCB)
219 return dlgitem->u.checkbox.bChecked;
221 return FALSE;
224 t_id RBSelected(t_dlg *dlg,int gid)
226 int i;
228 for(i=0; (i<dlg->nitem); i++)
229 if ((dlg->dlgitem[i]->type==edlgRB) &&
230 (dlg->dlgitem[i]->u.radiobutton.bSelect) &&
231 (dlg->dlgitem[i]->GroupID==gid))
232 return dlg->dlgitem[i]->ID;
234 return -1;
237 int EditTextLen(t_dlg *dlg,t_id id)
239 t_dlgitem *dlgitem;
241 if ((dlgitem=FindItem(dlg,id)) != NULL)
242 if (dlgitem->type==edlgET)
243 return strlen(dlgitem->u.edittext.buf);
245 return 0;
248 char *EditText(t_dlg *dlg,t_id id)
250 t_dlgitem *dlgitem;
252 if ((dlgitem=FindItem(dlg,id)) != NULL)
253 if (dlgitem->type==edlgET)
254 return dlgitem->u.edittext.buf;
256 return NULL;
259 /*****************************
261 * Exececute the dialog box procedure
262 * Returns when a button is pushed.
263 * return value is the ID of the button
265 ****************************/
266 void ShowDlg(t_dlg *dlg)
268 int i;
269 t_dlgitem *dlgitem;
271 XMapWindow(dlg->x11->disp,dlg->win.self);
272 XMapSubwindows(dlg->x11->disp,dlg->win.self);
273 for (i=0; (i<dlg->nitem); i++)
274 LightBorder(dlg->x11->disp,dlg->dlgitem[i]->win.self,dlg->bg);
275 XSetForeground(dlg->x11->disp,dlg->x11->gc,dlg->x11->fg);
276 for(i=0; (i<dlg->nitem); i++) {
277 dlgitem=dlg->dlgitem[i];
278 if ((dlgitem->type==edlgBN) &&
279 (dlgitem->u.button.bDefault)) {
280 PushMouse(dlg->x11->disp,dlgitem->win.self,
281 dlgitem->win.width/2,dlgitem->win.height/2);
282 dlg->bPop=TRUE;
283 break;
286 dlg->bGrab=FALSE;
289 void HideDlg(t_dlg *dlg)
291 if (dlg->bPop)
292 PopMouse(dlg->x11->disp);
294 XUnmapSubwindows(dlg->x11->disp,dlg->win.self);
295 XUnmapWindow(dlg->x11->disp,dlg->win.self);
298 void NoHelp(t_dlg *dlg)
300 char **lines=NULL;
302 snew(lines,2);
303 lines[0]=strdup("Error");
304 lines[1]=strdup("No help for this item");
305 MessageBox(dlg->x11,dlg->wDad,"No Help",2,lines,
306 MB_OK | MB_ICONSTOP | MB_APPLMODAL,NULL,NULL);
307 sfree(lines[0]);
308 sfree (lines[1]);
309 sfree(lines);
312 void HelpDlg(t_dlg *dlg)
314 char *lines[] = {
315 "Place the cursor over one of the items",
316 "and press the F1 key to get more help.",
317 "First press the OK button."
319 MessageBox(dlg->x11,dlg->win.self,"Help Dialogbox",
320 3,lines,MB_OK | MB_ICONINFORMATION | MB_APPLMODAL,NULL,NULL);
323 void HelpNow(t_dlg *dlg, t_dlgitem *dlgitem)
325 char buf[80];
326 bool bCont=TRUE;
327 int i,nlines=0;
328 char **lines=NULL;
330 if (!dlgitem->help) {
331 NoHelp(dlg);
332 return;
335 printf("%s\n",dlgitem->help);
336 do {
337 fgets2(buf,79,stdin);
338 #ifdef DEBUG
339 fprintf(dlg->x11->console,"buffer: '%s'\n",buf);
340 dlg->x11->Flush(dlg->x11);
341 #endif
342 if (strcasecmp(buf,"nok")==0) {
343 /* An error occurred */
344 for(i=0; (i<nlines); i++)
345 sfree(lines[i]);
346 sfree(lines);
347 NoHelp(dlg);
348 return;
350 else {
351 bCont=(strcasecmp(buf,"ok") != 0);
352 if (bCont) {
353 srenew(lines,++nlines);
354 lines[nlines-1]=strdup(buf);
357 } while (bCont);
358 MessageBox(dlg->x11,dlg->wDad,"Help",
359 nlines,lines,MB_OK | MB_ICONINFORMATION | MB_APPLMODAL,NULL,NULL);
360 for(i=0; (i<nlines); i++)
361 sfree(lines[i]);
362 sfree(lines);
365 static void EnterDlg(t_dlg *dlg)
367 if (dlg->flags & DLG_APPLMODAL)
368 dlg->bGrab=GrabOK(dlg->x11->console,
369 XGrabPointer(dlg->x11->disp,dlg->win.self,
370 True,0,GrabModeAsync,GrabModeAsync,
371 dlg->win.self,None,CurrentTime));
372 dlg->x11->Flush(dlg->x11);
375 static void ExitDlg(t_dlg *dlg)
377 if (dlg->bGrab) {
378 XUngrabPointer(dlg->x11->disp,CurrentTime);
379 dlg->bGrab=FALSE;
381 HideDlg(dlg);
382 if (dlg->flags & DLG_FREEONBUTTON)
383 FreeDlg(dlg);
386 static bool DlgCB(t_x11 *x11,XEvent *event, Window w, void *data)
388 t_dlg *dlg=(t_dlg *)data;
389 int i,nWndProc;
390 t_dlgitem *dlgitem;
392 if ((dlgitem=FindWin(dlg,w))!=NULL) {
393 nWndProc=(dlgitem->WndProc)(x11,dlgitem,event);
394 #ifdef DEBUG
395 fprintf(x11->console,
396 "window: %s, nWndProc: %d\n",dlgitem->win.text,nWndProc);
397 x11->Flush(x11);
398 #endif
399 switch (nWndProc) {
400 case ENTERPRESSED:
401 if ((dlgitem->type==edlgBN) && (dlgitem->u.button.bDefault)) {
402 if (dlg->cb)
403 dlg->cb(x11,DLG_EXIT,dlgitem->ID,dlgitem->win.text,dlg->data);
404 else
405 ExitDlg(dlg);
407 else {
408 for(i=0; (i<dlg->nitem); i++)
409 if ((dlg->dlgitem[i]->type==edlgBN) &&
410 (dlg->dlgitem[i]->u.button.bDefault)) {
411 PushMouse(x11->disp,dlg->dlgitem[i]->win.self,
412 dlg->dlgitem[i]->win.width/2,
413 dlg->dlgitem[i]->win.height/2);
414 break;
417 break;
418 case BNPRESSED:
419 if (dlg->cb)
420 dlg->cb(x11,DLG_EXIT,dlgitem->ID,dlgitem->win.text,dlg->data);
421 else
422 ExitDlg(dlg);
423 break;
424 case RBPRESSED: {
425 int gid=dlgitem->GroupID;
426 t_id tid=RBSelected(dlg,gid);
427 #ifdef DEBUG
428 fprintf(stderr,"RBPRESSED\n");
429 #endif
430 if (tid != -1) {
431 t_dlgitem *dit=FindItem(dlg,tid);
432 dit->u.radiobutton.bSelect=FALSE;
433 ExposeWin(x11->disp,dit->win.self);
435 else
436 fatal_error(0,"No RB Selected initially!\n");
437 dlgitem->u.radiobutton.bSelect=TRUE;
438 ExposeWin(x11->disp,dlgitem->win.self);
439 if (dlg->cb)
440 dlg->cb(x11,DLG_SET,dlgitem->ID,dlgitem->win.text,dlg->data);
441 break;
443 case CBPRESSED:
444 ExposeWin(x11->disp,dlgitem->win.self);
445 if (dlg->cb)
446 dlg->cb(x11,DLG_SET,dlgitem->ID,dlgitem->set,dlg->data);
447 break;
448 case ETCHANGED:
449 ExposeWin(x11->disp,dlgitem->win.self);
450 if (dlg->cb)
451 dlg->cb(x11,DLG_SET,dlgitem->ID,dlgitem->u.edittext.buf,dlg->data);
452 break;
453 case HELPPRESSED:
454 HelpNow(dlg,dlgitem);
455 break;
456 case ITEMOK:
457 break;
458 default:
459 fatal_error(0,"Invalid return code (%d) from wndproc\n",nWndProc);
462 else if (w==dlg->win.self) {
463 switch(event->type) {
464 case Expose:
465 EnterDlg(dlg);
466 break;
467 case ButtonPress:
468 case KeyPress:
469 if (HelpPressed(event))
470 HelpDlg(dlg);
471 else
472 XBell(x11->disp,50);
473 break;
474 default:
475 break;
478 return FALSE;
481 /*****************************
483 * Routine to add an item to the dialog box
484 * The pointer to the item is copied to the dlg struct,
485 * the item itself may not be freed until the dlg is done with
487 ****************************/
488 void DoCreateDlg(t_dlg *dlg)
490 XSizeHints hints;
491 XSetWindowAttributes attr;
492 unsigned long Val;
494 attr.border_pixel=dlg->x11->fg;
495 attr.background_pixel=dlg->bg;
496 attr.override_redirect=False;
497 attr.save_under=True;
498 attr.cursor=XCreateFontCursor(dlg->x11->disp,XC_hand2);
499 Val=CWBackPixel | CWBorderPixel | CWOverrideRedirect | CWSaveUnder |
500 CWCursor;
501 dlg->win.self=XCreateWindow(dlg->x11->disp,dlg->wDad,
502 dlg->win.x,dlg->win.y,
503 dlg->win.width,dlg->win.height,
504 dlg->win.bwidth,CopyFromParent,
505 InputOutput,CopyFromParent,
506 Val,&attr);
507 dlg->x11->RegisterCallback(dlg->x11,dlg->win.self,dlg->wDad,
508 DlgCB,dlg);
509 dlg->x11->SetInputMask(dlg->x11,dlg->win.self,
510 ExposureMask | ButtonPressMask | KeyPressMask);
512 if (!CheckWindow(dlg->win.self))
513 exit(1);
514 hints.x=dlg->win.x;
515 hints.y=dlg->win.y;
516 hints.flags=PPosition;
517 XSetStandardProperties(dlg->x11->disp,dlg->win.self,dlg->title,
518 dlg->title,None,NULL,0,&hints);
521 void AddDlgItem(t_dlg *dlg, t_dlgitem *new)
523 #define EnterLeaveMask (EnterWindowMask | LeaveWindowMask)
524 #define UserMask (ButtonPressMask | KeyPressMask)
525 static unsigned long InputMask[edlgNR] = {
526 ExposureMask | UserMask | EnterLeaveMask, /* edlgBN */
527 ExposureMask | UserMask | EnterLeaveMask, /* edlgRB */
528 ExposureMask, /* edlgGB */
529 ExposureMask | UserMask | EnterLeaveMask, /* edlgCB */
530 0, /* edlgPM */
531 ExposureMask, /* edlgST */
532 ExposureMask | UserMask | EnterLeaveMask /* edlgET */
535 if (!dlg->win.self)
536 DoCreateDlg(dlg);
537 srenew(dlg->dlgitem,dlg->nitem+1);
538 assert(new);
539 new->win.self=
540 XCreateSimpleWindow(dlg->x11->disp,dlg->win.self,new->win.x,new->win.y,
541 new->win.width,new->win.height,
542 new->win.bwidth,dlg->x11->fg,dlg->x11->bg);
543 CheckWindow(new->win.self);
545 dlg->x11->RegisterCallback(dlg->x11,new->win.self,dlg->win.self,
546 DlgCB,dlg);
547 dlg->x11->SetInputMask(dlg->x11,new->win.self,InputMask[new->type]);
549 switch (new->type) {
550 case edlgPM:
551 XSetWindowBackgroundPixmap(dlg->x11->disp,new->win.self,new->u.pixmap.pm);
552 break;
553 default:
554 break;
556 dlg->dlgitem[dlg->nitem]=new;
558 dlg->nitem++;
561 void AddDlgItems(t_dlg *dlg,int nitem,t_dlgitem *new[])
563 int i;
565 for(i=0; (i<nitem); i++) {
566 #ifdef DEBUG
567 fprintf(dlg->x11->console,
568 "Adding item: %d from group %d\n",new[i]->ID,new[i]->GroupID);
569 dlg->x11->Flush(dlg->x11);
570 #endif
571 AddDlgItem(dlg,new[i]);
575 void FreeDlgItem(t_dlg *dlg, t_id id)
577 t_dlgitem *dlgitem;
578 int i;
580 if ((dlgitem=FindItem(dlg,id)) != NULL) {
581 dlg->x11->UnRegisterCallback(dlg->x11,dlgitem->win.self);
582 if (dlgitem->win.self)
583 XDestroyWindow(dlg->x11->disp,dlgitem->win.self);
584 FreeWin(dlg->x11->disp,&(dlgitem->win));
585 switch(dlgitem->type) {
586 case edlgBN:
587 case edlgRB:
588 break;
589 case edlgGB:
590 sfree(dlgitem->u.groupbox.item);
591 break;
592 case edlgCB:
593 break;
594 case edlgPM:
595 XFreePixmap(dlg->x11->disp,dlgitem->u.pixmap.pm);
596 break;
597 case edlgST:
598 for (i=0; (i<dlgitem->u.statictext.nlines); i++)
599 sfree(dlgitem->u.statictext.lines[i]);
600 sfree(dlgitem->u.statictext.lines);
601 break;
602 case edlgET:
603 sfree(dlgitem->u.edittext.buf);
604 break;
605 default:
606 break;
611 void FreeDlg(t_dlg *dlg)
613 int i;
615 if (dlg->dlgitem) {
616 HideDlg(dlg);
617 dlg->x11->UnRegisterCallback(dlg->x11,dlg->win.self);
618 for(i=0; (i<dlg->nitem); i++) {
619 FreeDlgItem(dlg,dlg->dlgitem[i]->ID);
620 if (dlg->dlgitem[i])
621 sfree(dlg->dlgitem[i]);
623 sfree(dlg->dlgitem);
624 if (dlg->win.self)
625 XDestroyWindow(dlg->x11->disp,dlg->win.self);
626 dlg->dlgitem=NULL;
630 /*****************************
632 * Routine to create the DLG structure, returns NULL on failure
634 ****************************/
635 t_dlg *CreateDlg(t_x11 *x11, Window Parent, char *title,
636 int x0,int y0,int w,int h,int bw, unsigned long fg, unsigned long bg,
637 DlgCallback *cb,void *data)
639 t_dlg *dlg;
640 int x=0,y=0;
642 snew(dlg,1);
643 dlg->x11=x11;
644 dlg->cb=cb;
645 dlg->data=data;
646 if (title)
647 dlg->title=strdup(title);
648 else
649 dlg->title=NULL;
650 if (w==0) w=1;
651 if (h==0) h=1;
652 if (!Parent) {
653 Parent=x11->root;
654 dlg->xmax=DisplayWidth(x11->disp,x11->screen);
655 dlg->ymax=DisplayHeight(x11->disp,x11->screen);
657 else {
658 Window root;
659 unsigned int dum;
661 XGetGeometry(x11->disp,Parent,&root,&x,&y,
662 &(dlg->xmax),&(dlg->ymax),&dum,&dum);
663 #ifdef DEBUG
664 fprintf(x11->console,
665 "Daddy is %d x %d at %d, %d\n",dlg->xmax,dlg->ymax,x,y);
666 dlg->x11->Flush(dlg->x11);
667 #endif
669 if (x0) x=x0;
670 if (y0) y=y0;
671 InitWin(&(dlg->win),x,y,w,h,bw,NULL);
672 SetDlgSize(dlg,w,h,x0 || y0);
674 dlg->wDad=Parent;
675 dlg->fg=x11->fg;
676 dlg->bg=x11->bg;
677 dlg->nitem=0;
678 dlg->dlgitem=NULL;
680 DoCreateDlg(dlg);
681 return dlg;
684 void SetDlgSize(t_dlg *dlg,int w,int h, bool bAutoPosition)
686 if (bAutoPosition) {
687 int x,y;
689 x=(dlg->xmax-w)/2;
690 y=(dlg->ymax-h)/2;
691 dlg->win.x=x;
692 dlg->win.y=y;
694 dlg->win.width=w;
695 dlg->win.height=h;
697 #ifdef DEBUG
698 fprintf(dlg->x11->console,"SetDlgSize: Dialog is %dx%d, at %d,%d\n",
699 dlg->win.width,dlg->win.height,dlg->win.x,dlg->win.y);
700 dlg->x11->Flush(dlg->x11);
701 #endif
702 if (dlg->win.self) {
703 XMoveWindow(dlg->x11->disp,dlg->win.self,dlg->win.x,dlg->win.y);
704 XResizeWindow(dlg->x11->disp,dlg->win.self,w,h);