2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2013, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015,2017, 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.
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.
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.
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.
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.
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.
47 #include "gromacs/utility/cstringutil.h"
48 #include "gromacs/utility/fatalerror.h"
49 #include "gromacs/utility/smalloc.h"
55 static t_dlgitem
*newitem(void)
64 /*****************************
66 * Window Procedures and helpful functions
68 ****************************/
69 static void ShowCaret(t_x11
*x11
, t_dlgitem
*dlgitem
)
73 if (dlgitem
->type
== edlgET
)
77 et
= &(dlgitem
->u
.edittext
);
78 x
= XTextWidth(x11
->font
, dlgitem
->win
.text
, std::strlen(dlgitem
->win
.text
))+XCARET
+
79 XTextWidth(x11
->font
, (char*) &(et
->buf
[et
->strbegin
]), et
->pos
);
80 y1
= (dlgitem
->win
.height
-XTextHeight(x11
->font
))/2;
81 y2
= (dlgitem
->win
.height
-y1
);
83 XDrawLine(x11
->disp
, dlgitem
->win
.self
, x11
->gc
, x
-XCARET
, y1
, x
+XCARET
, y1
);
84 XDrawLine(x11
->disp
, dlgitem
->win
.self
, x11
->gc
, x
, y1
, x
, y2
);
85 XDrawLine(x11
->disp
, dlgitem
->win
.self
, x11
->gc
, x
-XCARET
, y2
, x
+XCARET
, y2
);
89 static void HideCaret(t_x11
*x11
, t_dlgitem
*dlgitem
)
91 XSetForeground(x11
->disp
, x11
->gc
, x11
->bg
);
92 ShowCaret(x11
, dlgitem
);
93 XSetForeground(x11
->disp
, x11
->gc
, x11
->fg
);
96 static int DefWndProc(t_x11
*x11
, t_dlgitem
*dlgitem
, XEvent
*event
)
98 XComposeStatus status
;
103 std::printf("DefWndProc\n");
110 if (HelpPressed(event
))
116 XLookupString(&(event
->xkey
), c
, BUFSIZE
, &keysym
, &status
);
117 if ((keysym
== XK_Return
) || (keysym
== XK_KP_Enter
))
124 dlgitem
->win
.bFocus
= true;
125 ShowCaret(x11
, dlgitem
);
126 /* LightBorder(x11->disp,dlgitem->win.self,x11->fg); */
129 dlgitem
->win
.bFocus
= false;
130 HideCaret(x11
, dlgitem
);
131 /* LightBorder(x11->disp,dlgitem->win.self,x11->bg); */
134 XBell(x11
->disp
, 50);
139 static int WndProcBN(t_x11
*x11
, t_dlgitem
*dlgitem
, XEvent
*event
)
144 if (dlgitem
->type
!= edlgBN
)
146 gmx_incons("button processing");
148 win
= &(dlgitem
->win
);
149 w
= XTextWidth(x11
->font
, win
->text
, std::strlen(win
->text
));
150 x
= (win
->width
-w
)/2;
151 th
= XTextHeight(x11
->font
)+OFFS_Y
;
155 RectWin(x11
->disp
, x11
->gc
, win
, x11
->fg
);
156 TextInRect(x11
, win
->self
, win
->text
, 0, 0, win
->width
, th
, eXCenter
, eYCenter
);
161 XDrawLine(x11
->disp
, win
->self
, x11
->gc
, x
-1, th
, x
+w
, th
);
164 XSetForeground(x11
->disp
, x11
->gc
, x11
->bg
);
165 XDrawLine(x11
->disp
, win
->self
, x11
->gc
, x
-1, th
, x
+w
, th
);
166 XSetForeground(x11
->disp
, x11
->gc
, x11
->fg
);
169 return DefWndProc(x11
, dlgitem
, event
);
174 static int WndProcRB(t_x11
*x11
, t_dlgitem
*dlgitem
, XEvent
*event
)
180 if (dlgitem
->type
!= edlgRB
)
182 gmx_incons("radiobutton processing");
184 rb
= &(dlgitem
->u
.radiobutton
);
185 win
= &(dlgitem
->win
);
193 XClearArea(x11
->disp
, win
->self
, x
-rad
, y
-rad
, x
+rad
, y
+rad
, False
);
197 XFillCircle(x11
->disp
, win
->self
, x11
->gc
, x
, y
, rad
);
199 XDrawCircle(x11
->disp
, win
->self
, x11
->gc
, x
, y
, rad
);
201 TextInRect(x11
, win
->self
, win
->text
, x
, 0, win
->width
-x
, win
->height
,
209 XBell(x11
->disp
, 50);
215 return DefWndProc(x11
, dlgitem
, event
);
220 static int WndProcGB(t_x11
*x11
, t_dlgitem
*dlgitem
, XEvent
*event
)
225 if (dlgitem
->type
!= edlgGB
)
227 gmx_incons("gb processing");
229 win
= &(dlgitem
->win
);
231 x
= XTextWidth(x11
->font
, win
->text
, std::strlen(win
->text
));
232 y
= XTextHeight(x11
->font
);
236 XSetForeground(x11
->disp
, x11
->gc
, x11
->fg
);
237 XDrawRoundRect(x11
->disp
, win
->self
, x11
->gc
, 0, y
/2,
238 win
->width
-1, win
->height
-y
/2-1);
239 XClearArea(x11
->disp
, win
->self
, OFFS_X
, 0, x
+OFFS_X
, y
, False
);
240 TextInRect(x11
, win
->self
, win
->text
, 2*OFFS_X
, 0, x
, y
, eXCenter
, eYCenter
);
246 return DefWndProc(x11
, dlgitem
, event
);
251 static int WndProcCB(t_x11
*x11
, t_dlgitem
*dlgitem
, XEvent
*event
)
257 if (dlgitem
->type
!= edlgCB
)
259 gmx_incons("check box processing");
261 cb
= &(dlgitem
->u
.checkbox
);
262 win
= &(dlgitem
->win
);
271 XSetForeground(x11
->disp
, x11
->gc
, x11
->fg
);
272 XClearArea(x11
->disp
, win
->self
, x
, y
, w
, h
, False
);
273 XDrawRectangle(x11
->disp
, win
->self
, x11
->gc
, x
, y
, w
, h
);
276 XDrawLine(x11
->disp
, win
->self
, x11
->gc
, x
, y
, x
+w
, y
+h
);
277 XDrawLine(x11
->disp
, win
->self
, x11
->gc
, x
+w
, y
, x
, y
+h
);
280 TextInRect(x11
, win
->self
, win
->text
, x
, 0, win
->width
-x
, win
->height
,
284 cb
->bChecked
= !cb
->bChecked
;
290 return DefWndProc(x11
, dlgitem
, event
);
295 static int WndProcST(t_x11
*x11
, t_dlgitem
*dlgitem
, XEvent
*event
)
301 if (dlgitem
->type
!= edlgST
)
303 gmx_incons("st processing");
305 st
= &(dlgitem
->u
.statictext
);
306 win
= &(dlgitem
->win
);
311 dy
= XTextHeight(x11
->font
)+OFFS_Y
;
312 for (i
= 0; (i
< st
->nlines
); i
++)
314 TextInRect(x11
, win
->self
, st
->lines
[i
],
315 0, OFFS_Y
+i
*dy
, win
->width
, dy
, eXLeft
, eYCenter
);
319 return DefWndProc(x11
, dlgitem
, event
);
324 static bool insert(char *s
, char c
, int *pos
)
331 /* +1 for zero termination */
332 for (i
= sl
+1; (i
> *pos
); i
--)
343 static bool my_backspace(char *s
, int *pos
)
348 if ((sl
> 0) && ((*pos
) > 0))
350 for (i
= *pos
-1; (i
< sl
); i
++)
354 (*pos
) = std::max(0, (*pos
)-1);
360 static bool my_delete(char *s
, int *pos
)
365 if ((sl
> 0) && ((*pos
) < sl
))
367 for (i
= *pos
; (i
< sl
); i
++)
376 static int WndProcET(t_x11
*x11
, t_dlgitem
*dlgitem
, XEvent
*event
)
381 char c
[BUFSIZE
+1], *bp
;
384 int xp
, xtitle
, ewidth
;
386 if (dlgitem
->type
!= edlgET
)
388 gmx_incons("st processing");
390 et
= &(dlgitem
->u
.edittext
);
391 win
= &(dlgitem
->win
);
393 /* Copy string part that is visible into screen buffer */
394 for (i
= 0; (i
< et
->buflen
); i
++)
396 scrbuf
[i
] = et
->buf
[i
+et
->strbegin
];
403 XSetForeground(x11
->disp
, x11
->gc
, x11
->fg
);
404 xtitle
= XTextWidth(x11
->font
, win
->text
, std::strlen(win
->text
));
405 ewidth
= win
->width
-xtitle
;
406 TextInRect(x11
, win
->self
, win
->text
,
407 0, 0, xtitle
-1, win
->height
, eXLeft
, eYCenter
);
408 XClearArea(x11
->disp
, win
->self
, xtitle
, 0, ewidth
+XCARET
, win
->height
, False
);
409 TextInRect(x11
, win
->self
, scrbuf
,
410 xtitle
+XCARET
, 0, ewidth
, win
->height
, eXLeft
, eYCenter
);
412 std::printf("Expose\n");
416 ShowCaret(x11
, dlgitem
);
420 /* Calculate new position for caret */
421 et
->pos
= std::strlen(et
->buf
);
422 bp
= gmx_strdup(et
->buf
);
423 xp
= event
->xbutton
.x
-XTextWidth(x11
->font
, win
->text
, std::strlen(win
->text
))-
425 while ((et
->pos
> 0) && (XTextWidth(x11
->font
, bp
, std::strlen(bp
)) > xp
))
434 /* Check for HelpKey */
435 if (HelpPressed(event
))
437 return DefWndProc(x11
, dlgitem
, event
);
439 XLookupString(&(event
->xkey
), c
, BUFSIZE
, &keysym
, nullptr);
441 std::printf("Keysym: %x\n", keysym
);
446 if (my_delete(et
->buf
, &(et
->pos
)))
453 XBell(x11
->disp
, 50);
457 if (my_backspace(et
->buf
, &(et
->pos
)))
464 XBell(x11
->disp
, 50);
476 if (strlen(et
->buf
) <= (unsigned int)et
->buflen
)
478 et
->pos
= std::strlen(et
->buf
);
482 et
->pos
= et
->buflen
;
483 et
->strbegin
= std::strlen(et
->buf
)-et
->buflen
;
488 et
->pos
= std::max(0, et
->pos
-1);
489 et
->strbegin
= std::min(et
->strbegin
, et
->pos
);
493 if ((et
->pos
< et
->buflen
) &&
494 (et
->strbegin
+et
->buflen
> (int)strlen(et
->buf
)))
498 else if ((et
->buflen
< (int)strlen(et
->buf
)) &&
499 (et
->strbegin
< (int)strlen(et
->buf
)-et
->buflen
))
512 if (insert(et
->buf
, c
[0], &(et
->pos
)))
518 XBell(x11
->disp
, 50);
524 HideCaret(x11
, dlgitem
);
527 et
->bChanged
= false;
531 return DefWndProc(x11
, dlgitem
, event
);
536 /*****************************
538 * Routines to create dialog items, all items have an id
539 * which you can use to extract info. It is possible to have
540 * multiple items with the same id but it may then not be possible
541 * to extract information.
542 * All routines take the position relative to the parent dlg
543 * and the size and border width.
544 * If the width and height are set to zero initially, they will
545 * be calculated and set by the routine. With the dlgitem manipulation
546 * routines listed below, the application can then move the items around
547 * on the dlg box, and if wished resize them.
549 ****************************/
550 t_dlgitem
*CreateButton(t_x11
*x11
,
551 const char *szLab
, bool bDef
, t_id id
, t_id groupid
,
552 int x0
, int y0
, int w
, int h
, int bw
)
560 h
= XTextHeight(x11
->font
)+2*OFFS_Y
;
564 w
= XTextWidth(x11
->font
, szLab
, std::strlen(szLab
))+2*OFFS_X
;
568 snew(lab
, std::strlen(szLab
)+7); /* 6 for >> << and 1 for \0 */
569 std::sprintf(lab
, ">> %s <<", szLab
);
573 lab
= gmx_strdup(szLab
);
575 InitWin(&(dlgitem
->win
), x0
, y0
, w
, h
, bw
, szLab
);
578 dlgitem
->GroupID
= groupid
;
579 dlgitem
->type
= edlgBN
;
580 dlgitem
->u
.button
.bDefault
= bDef
;
581 dlgitem
->WndProc
= WndProcBN
;
586 t_dlgitem
*CreateRadioButton(t_x11
*x11
,
587 const char *szLab
, bool bSet
, t_id id
,
589 int x0
, int y0
, int w
, int h
, int bw
)
596 h
= XTextHeight(x11
->font
)+OFFS_Y
;
600 w
= XTextWidth(x11
->font
, szLab
, std::strlen(szLab
))+OFFS_X
+h
;
602 InitWin(&(dlgitem
->win
), x0
, y0
, w
, h
, bw
, szLab
);
604 dlgitem
->GroupID
= groupid
;
605 dlgitem
->type
= edlgRB
;
606 dlgitem
->u
.radiobutton
.bSelect
= bSet
;
607 dlgitem
->WndProc
= WndProcRB
;
612 t_dlgitem
*CreateGroupBox(t_x11
*x11
,
613 const char *szLab
, t_id id
,
614 int nitems
, t_id items
[],
615 int x0
, int y0
, int w
, int h
, int bw
)
622 h
= XTextHeight(x11
->font
)+OFFS_Y
;
626 w
= XTextWidth(x11
->font
, szLab
, std::strlen(szLab
))+2*OFFS_X
;
628 InitWin(&(dlgitem
->win
), x0
, y0
, w
, h
, bw
, szLab
);
629 dlgitem
->GroupID
= id
;
631 dlgitem
->type
= edlgGB
;
632 dlgitem
->u
.groupbox
.nitems
= nitems
;
633 snew(dlgitem
->u
.groupbox
.item
, nitems
);
634 std::memcpy((char *)dlgitem
->u
.groupbox
.item
, (char *)items
,
635 nitems
*sizeof(items
[0]));
636 dlgitem
->WndProc
= WndProcGB
;
641 t_dlgitem
*CreateCheckBox(t_x11
*x11
,
642 const char *szLab
, bool bCheckedInitial
, t_id id
,
644 int x0
, int y0
, int w
, int h
, int bw
)
651 h
= XTextHeight(x11
->font
)+OFFS_Y
;
655 w
= XTextWidth(x11
->font
, szLab
, std::strlen(szLab
))+OFFS_X
+h
;
657 InitWin(&(dlgitem
->win
), x0
, y0
, w
, h
, bw
, szLab
);
659 dlgitem
->GroupID
= groupid
;
660 dlgitem
->type
= edlgCB
;
661 dlgitem
->u
.checkbox
.bChecked
= bCheckedInitial
;
662 dlgitem
->WndProc
= WndProcCB
;
667 t_dlgitem
*CreatePixmap(Pixmap pm
, t_id id
,
668 t_id
/*groupid*/, int x0
, int y0
, int w
, int h
, int bw
)
673 InitWin(&(dlgitem
->win
), x0
, y0
, w
, h
, bw
, nullptr);
675 dlgitem
->type
= edlgPM
;
676 dlgitem
->u
.pixmap
.pm
= pm
;
677 dlgitem
->WndProc
= DefWndProc
;
682 t_dlgitem
*CreateStaticText(t_x11
*x11
,
683 int nlines
, const char * const *lines
, t_id id
,
685 int x0
, int y0
, int w
, int h
, int bw
)
693 h
= (XTextHeight(x11
->font
)+OFFS_Y
)*nlines
+OFFS_Y
;
697 for (i
= 0; (i
< nlines
); i
++)
699 w
= std::max(w
, XTextWidth(x11
->font
, lines
[i
], std::strlen(lines
[i
])));
703 InitWin(&(dlgitem
->win
), x0
, y0
, w
, h
, bw
, nullptr);
705 dlgitem
->GroupID
= groupid
;
706 dlgitem
->type
= edlgST
;
707 dlgitem
->u
.statictext
.nlines
= nlines
;
708 snew(dlgitem
->u
.statictext
.lines
, nlines
);
709 for (i
= 0; (i
< nlines
); i
++)
711 dlgitem
->u
.statictext
.lines
[i
] = gmx_strdup(lines
[i
]);
713 dlgitem
->WndProc
= WndProcST
;
718 t_dlgitem
*CreateEditText(t_x11
*x11
,
720 int screenbuf
, char *buf
, t_id id
, t_id groupid
,
721 int x0
, int y0
, int w
, int h
, int bw
)
729 h
= XTextHeight(x11
->font
)+OFFS_Y
;
735 snew(test
, screenbuf
);
736 std::memset(test
, 'w', screenbuf
);
737 w
= XTextWidth(x11
->font
, test
, screenbuf
)+
738 XTextWidth(x11
->font
, title
, std::strlen(title
))+
742 InitWin(&(dlgitem
->win
), x0
, y0
, w
, h
, bw
, title
);
744 dlgitem
->GroupID
= groupid
;
745 dlgitem
->type
= edlgET
;
746 et
= &(dlgitem
->u
.edittext
);
747 snew(et
->buf
, STRLEN
);
748 std::strcpy(et
->buf
, buf
);
749 et
->buflen
= screenbuf
;
751 et
->bChanged
= false;
752 dlgitem
->WndProc
= WndProcET
;
757 #define SC(src) (strlen(src) ? gmx_strdup(src) : NULL)
759 void SetDlgitemOpts(t_dlgitem
*dlgitem
, bool bUseMon
,
760 char *set
, char *get
, char *help
)
762 dlgitem
->bUseMon
= bUseMon
;
763 dlgitem
->set
= SC(set
);
764 dlgitem
->get
= SC(get
);
765 dlgitem
->help
= SC(help
);
767 std::printf("Help is: '%s'\n", dlgitem
->help
);