Don't use POSIX fnmatch() for pattern matching.
[gromacs/qmmm-gamess-us.git] / src / ngmx / xdlgitem.c
blobc30accc35d7989b2b7070e72f6a4cd404c2dea93
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 <ctype.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
44 #include "gmx_fatal.h"
45 #include "string2.h"
46 #include "smalloc.h"
47 #include "macros.h"
48 #include "Xstuff.h"
49 #include "xdlgitem.h"
51 #define BUFSIZE 16
53 t_dlgitem *newitem(t_x11 *x11)
55 t_dlgitem *item;
57 snew(item,1);
59 return item;
62 /*****************************
64 * Window Procedures and helpful functions
66 ****************************/
67 static void ShowCaret(t_x11 *x11, t_dlgitem *dlgitem)
69 t_edittext *et;
71 if (dlgitem->type == edlgET) {
72 int x,y1,y2;
74 et=&(dlgitem->u.edittext);
75 x=XTextWidth(x11->font,dlgitem->win.text,strlen(dlgitem->win.text))+XCARET+
76 XTextWidth(x11->font,(char*) &(et->buf[et->strbegin]),et->pos);
77 y1=(dlgitem->win.height-XTextHeight(x11->font))/2;
78 y2=(dlgitem->win.height-y1);
79 y1--, y2++;
80 XDrawLine(x11->disp,dlgitem->win.self,x11->gc,x-XCARET,y1,x+XCARET,y1);
81 XDrawLine(x11->disp,dlgitem->win.self,x11->gc,x,y1,x,y2);
82 XDrawLine(x11->disp,dlgitem->win.self,x11->gc,x-XCARET,y2,x+XCARET,y2);
86 static void HideCaret(t_x11 *x11, t_dlgitem *dlgitem)
88 XSetForeground(x11->disp,x11->gc,x11->bg);
89 ShowCaret(x11,dlgitem);
90 XSetForeground(x11->disp,x11->gc,x11->fg);
93 static int DefWndProc(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
95 XComposeStatus status;
96 KeySym keysym;
97 char c[BUFSIZE+1];
99 #ifdef DEBUG
100 printf("DefWndProc\n");
101 #endif
102 switch(event->type) {
103 case Expose:
104 case ButtonPress:
105 case KeyPress:
106 if (HelpPressed(event))
107 return HELPPRESSED;
108 else {
109 XLookupString(&(event->xkey),c,BUFSIZE,&keysym,&status);
110 if ((keysym==XK_Return) || (keysym==XK_KP_Enter))
111 return ENTERPRESSED;
113 break;
114 case EnterNotify:
115 dlgitem->win.bFocus=TRUE;
116 ShowCaret(x11,dlgitem);
117 /* LightBorder(x11->disp,dlgitem->win.self,x11->fg); */
118 break;
119 case LeaveNotify:
120 dlgitem->win.bFocus=FALSE;
121 HideCaret(x11,dlgitem);
122 /* LightBorder(x11->disp,dlgitem->win.self,x11->bg); */
123 break;
124 default:
125 XBell(x11->disp,50);
127 return ITEMOK;
130 static int WndProcBN(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
132 t_windata *win;
133 int x,w,th;
135 if (dlgitem->type != edlgBN)
136 gmx_incons("button processing");
137 win=&(dlgitem->win);
138 w=XTextWidth(x11->font,win->text,strlen(win->text));
139 x=(win->width-w)/2;
140 th=XTextHeight(x11->font)+OFFS_Y;
141 switch(event->type) {
142 case Expose:
143 RectWin(x11->disp,x11->gc,win,x11->fg);
144 TextInRect(x11,win->self,win->text,0,0,win->width,th,eXCenter,eYCenter);
145 break;
146 case ButtonPress:
147 return BNPRESSED;
148 case EnterNotify:
149 XDrawLine(x11->disp,win->self,x11->gc,x-1,th,x+w,th);
150 break;
151 case LeaveNotify:
152 XSetForeground(x11->disp,x11->gc,x11->bg);
153 XDrawLine(x11->disp,win->self,x11->gc,x-1,th,x+w,th);
154 XSetForeground(x11->disp,x11->gc,x11->fg);
155 break;
156 default:
157 return DefWndProc(x11,dlgitem,event);
159 return ITEMOK;
162 static int WndProcRB(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
164 t_radiobutton *rb;
165 t_windata *win;
166 int x,y,rad;
168 if (dlgitem->type != edlgRB)
169 gmx_incons("radiobutton processing");
170 rb=&(dlgitem->u.radiobutton);
171 win=&(dlgitem->win);
173 rad=win->height/3;
174 x=rad;
175 y=win->height/2;
176 switch(event->type) {
177 case Expose:
178 XClearArea(x11->disp,win->self,x-rad,y-rad,x+rad,y+rad,False);
179 if (rb->bSelect)
180 /* Filled */
181 XFillCircle(x11->disp,win->self,x11->gc,x,y,rad);
182 XDrawCircle(x11->disp,win->self,x11->gc,x,y,rad);
183 x+=rad+OFFS_X;
184 TextInRect(x11,win->self,win->text,x,0,win->width-x,win->height,
185 eXLeft,eYCenter);
186 break;
187 case ButtonPress:
188 if (!rb->bSelect)
189 return RBPRESSED;
190 XBell(x11->disp,50);
191 break;
192 case EnterNotify:
193 case LeaveNotify:
194 break;
195 default:
196 return DefWndProc(x11,dlgitem,event);
198 return ITEMOK;
201 static int WndProcGB(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
203 t_windata *win;
204 int x,y;
206 if (dlgitem->type != edlgGB)
207 gmx_incons("gb processing");
208 win=&(dlgitem->win);
210 x=XTextWidth(x11->font,win->text,strlen(win->text));
211 y=XTextHeight(x11->font);
212 switch(event->type) {
213 case Expose:
214 XSetForeground(x11->disp,x11->gc,x11->fg);
215 XDrawRoundRect(x11->disp,win->self,x11->gc,0,y/2,
216 win->width-1,win->height-y/2-1);
217 XClearArea(x11->disp,win->self,OFFS_X,0,x+OFFS_X,y,False);
218 TextInRect(x11,win->self,win->text,2*OFFS_X,0,x,y,eXCenter,eYCenter);
219 break;
220 case EnterNotify:
221 case LeaveNotify:
222 break;
223 default:
224 return DefWndProc(x11,dlgitem,event);
226 return ITEMOK;
229 static int WndProcCB(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
231 t_checkbox *cb;
232 t_windata *win;
233 int x,y,w,h;
235 if (dlgitem->type != edlgCB)
236 gmx_incons("check box processing");
237 cb=&(dlgitem->u.checkbox);
238 win=&(dlgitem->win);
240 x=0;
241 y=win->height/7;
242 w=5*y;
243 h=5*y;
244 switch(event->type) {
245 case Expose:
246 XSetForeground(x11->disp,x11->gc,x11->fg);
247 XClearArea(x11->disp,win->self,x,y,w,h,False);
248 XDrawRectangle(x11->disp,win->self,x11->gc,x,y,w,h);
249 if (cb->bChecked) {
250 XDrawLine(x11->disp,win->self,x11->gc,x,y,x+w,y+h);
251 XDrawLine(x11->disp,win->self,x11->gc,x+w,y,x,y+h);
253 x=w+OFFS_X;
254 TextInRect(x11,win->self,win->text,x,0,win->width-x,win->height,
255 eXLeft,eYCenter);
256 break;
257 case ButtonPress:
258 cb->bChecked=!cb->bChecked;
259 return CBPRESSED;
260 case EnterNotify:
261 case LeaveNotify:
262 break;
263 default:
264 return DefWndProc(x11,dlgitem,event);
266 return ITEMOK;
269 static int WndProcST(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
271 t_statictext *st;
272 t_windata *win;
273 int i,dy;
275 if (dlgitem->type != edlgST)
276 gmx_incons("st processing");
277 st=&(dlgitem->u.statictext);
278 win=&(dlgitem->win);
280 switch(event->type) {
281 case Expose:
282 dy=XTextHeight(x11->font)+OFFS_Y;
283 for (i=0; (i<st->nlines); i++)
284 TextInRect(x11,win->self,st->lines[i],
285 0,OFFS_Y+i*dy,win->width,dy,eXLeft,eYCenter);
286 break;
287 default:
288 return DefWndProc(x11,dlgitem,event);
290 return ITEMOK;
293 static bool insert(char *s, char c, int *pos)
295 int i,sl;
297 if (isprint(c)) {
298 sl=strlen(s);
299 /* +1 for zero termination */
300 for(i=sl+1; (i>*pos); i--)
301 s[i+1]=s[i];
302 s[*pos]=c;
303 (*pos)++;
304 return TRUE;
306 return FALSE;
309 static bool my_backspace(char *s, int *pos)
311 int i,sl;
313 sl=strlen(s);
314 if ((sl > 0) && ((*pos) > 0)) {
315 for(i=*pos-1; (i<sl); i++)
316 s[i]=s[i+1];
317 (*pos)=max(0,(*pos)-1);
318 return TRUE;
320 return FALSE;
323 static bool my_delete(char *s, int *pos)
325 int i,sl;
327 sl=strlen(s);
328 if ((sl > 0) && ((*pos) < sl)) {
329 for(i=*pos; (i<sl); i++)
330 s[i]=s[i+1];
331 return TRUE;
333 return FALSE;
336 static int WndProcET(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
338 t_edittext *et;
339 t_windata *win;
340 KeySym keysym;
341 char c[BUFSIZE+1],*bp;
342 char scrbuf[STRLEN];
343 int i,xp,xtitle,ewidth;
345 if (dlgitem->type != edlgET)
346 gmx_incons("st processing");
347 et=&(dlgitem->u.edittext);
348 win=&(dlgitem->win);
350 /* Copy string part that is visible into screen buffer */
351 for(i=0; (i<et->buflen); i++)
352 scrbuf[i]=et->buf[i+et->strbegin];
353 scrbuf[i]='\0';
355 switch(event->type) {
356 case Expose:
357 XSetForeground(x11->disp,x11->gc,x11->fg);
358 xtitle=XTextWidth(x11->font,win->text,strlen(win->text));
359 ewidth=win->width-xtitle;
360 TextInRect(x11,win->self,win->text,
361 0,0,xtitle-1,win->height,eXLeft,eYCenter);
362 XClearArea(x11->disp,win->self,xtitle,0,ewidth+XCARET,win->height,False);
363 TextInRect(x11,win->self,scrbuf,
364 xtitle+XCARET,0,ewidth,win->height,eXLeft,eYCenter);
365 #ifdef DEBUG
366 printf("Expose\n");
367 #endif
368 if (win->bFocus)
369 ShowCaret(x11,dlgitem);
370 break;
371 case ButtonPress:
372 /* Calculate new position for caret */
373 et->pos=strlen(et->buf);
374 bp=strdup(et->buf);
375 xp=event->xbutton.x-XTextWidth(x11->font,win->text,strlen(win->text))-
376 XCARET;
377 while ((et->pos > 0) && (XTextWidth(x11->font,bp,strlen(bp)) > xp)) {
378 et->pos--;
379 bp[et->pos]='\0';
381 sfree(bp);
382 et->bChanged=TRUE;
383 return ETCHANGED;
384 case KeyPress:
385 /* Check for HelpKey */
386 if (HelpPressed(event))
387 return DefWndProc(x11,dlgitem,event);
388 XLookupString(&(event->xkey),c,BUFSIZE,&keysym,NULL);
389 #ifdef DEBUG
390 printf("Keysym: %x\n",keysym);
391 #endif
392 switch(keysym) {
393 case XK_Delete:
394 if (my_delete(et->buf,&(et->pos))){
395 et->bChanged=TRUE;
396 return ETCHANGED;
398 else
399 XBell(x11->disp,50);
400 break;
401 case XK_BackSpace:
402 if (my_backspace(et->buf,&(et->pos))) {
403 et->bChanged=TRUE;
404 return ETCHANGED;
406 else
407 XBell(x11->disp,50);
408 break;
409 case XK_KP_Enter:
410 case XK_Return:
411 return ENTERPRESSED;
412 case XK_Home:
413 et->pos=0;
414 et->strbegin=0;
415 et->bChanged=TRUE;
416 return ETCHANGED;
417 case XK_End:
418 if (strlen(et->buf) <= et->buflen)
419 et->pos=strlen(et->buf);
420 else {
421 et->pos=et->buflen;
422 et->strbegin=strlen(et->buf)-et->buflen;
424 et->bChanged=TRUE;
425 return ETCHANGED;
426 case XK_Left:
427 et->pos=max(0,et->pos-1);
428 et->strbegin=min(et->strbegin,et->pos);
429 et->bChanged=TRUE;
430 return ETCHANGED;
431 case XK_Right:
432 if ((et->pos < et->buflen) && (et->strbegin+et->buflen > strlen(et->buf)))
433 et->pos++;
434 else if ((et->buflen < strlen(et->buf)) &&
435 (et->strbegin < strlen(et->buf)-et->buflen))
436 et->strbegin++;
437 else
438 break;
439 et->bChanged=TRUE;
440 return ETCHANGED;
441 default:
442 if (keysym < 256)
443 if (insert(et->buf,c[0],&(et->pos))) {
444 et->bChanged=TRUE;
445 return ETCHANGED;
447 XBell(x11->disp,50);
448 break;
450 break;
451 case LeaveNotify:
452 win->bFocus=FALSE;
453 HideCaret(x11,dlgitem);
454 if (et->bChanged)
455 et->bChanged=FALSE;
456 break;
457 default:
458 return DefWndProc(x11,dlgitem,event);
460 return ITEMOK;
463 /*****************************
465 * Routines to create dialog items, all items have an id
466 * which you can use to extract info. It is possible to have
467 * multiple items with the same id but it may then not be possible
468 * to extract information.
469 * All routines take the position relative to the parent dlg
470 * and the size and border width.
471 * If the width and height are set to zero initially, they will
472 * be calculated and set by the routine. With the dlgitem manipulation
473 * routines listed below, the application can then move the items around
474 * on the dlg box, and if wished resize them.
476 ****************************/
477 t_dlgitem *CreateButton(t_x11 *x11,
478 const char *szLab,bool bDef,t_id id,t_id groupid,
479 int x0,int y0,int w,int h,int bw)
481 t_dlgitem *dlgitem;
482 char *lab;
484 dlgitem=newitem(x11);
485 if (h==0) h=XTextHeight(x11->font)+2*OFFS_Y;
486 if (w==0) w=XTextWidth(x11->font,szLab,strlen(szLab))+2*OFFS_X;
487 if (bDef) {
488 snew(lab,strlen(szLab)+7); /* 6 for >> << and 1 for \0 */
489 sprintf(lab,">> %s <<",szLab);
491 else
492 lab=strdup(szLab);
493 InitWin(&(dlgitem->win),x0,y0,w,h,bw,szLab);
494 sfree(lab);
495 dlgitem->ID=id;
496 dlgitem->GroupID=groupid;
497 dlgitem->type=edlgBN;
498 dlgitem->u.button.bDefault=bDef;
499 dlgitem->WndProc=WndProcBN;
501 return dlgitem;
504 t_dlgitem *CreateRadioButton(t_x11 *x11,
505 const char *szLab,bool bSet,t_id id,
506 t_id groupid,
507 int x0,int y0,int w,int h,int bw)
509 t_dlgitem *dlgitem;
511 dlgitem=newitem(x11);
512 if (h==0) h=XTextHeight(x11->font)+OFFS_Y;
513 if (w==0) w=XTextWidth(x11->font,szLab,strlen(szLab))+OFFS_X+h;
514 InitWin(&(dlgitem->win),x0,y0,w,h,bw,szLab);
515 dlgitem->ID=id;
516 dlgitem->GroupID=groupid;
517 dlgitem->type=edlgRB;
518 dlgitem->u.radiobutton.bSelect=bSet;
519 dlgitem->WndProc=WndProcRB;
521 return dlgitem;
524 t_dlgitem *CreateGroupBox(t_x11 *x11,
525 const char *szLab,t_id id,
526 int nitems, t_id items[],
527 int x0,int y0,int w,int h,int bw)
529 t_dlgitem *dlgitem;
531 dlgitem=newitem(x11);
532 if (h==0) h=XTextHeight(x11->font)+OFFS_Y;
533 if (w==0) w=XTextWidth(x11->font,szLab,strlen(szLab))+2*OFFS_X;
534 InitWin(&(dlgitem->win),x0,y0,w,h,bw,szLab);
535 dlgitem->GroupID=id;
536 dlgitem->ID=id;
537 dlgitem->type=edlgGB;
538 dlgitem->u.groupbox.nitems=nitems;
539 snew(dlgitem->u.groupbox.item,nitems);
540 memcpy((char *)dlgitem->u.groupbox.item,(char *)items,
541 nitems*sizeof(items[0]));
542 dlgitem->WndProc=WndProcGB;
544 return dlgitem;
547 t_dlgitem *CreateCheckBox(t_x11 *x11,
548 const char *szLab,bool bCheckedInitial,t_id id,
549 t_id groupid,
550 int x0,int y0,int w,int h,int bw)
552 t_dlgitem *dlgitem;
554 dlgitem=newitem(x11);
555 if (h==0) h=XTextHeight(x11->font)+OFFS_Y;
556 if (w==0) w=XTextWidth(x11->font,szLab,strlen(szLab))+OFFS_X+h;
557 InitWin(&(dlgitem->win),x0,y0,w,h,bw,szLab);
558 dlgitem->ID=id;
559 dlgitem->GroupID=groupid;
560 dlgitem->type=edlgCB;
561 dlgitem->u.checkbox.bChecked=bCheckedInitial;
562 dlgitem->WndProc=WndProcCB;
564 return dlgitem;
567 t_dlgitem *CreatePixmap(t_x11 *x11,
568 Pixmap pm,t_id id,
569 t_id groupid,int x0,int y0,int w,int h,int bw)
571 t_dlgitem *dlgitem;
573 dlgitem=newitem(x11);
574 InitWin(&(dlgitem->win),x0,y0,w,h,bw,NULL);
575 dlgitem->ID=id;
576 dlgitem->type=edlgPM;
577 dlgitem->u.pixmap.pm=pm;
578 dlgitem->WndProc=DefWndProc;
580 return dlgitem;
583 t_dlgitem *CreateStaticText(t_x11 *x11,
584 int nlines,char * const * lines,t_id id,
585 t_id groupid,
586 int x0,int y0,int w,int h,int bw)
588 t_dlgitem *dlgitem;
589 int i;
591 dlgitem=newitem(x11);
592 if (h==0) h=(XTextHeight(x11->font)+OFFS_Y)*nlines+OFFS_Y;
593 if (w==0) {
594 for(i=0; (i<nlines); i++)
595 w=max(w,XTextWidth(x11->font,lines[i],strlen(lines[i])));
596 w+=2*OFFS_X;
598 InitWin(&(dlgitem->win),x0,y0,w,h,bw,NULL);
599 dlgitem->ID=id;
600 dlgitem->GroupID=groupid;
601 dlgitem->type=edlgST;
602 dlgitem->u.statictext.nlines=nlines;
603 snew(dlgitem->u.statictext.lines,nlines);
604 for(i=0; (i<nlines); i++)
605 dlgitem->u.statictext.lines[i]=strdup(lines[i]);
606 dlgitem->WndProc=WndProcST;
608 return dlgitem;
611 t_dlgitem *CreateEditText(t_x11 *x11,
612 const char *title,
613 int screenbuf,char *buf, t_id id,t_id groupid,
614 int x0,int y0,int w,int h,int bw)
616 t_dlgitem *dlgitem;
617 t_edittext *et;
619 dlgitem=newitem(x11);
620 if (h==0) h=XTextHeight(x11->font)+OFFS_Y;
621 if (w==0) {
622 char *test;
624 snew(test,screenbuf);
625 memset(test,'w',screenbuf);
626 w=XTextWidth(x11->font,test,screenbuf)+
627 XTextWidth(x11->font,title,strlen(title))+
628 2*XCARET+2*OFFS_X;
629 sfree(test);
631 InitWin(&(dlgitem->win),x0,y0,w,h,bw,title);
632 dlgitem->ID=id;
633 dlgitem->GroupID=groupid;
634 dlgitem->type=edlgET;
635 et=&(dlgitem->u.edittext);
636 snew(et->buf,STRLEN);
637 strcpy(et->buf,buf);
638 et->buflen=screenbuf;
639 et->strbegin=0;
640 et->bChanged=FALSE;
641 dlgitem->WndProc=WndProcET;
643 return dlgitem;
646 #define SC(src) (strlen(src)?strdup(src):NULL)
648 void SetDlgitemOpts(t_dlgitem *dlgitem,bool bUseMon,
649 char *set,char *get,char *help)
651 dlgitem->bUseMon=bUseMon;
652 dlgitem->set=SC(set);
653 dlgitem->get=SC(get);
654 dlgitem->help=SC(help);
655 #ifdef DEBUG
656 printf("Help is: '%s'\n",dlgitem->help);
657 #endif