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, 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.
48 #include "gmx_fatal.h"
49 #include "gromacs/utility/smalloc.h"
56 static t_dlgitem *newitem(void)
65 /*****************************
67 * Window Procedures and helpful functions
69 ****************************/
70 static void ShowCaret(t_x11 *x11, t_dlgitem *dlgitem)
74 if (dlgitem->type == edlgET)
78 et = &(dlgitem->u.edittext);
79 x = XTextWidth(x11->font, dlgitem->win.text, strlen(dlgitem->win.text))+XCARET+
80 XTextWidth(x11->font, (char*) &(et->buf[et->strbegin]), et->pos);
81 y1 = (dlgitem->win.height-XTextHeight(x11->font))/2;
82 y2 = (dlgitem->win.height-y1);
84 XDrawLine(x11->disp, dlgitem->win.self, x11->gc, x-XCARET, y1, x+XCARET, y1);
85 XDrawLine(x11->disp, dlgitem->win.self, x11->gc, x, y1, x, y2);
86 XDrawLine(x11->disp, dlgitem->win.self, x11->gc, x-XCARET, y2, x+XCARET, y2);
90 static void HideCaret(t_x11 *x11, t_dlgitem *dlgitem)
92 XSetForeground(x11->disp, x11->gc, x11->bg);
93 ShowCaret(x11, dlgitem);
94 XSetForeground(x11->disp, x11->gc, x11->fg);
97 static int DefWndProc(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
99 XComposeStatus status;
104 printf("DefWndProc\n");
111 if (HelpPressed(event))
117 XLookupString(&(event->xkey), c, BUFSIZE, &keysym, &status);
118 if ((keysym == XK_Return) || (keysym == XK_KP_Enter))
125 dlgitem->win.bFocus = true;
126 ShowCaret(x11, dlgitem);
127 /* LightBorder(x11->disp,dlgitem->win.self,x11->fg); */
130 dlgitem->win.bFocus = false;
131 HideCaret(x11, dlgitem);
132 /* LightBorder(x11->disp,dlgitem->win.self,x11->bg); */
135 XBell(x11->disp, 50);
140 static int WndProcBN(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
145 if (dlgitem->type != edlgBN)
147 gmx_incons("button processing");
149 win = &(dlgitem->win);
150 w = XTextWidth(x11->font, win->text, strlen(win->text));
151 x = (win->width-w)/2;
152 th = XTextHeight(x11->font)+OFFS_Y;
156 RectWin(x11->disp, x11->gc, win, x11->fg);
157 TextInRect(x11, win->self, win->text, 0, 0, win->width, th, eXCenter, eYCenter);
162 XDrawLine(x11->disp, win->self, x11->gc, x-1, th, x+w, th);
165 XSetForeground(x11->disp, x11->gc, x11->bg);
166 XDrawLine(x11->disp, win->self, x11->gc, x-1, th, x+w, th);
167 XSetForeground(x11->disp, x11->gc, x11->fg);
170 return DefWndProc(x11, dlgitem, event);
175 static int WndProcRB(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
181 if (dlgitem->type != edlgRB)
183 gmx_incons("radiobutton processing");
185 rb = &(dlgitem->u.radiobutton);
186 win = &(dlgitem->win);
194 XClearArea(x11->disp, win->self, x-rad, y-rad, x+rad, y+rad, False);
198 XFillCircle(x11->disp, win->self, x11->gc, x, y, rad);
200 XDrawCircle(x11->disp, win->self, x11->gc, x, y, rad);
202 TextInRect(x11, win->self, win->text, x, 0, win->width-x, win->height,
210 XBell(x11->disp, 50);
216 return DefWndProc(x11, dlgitem, event);
221 static int WndProcGB(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
226 if (dlgitem->type != edlgGB)
228 gmx_incons("gb processing");
230 win = &(dlgitem->win);
232 x = XTextWidth(x11->font, win->text, strlen(win->text));
233 y = XTextHeight(x11->font);
237 XSetForeground(x11->disp, x11->gc, x11->fg);
238 XDrawRoundRect(x11->disp, win->self, x11->gc, 0, y/2,
239 win->width-1, win->height-y/2-1);
240 XClearArea(x11->disp, win->self, OFFS_X, 0, x+OFFS_X, y, False);
241 TextInRect(x11, win->self, win->text, 2*OFFS_X, 0, x, y, eXCenter, eYCenter);
247 return DefWndProc(x11, dlgitem, event);
252 static int WndProcCB(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
258 if (dlgitem->type != edlgCB)
260 gmx_incons("check box processing");
262 cb = &(dlgitem->u.checkbox);
263 win = &(dlgitem->win);
272 XSetForeground(x11->disp, x11->gc, x11->fg);
273 XClearArea(x11->disp, win->self, x, y, w, h, False);
274 XDrawRectangle(x11->disp, win->self, x11->gc, x, y, w, h);
277 XDrawLine(x11->disp, win->self, x11->gc, x, y, x+w, y+h);
278 XDrawLine(x11->disp, win->self, x11->gc, x+w, y, x, y+h);
281 TextInRect(x11, win->self, win->text, x, 0, win->width-x, win->height,
285 cb->bChecked = !cb->bChecked;
291 return DefWndProc(x11, dlgitem, event);
296 static int WndProcST(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
302 if (dlgitem->type != edlgST)
304 gmx_incons("st processing");
306 st = &(dlgitem->u.statictext);
307 win = &(dlgitem->win);
312 dy = XTextHeight(x11->font)+OFFS_Y;
313 for (i = 0; (i < st->nlines); i++)
315 TextInRect(x11, win->self, st->lines[i],
316 0, OFFS_Y+i*dy, win->width, dy, eXLeft, eYCenter);
320 return DefWndProc(x11, dlgitem, event);
325 static bool insert(char *s, char c, int *pos)
332 /* +1 for zero termination */
333 for (i = sl+1; (i > *pos); i--)
344 static bool my_backspace(char *s, int *pos)
349 if ((sl > 0) && ((*pos) > 0))
351 for (i = *pos-1; (i < sl); i++)
355 (*pos) = std::max(0, (*pos)-1);
361 static bool my_delete(char *s, int *pos)
366 if ((sl > 0) && ((*pos) < sl))
368 for (i = *pos; (i < sl); i++)
377 static int WndProcET(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
382 char c[BUFSIZE+1], *bp;
385 int xp, xtitle, ewidth;
387 if (dlgitem->type != edlgET)
389 gmx_incons("st processing");
391 et = &(dlgitem->u.edittext);
392 win = &(dlgitem->win);
394 /* Copy string part that is visible into screen buffer */
395 for (i = 0; (i < et->buflen); i++)
397 scrbuf[i] = et->buf[i+et->strbegin];
404 XSetForeground(x11->disp, x11->gc, x11->fg);
405 xtitle = XTextWidth(x11->font, win->text, strlen(win->text));
406 ewidth = win->width-xtitle;
407 TextInRect(x11, win->self, win->text,
408 0, 0, xtitle-1, win->height, eXLeft, eYCenter);
409 XClearArea(x11->disp, win->self, xtitle, 0, ewidth+XCARET, win->height, False);
410 TextInRect(x11, win->self, scrbuf,
411 xtitle+XCARET, 0, ewidth, win->height, eXLeft, eYCenter);
417 ShowCaret(x11, dlgitem);
421 /* Calculate new position for caret */
422 et->pos = strlen(et->buf);
423 bp = strdup(et->buf);
424 xp = event->xbutton.x-XTextWidth(x11->font, win->text, strlen(win->text))-
426 while ((et->pos > 0) && (XTextWidth(x11->font, bp, strlen(bp)) > xp))
435 /* Check for HelpKey */
436 if (HelpPressed(event))
438 return DefWndProc(x11, dlgitem, event);
440 XLookupString(&(event->xkey), c, BUFSIZE, &keysym, NULL);
442 printf("Keysym: %x\n", keysym);
447 if (my_delete(et->buf, &(et->pos)))
454 XBell(x11->disp, 50);
458 if (my_backspace(et->buf, &(et->pos)))
465 XBell(x11->disp, 50);
477 if (strlen(et->buf) <= (unsigned int)et->buflen)
479 et->pos = strlen(et->buf);
483 et->pos = et->buflen;
484 et->strbegin = strlen(et->buf)-et->buflen;
489 et->pos = std::max(0, et->pos-1);
490 et->strbegin = std::min(et->strbegin, et->pos);
494 if ((et->pos < et->buflen) &&
495 (et->strbegin+et->buflen > (int)strlen(et->buf)))
499 else if ((et->buflen < (int)strlen(et->buf)) &&
500 (et->strbegin < (int)strlen(et->buf)-et->buflen))
513 if (insert(et->buf, c[0], &(et->pos)))
519 XBell(x11->disp, 50);
525 HideCaret(x11, dlgitem);
528 et->bChanged = false;
532 return DefWndProc(x11, dlgitem, event);
537 /*****************************
539 * Routines to create dialog items, all items have an id
540 * which you can use to extract info. It is possible to have
541 * multiple items with the same id but it may then not be possible
542 * to extract information.
543 * All routines take the position relative to the parent dlg
544 * and the size and border width.
545 * If the width and height are set to zero initially, they will
546 * be calculated and set by the routine. With the dlgitem manipulation
547 * routines listed below, the application can then move the items around
548 * on the dlg box, and if wished resize them.
550 ****************************/
551 t_dlgitem *CreateButton(t_x11 *x11,
552 const char *szLab, bool bDef, t_id id, t_id groupid,
553 int x0, int y0, int w, int h, int bw)
561 h = XTextHeight(x11->font)+2*OFFS_Y;
565 w = XTextWidth(x11->font, szLab, strlen(szLab))+2*OFFS_X;
569 snew(lab, strlen(szLab)+7); /* 6 for >> << and 1 for \0 */
570 sprintf(lab, ">> %s <<", szLab);
576 InitWin(&(dlgitem->win), x0, y0, w, h, bw, szLab);
579 dlgitem->GroupID = groupid;
580 dlgitem->type = edlgBN;
581 dlgitem->u.button.bDefault = bDef;
582 dlgitem->WndProc = WndProcBN;
587 t_dlgitem *CreateRadioButton(t_x11 *x11,
588 const char *szLab, bool bSet, t_id id,
590 int x0, int y0, int w, int h, int bw)
597 h = XTextHeight(x11->font)+OFFS_Y;
601 w = XTextWidth(x11->font, szLab, strlen(szLab))+OFFS_X+h;
603 InitWin(&(dlgitem->win), x0, y0, w, h, bw, szLab);
605 dlgitem->GroupID = groupid;
606 dlgitem->type = edlgRB;
607 dlgitem->u.radiobutton.bSelect = bSet;
608 dlgitem->WndProc = WndProcRB;
613 t_dlgitem *CreateGroupBox(t_x11 *x11,
614 const char *szLab, t_id id,
615 int nitems, t_id items[],
616 int x0, int y0, int w, int h, int bw)
623 h = XTextHeight(x11->font)+OFFS_Y;
627 w = XTextWidth(x11->font, szLab, strlen(szLab))+2*OFFS_X;
629 InitWin(&(dlgitem->win), x0, y0, w, h, bw, szLab);
630 dlgitem->GroupID = id;
632 dlgitem->type = edlgGB;
633 dlgitem->u.groupbox.nitems = nitems;
634 snew(dlgitem->u.groupbox.item, nitems);
635 memcpy((char *)dlgitem->u.groupbox.item, (char *)items,
636 nitems*sizeof(items[0]));
637 dlgitem->WndProc = WndProcGB;
642 t_dlgitem *CreateCheckBox(t_x11 *x11,
643 const char *szLab, bool bCheckedInitial, t_id id,
645 int x0, int y0, int w, int h, int bw)
652 h = XTextHeight(x11->font)+OFFS_Y;
656 w = XTextWidth(x11->font, szLab, strlen(szLab))+OFFS_X+h;
658 InitWin(&(dlgitem->win), x0, y0, w, h, bw, szLab);
660 dlgitem->GroupID = groupid;
661 dlgitem->type = edlgCB;
662 dlgitem->u.checkbox.bChecked = bCheckedInitial;
663 dlgitem->WndProc = WndProcCB;
668 t_dlgitem *CreatePixmap(Pixmap pm, t_id id,
669 t_id /*groupid*/, int x0, int y0, int w, int h, int bw)
674 InitWin(&(dlgitem->win), x0, y0, w, h, bw, NULL);
676 dlgitem->type = edlgPM;
677 dlgitem->u.pixmap.pm = pm;
678 dlgitem->WndProc = DefWndProc;
683 t_dlgitem *CreateStaticText(t_x11 *x11,
684 int nlines, const char * const *lines, t_id id,
686 int x0, int y0, int w, int h, int bw)
694 h = (XTextHeight(x11->font)+OFFS_Y)*nlines+OFFS_Y;
698 for (i = 0; (i < nlines); i++)
700 w = std::max(w, XTextWidth(x11->font, lines[i], strlen(lines[i])));
704 InitWin(&(dlgitem->win), x0, y0, w, h, bw, NULL);
706 dlgitem->GroupID = groupid;
707 dlgitem->type = edlgST;
708 dlgitem->u.statictext.nlines = nlines;
709 snew(dlgitem->u.statictext.lines, nlines);
710 for (i = 0; (i < nlines); i++)
712 dlgitem->u.statictext.lines[i] = strdup(lines[i]);
714 dlgitem->WndProc = WndProcST;
719 t_dlgitem *CreateEditText(t_x11 *x11,
721 int screenbuf, char *buf, t_id id, t_id groupid,
722 int x0, int y0, int w, int h, int bw)
730 h = XTextHeight(x11->font)+OFFS_Y;
736 snew(test, screenbuf);
737 memset(test, 'w', screenbuf);
738 w = XTextWidth(x11->font, test, screenbuf)+
739 XTextWidth(x11->font, title, strlen(title))+
743 InitWin(&(dlgitem->win), x0, y0, w, h, bw, title);
745 dlgitem->GroupID = groupid;
746 dlgitem->type = edlgET;
747 et = &(dlgitem->u.edittext);
748 snew(et->buf, STRLEN);
749 strcpy(et->buf, buf);
750 et->buflen = screenbuf;
752 et->bChanged = false;
753 dlgitem->WndProc = WndProcET;
758 #define SC(src) (strlen(src) ? strdup(src) : NULL)
760 void SetDlgitemOpts(t_dlgitem *dlgitem, bool bUseMon,
761 char *set, char *get, char *help)
763 dlgitem->bUseMon = bUseMon;
764 dlgitem->set = SC(set);
765 dlgitem->get = SC(get);
766 dlgitem->help = SC(help);
768 printf("Help is: '%s'\n", dlgitem->help);