Upped the version to 3.2.0
[gromacs.git] / src / ngmx / xdlgitem.c
blob1b2ce01c4b70b500b23de4be200b06de0bfc8d7f
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 3.2.0
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
33 * And Hey:
34 * Gyas ROwers Mature At Cryogenic Speed
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
40 #include "string2.h"
41 #include "assert.h"
42 #include "smalloc.h"
43 #include "macros.h"
44 #include "Xstuff.h"
45 #include "xdlgitem.h"
47 #define BUFSIZE 16
49 t_dlgitem *newitem(t_x11 *x11)
51 t_dlgitem *item;
53 snew(item,1);
55 return item;
58 /*****************************
60 * Window Procedures and helpful functions
62 ****************************/
63 static void ShowCaret(t_x11 *x11, t_dlgitem *dlgitem)
65 t_edittext *et;
67 if (dlgitem->type == edlgET) {
68 int x,y1,y2;
70 et=&(dlgitem->u.edittext);
71 x=XTextWidth(x11->font,dlgitem->win.text,strlen(dlgitem->win.text))+XCARET+
72 XTextWidth(x11->font,(char*) &(et->buf[et->strbegin]),et->pos);
73 y1=(dlgitem->win.height-XTextHeight(x11->font))/2;
74 y2=(dlgitem->win.height-y1);
75 y1--, y2++;
76 XDrawLine(x11->disp,dlgitem->win.self,x11->gc,x-XCARET,y1,x+XCARET,y1);
77 XDrawLine(x11->disp,dlgitem->win.self,x11->gc,x,y1,x,y2);
78 XDrawLine(x11->disp,dlgitem->win.self,x11->gc,x-XCARET,y2,x+XCARET,y2);
82 static void HideCaret(t_x11 *x11, t_dlgitem *dlgitem)
84 XSetForeground(x11->disp,x11->gc,x11->bg);
85 ShowCaret(x11,dlgitem);
86 XSetForeground(x11->disp,x11->gc,x11->fg);
89 static int DefWndProc(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
91 XComposeStatus status;
92 KeySym keysym;
93 char c[BUFSIZE+1];
95 #ifdef DEBUG
96 printf("DefWndProc\n");
97 #endif
98 switch(event->type) {
99 case Expose:
100 case ButtonPress:
101 case KeyPress:
102 if (HelpPressed(event))
103 return HELPPRESSED;
104 else {
105 XLookupString(&(event->xkey),c,BUFSIZE,&keysym,&status);
106 if ((keysym==XK_Return) || (keysym==XK_KP_Enter))
107 return ENTERPRESSED;
109 break;
110 case EnterNotify:
111 dlgitem->win.bFocus=TRUE;
112 ShowCaret(x11,dlgitem);
113 /* LightBorder(x11->disp,dlgitem->win.self,x11->fg); */
114 break;
115 case LeaveNotify:
116 dlgitem->win.bFocus=FALSE;
117 HideCaret(x11,dlgitem);
118 /* LightBorder(x11->disp,dlgitem->win.self,x11->bg); */
119 break;
120 default:
121 XBell(x11->disp,50);
123 return ITEMOK;
126 static int WndProcBN(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
128 t_windata *win;
129 int x,w,th;
131 assert(dlgitem->type==edlgBN);
132 win=&(dlgitem->win);
133 w=XTextWidth(x11->font,win->text,strlen(win->text));
134 x=(win->width-w)/2;
135 th=XTextHeight(x11->font)+OFFS_Y;
136 switch(event->type) {
137 case Expose:
138 RectWin(x11->disp,x11->gc,win,x11->fg);
139 TextInRect(x11,win->self,win->text,0,0,win->width,th,eXCenter,eYCenter);
140 break;
141 case ButtonPress:
142 return BNPRESSED;
143 case EnterNotify:
144 XDrawLine(x11->disp,win->self,x11->gc,x-1,th,x+w,th);
145 break;
146 case LeaveNotify:
147 XSetForeground(x11->disp,x11->gc,x11->bg);
148 XDrawLine(x11->disp,win->self,x11->gc,x-1,th,x+w,th);
149 XSetForeground(x11->disp,x11->gc,x11->fg);
150 break;
151 default:
152 return DefWndProc(x11,dlgitem,event);
154 return ITEMOK;
157 static int WndProcRB(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
159 t_radiobutton *rb;
160 t_windata *win;
161 int x,y,rad;
163 assert(dlgitem->type==edlgRB);
164 rb=&(dlgitem->u.radiobutton);
165 win=&(dlgitem->win);
167 rad=win->height/3;
168 x=rad;
169 y=win->height/2;
170 switch(event->type) {
171 case Expose:
172 XClearArea(x11->disp,win->self,x-rad,y-rad,x+rad,y+rad,False);
173 if (rb->bSelect)
174 /* Filled */
175 XFillCircle(x11->disp,win->self,x11->gc,x,y,rad);
176 XDrawCircle(x11->disp,win->self,x11->gc,x,y,rad);
177 x+=rad+OFFS_X;
178 TextInRect(x11,win->self,win->text,x,0,win->width-x,win->height,
179 eXLeft,eYCenter);
180 break;
181 case ButtonPress:
182 if (!rb->bSelect)
183 return RBPRESSED;
184 XBell(x11->disp,50);
185 break;
186 case EnterNotify:
187 case LeaveNotify:
188 break;
189 default:
190 return DefWndProc(x11,dlgitem,event);
192 return ITEMOK;
195 static int WndProcGB(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
197 t_windata *win;
198 int x,y;
200 assert(dlgitem->type==edlgGB);
201 win=&(dlgitem->win);
203 x=XTextWidth(x11->font,win->text,strlen(win->text));
204 y=XTextHeight(x11->font);
205 switch(event->type) {
206 case Expose:
207 XSetForeground(x11->disp,x11->gc,x11->fg);
208 XDrawRoundRect(x11->disp,win->self,x11->gc,0,y/2,
209 win->width-1,win->height-y/2-1);
210 XClearArea(x11->disp,win->self,OFFS_X,0,x+OFFS_X,y,False);
211 TextInRect(x11,win->self,win->text,2*OFFS_X,0,x,y,eXCenter,eYCenter);
212 break;
213 case EnterNotify:
214 case LeaveNotify:
215 break;
216 default:
217 return DefWndProc(x11,dlgitem,event);
219 return ITEMOK;
222 static int WndProcCB(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
224 t_checkbox *cb;
225 t_windata *win;
226 int x,y,w,h;
228 assert(dlgitem->type==edlgCB);
229 cb=&(dlgitem->u.checkbox);
230 win=&(dlgitem->win);
232 x=0;
233 y=win->height/7;
234 w=5*y;
235 h=5*y;
236 switch(event->type) {
237 case Expose:
238 XSetForeground(x11->disp,x11->gc,x11->fg);
239 XClearArea(x11->disp,win->self,x,y,w,h,False);
240 XDrawRectangle(x11->disp,win->self,x11->gc,x,y,w,h);
241 if (cb->bChecked) {
242 XDrawLine(x11->disp,win->self,x11->gc,x,y,x+w,y+h);
243 XDrawLine(x11->disp,win->self,x11->gc,x+w,y,x,y+h);
245 x=w+OFFS_X;
246 TextInRect(x11,win->self,win->text,x,0,win->width-x,win->height,
247 eXLeft,eYCenter);
248 break;
249 case ButtonPress:
250 cb->bChecked=!cb->bChecked;
251 return CBPRESSED;
252 case EnterNotify:
253 case LeaveNotify:
254 break;
255 default:
256 return DefWndProc(x11,dlgitem,event);
258 return ITEMOK;
261 static int WndProcST(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
263 t_statictext *st;
264 t_windata *win;
265 int i,dy;
267 assert(dlgitem->type==edlgST);
268 st=&(dlgitem->u.statictext);
269 win=&(dlgitem->win);
271 switch(event->type) {
272 case Expose:
273 dy=XTextHeight(x11->font)+OFFS_Y;
274 for (i=0; (i<st->nlines); i++)
275 TextInRect(x11,win->self,st->lines[i],
276 0,OFFS_Y+i*dy,win->width,dy,eXLeft,eYCenter);
277 break;
278 default:
279 return DefWndProc(x11,dlgitem,event);
281 return ITEMOK;
284 static bool insert(char *s, char c, int *pos)
286 int i,sl;
288 if (isprint(c)) {
289 sl=strlen(s);
290 /* +1 for zero termination */
291 for(i=sl+1; (i>*pos); i--)
292 s[i+1]=s[i];
293 s[*pos]=c;
294 (*pos)++;
295 return TRUE;
297 return FALSE;
300 static bool my_backspace(char *s, int *pos)
302 int i,sl;
304 sl=strlen(s);
305 if ((sl > 0) && ((*pos) > 0)) {
306 for(i=*pos-1; (i<sl); i++)
307 s[i]=s[i+1];
308 (*pos)=max(0,(*pos)-1);
309 return TRUE;
311 return FALSE;
314 static bool my_delete(char *s, int *pos)
316 int i,sl;
318 sl=strlen(s);
319 if ((sl > 0) && ((*pos) < sl)) {
320 for(i=*pos; (i<sl); i++)
321 s[i]=s[i+1];
322 return TRUE;
324 return FALSE;
327 static int WndProcET(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
329 t_edittext *et;
330 t_windata *win;
331 KeySym keysym;
332 char c[BUFSIZE+1],*bp;
333 char scrbuf[STRLEN];
334 int i,xp,xtitle,ewidth;
336 assert(dlgitem->type==edlgET);
337 et=&(dlgitem->u.edittext);
338 win=&(dlgitem->win);
340 /* Copy string part that is visible into screen buffer */
341 for(i=0; (i<et->buflen); i++)
342 scrbuf[i]=et->buf[i+et->strbegin];
343 scrbuf[i]='\0';
345 switch(event->type) {
346 case Expose:
347 XSetForeground(x11->disp,x11->gc,x11->fg);
348 xtitle=XTextWidth(x11->font,win->text,strlen(win->text));
349 ewidth=win->width-xtitle;
350 TextInRect(x11,win->self,win->text,
351 0,0,xtitle-1,win->height,eXLeft,eYCenter);
352 XClearArea(x11->disp,win->self,xtitle,0,ewidth+XCARET,win->height,False);
353 TextInRect(x11,win->self,scrbuf,
354 xtitle+XCARET,0,ewidth,win->height,eXLeft,eYCenter);
355 #ifdef DEBUG
356 printf("Expose\n");
357 #endif
358 if (win->bFocus)
359 ShowCaret(x11,dlgitem);
360 break;
361 case ButtonPress:
362 /* Calculate new position for caret */
363 et->pos=strlen(et->buf);
364 bp=strdup(et->buf);
365 xp=event->xbutton.x-XTextWidth(x11->font,win->text,strlen(win->text))-
366 XCARET;
367 while ((et->pos > 0) && (XTextWidth(x11->font,bp,strlen(bp)) > xp)) {
368 et->pos--;
369 bp[et->pos]='\0';
371 sfree(bp);
372 et->bChanged=TRUE;
373 return ETCHANGED;
374 case KeyPress:
375 /* Check for HelpKey */
376 if (HelpPressed(event))
377 return DefWndProc(x11,dlgitem,event);
378 XLookupString(&(event->xkey),c,BUFSIZE,&keysym,NULL);
379 #ifdef DEBUG
380 printf("Keysym: %x\n",keysym);
381 #endif
382 switch(keysym) {
383 case XK_Delete:
384 if (my_delete(et->buf,&(et->pos))){
385 et->bChanged=TRUE;
386 return ETCHANGED;
388 else
389 XBell(x11->disp,50);
390 break;
391 case XK_BackSpace:
392 if (my_backspace(et->buf,&(et->pos))) {
393 et->bChanged=TRUE;
394 return ETCHANGED;
396 else
397 XBell(x11->disp,50);
398 break;
399 case XK_KP_Enter:
400 case XK_Return:
401 return ENTERPRESSED;
402 case XK_Home:
403 et->pos=0;
404 et->strbegin=0;
405 et->bChanged=TRUE;
406 return ETCHANGED;
407 case XK_End:
408 if (strlen(et->buf) <= et->buflen)
409 et->pos=strlen(et->buf);
410 else {
411 et->pos=et->buflen;
412 et->strbegin=strlen(et->buf)-et->buflen;
414 et->bChanged=TRUE;
415 return ETCHANGED;
416 case XK_Left:
417 et->pos=max(0,et->pos-1);
418 et->strbegin=min(et->strbegin,et->pos);
419 et->bChanged=TRUE;
420 return ETCHANGED;
421 case XK_Right:
422 if ((et->pos < et->buflen) && (et->strbegin+et->buflen > strlen(et->buf)))
423 et->pos++;
424 else if ((et->buflen < strlen(et->buf)) &&
425 (et->strbegin < strlen(et->buf)-et->buflen))
426 et->strbegin++;
427 else
428 break;
429 et->bChanged=TRUE;
430 return ETCHANGED;
431 default:
432 if (keysym < 256)
433 if (insert(et->buf,c[0],&(et->pos))) {
434 et->bChanged=TRUE;
435 return ETCHANGED;
437 XBell(x11->disp,50);
438 break;
440 break;
441 case LeaveNotify:
442 win->bFocus=FALSE;
443 HideCaret(x11,dlgitem);
444 if (et->bChanged)
445 et->bChanged=FALSE;
446 break;
447 default:
448 return DefWndProc(x11,dlgitem,event);
450 return ITEMOK;
453 /*****************************
455 * Routines to create dialog items, all items have an id
456 * which you can use to extract info. It is possible to have
457 * multiple items with the same id but it may then not be possible
458 * to extract information.
459 * All routines take the position relative to the parent dlg
460 * and the size and border width.
461 * If the width and height are set to zero initially, they will
462 * be calculated and set by the routine. With the dlgitem manipulation
463 * routines listed below, the application can then move the items around
464 * on the dlg box, and if wished resize them.
466 ****************************/
467 t_dlgitem *CreateButton(t_x11 *x11,
468 char *szLab,bool bDef,t_id id,t_id groupid,
469 int x0,int y0,int w,int h,int bw)
471 t_dlgitem *dlgitem;
472 char *lab;
474 dlgitem=newitem(x11);
475 if (h==0) h=XTextHeight(x11->font)+2*OFFS_Y;
476 if (w==0) w=XTextWidth(x11->font,szLab,strlen(szLab))+2*OFFS_X;
477 if (bDef) {
478 snew(lab,strlen(szLab)+7); /* 6 for >> << and 1 for \0 */
479 sprintf(lab,">> %s <<",szLab);
481 else
482 lab=strdup(szLab);
483 InitWin(&(dlgitem->win),x0,y0,w,h,bw,szLab);
484 sfree(lab);
485 dlgitem->ID=id;
486 dlgitem->GroupID=groupid;
487 dlgitem->type=edlgBN;
488 dlgitem->u.button.bDefault=bDef;
489 dlgitem->WndProc=WndProcBN;
491 return dlgitem;
494 t_dlgitem *CreateRadioButton(t_x11 *x11,
495 char *szLab,bool bSet,t_id id,
496 t_id groupid,
497 int x0,int y0,int w,int h,int bw)
499 t_dlgitem *dlgitem;
501 dlgitem=newitem(x11);
502 if (h==0) h=XTextHeight(x11->font)+OFFS_Y;
503 if (w==0) w=XTextWidth(x11->font,szLab,strlen(szLab))+OFFS_X+h;
504 InitWin(&(dlgitem->win),x0,y0,w,h,bw,szLab);
505 dlgitem->ID=id;
506 dlgitem->GroupID=groupid;
507 dlgitem->type=edlgRB;
508 dlgitem->u.radiobutton.bSelect=bSet;
509 dlgitem->WndProc=WndProcRB;
511 return dlgitem;
514 t_dlgitem *CreateGroupBox(t_x11 *x11,
515 char *szLab,t_id id,
516 int nitems, t_id items[],
517 int x0,int y0,int w,int h,int bw)
519 t_dlgitem *dlgitem;
521 dlgitem=newitem(x11);
522 if (h==0) h=XTextHeight(x11->font)+OFFS_Y;
523 if (w==0) w=XTextWidth(x11->font,szLab,strlen(szLab))+2*OFFS_X;
524 InitWin(&(dlgitem->win),x0,y0,w,h,bw,szLab);
525 dlgitem->GroupID=id;
526 dlgitem->ID=id;
527 dlgitem->type=edlgGB;
528 dlgitem->u.groupbox.nitems=nitems;
529 snew(dlgitem->u.groupbox.item,nitems);
530 memcpy((char *)dlgitem->u.groupbox.item,(char *)items,
531 nitems*sizeof(items[0]));
532 dlgitem->WndProc=WndProcGB;
534 return dlgitem;
537 t_dlgitem *CreateCheckBox(t_x11 *x11,
538 char *szLab,bool bCheckedInitial,t_id id,
539 t_id groupid,
540 int x0,int y0,int w,int h,int bw)
542 t_dlgitem *dlgitem;
544 dlgitem=newitem(x11);
545 if (h==0) h=XTextHeight(x11->font)+OFFS_Y;
546 if (w==0) w=XTextWidth(x11->font,szLab,strlen(szLab))+OFFS_X+h;
547 InitWin(&(dlgitem->win),x0,y0,w,h,bw,szLab);
548 dlgitem->ID=id;
549 dlgitem->GroupID=groupid;
550 dlgitem->type=edlgCB;
551 dlgitem->u.checkbox.bChecked=bCheckedInitial;
552 dlgitem->WndProc=WndProcCB;
554 return dlgitem;
557 t_dlgitem *CreatePixmap(t_x11 *x11,
558 Pixmap pm,t_id id,
559 t_id groupid,int x0,int y0,int w,int h,int bw)
561 t_dlgitem *dlgitem;
563 dlgitem=newitem(x11);
564 InitWin(&(dlgitem->win),x0,y0,w,h,bw,NULL);
565 dlgitem->ID=id;
566 dlgitem->type=edlgPM;
567 dlgitem->u.pixmap.pm=pm;
568 dlgitem->WndProc=DefWndProc;
570 return dlgitem;
573 t_dlgitem *CreateStaticText(t_x11 *x11,
574 int nlines,char **lines,t_id id,t_id groupid,
575 int x0,int y0,int w,int h,int bw)
577 t_dlgitem *dlgitem;
578 int i;
580 dlgitem=newitem(x11);
581 if (h==0) h=(XTextHeight(x11->font)+OFFS_Y)*nlines+OFFS_Y;
582 if (w==0) {
583 for(i=0; (i<nlines); i++)
584 w=max(w,XTextWidth(x11->font,lines[i],strlen(lines[i])));
585 w+=2*OFFS_X;
587 InitWin(&(dlgitem->win),x0,y0,w,h,bw,NULL);
588 dlgitem->ID=id;
589 dlgitem->GroupID=groupid;
590 dlgitem->type=edlgST;
591 dlgitem->u.statictext.nlines=nlines;
592 snew(dlgitem->u.statictext.lines,nlines);
593 for(i=0; (i<nlines); i++)
594 dlgitem->u.statictext.lines[i]=strdup(lines[i]);
595 dlgitem->WndProc=WndProcST;
597 return dlgitem;
600 t_dlgitem *CreateEditText(t_x11 *x11,
601 char *title,
602 int screenbuf,char *buf, t_id id,t_id groupid,
603 int x0,int y0,int w,int h,int bw)
605 t_dlgitem *dlgitem;
606 t_edittext *et;
608 dlgitem=newitem(x11);
609 if (h==0) h=XTextHeight(x11->font)+OFFS_Y;
610 if (w==0) {
611 char *test;
613 snew(test,screenbuf);
614 memset(test,'w',screenbuf);
615 w=XTextWidth(x11->font,test,screenbuf)+
616 XTextWidth(x11->font,title,strlen(title))+
617 2*XCARET+2*OFFS_X;
618 sfree(test);
620 InitWin(&(dlgitem->win),x0,y0,w,h,bw,title);
621 dlgitem->ID=id;
622 dlgitem->GroupID=groupid;
623 dlgitem->type=edlgET;
624 et=&(dlgitem->u.edittext);
625 snew(et->buf,STRLEN);
626 strcpy(et->buf,buf);
627 et->buflen=screenbuf;
628 et->strbegin=0;
629 et->bChanged=FALSE;
630 dlgitem->WndProc=WndProcET;
632 return dlgitem;
635 #define SC(src) (strlen(src)?strdup(src):NULL)
637 void SetDlgitemOpts(t_dlgitem *dlgitem,bool bUseMon,
638 char *set,char *get,char *help)
640 dlgitem->bUseMon=bUseMon;
641 dlgitem->set=SC(set);
642 dlgitem->get=SC(get);
643 dlgitem->help=SC(help);
644 #ifdef DEBUG
645 printf("Help is: '%s'\n",dlgitem->help);
646 #endif