1 /****************************************************************************
2 **
3 *W popdial.c XGAP source Frank Celler
4 **
5 **
6 *Y Copyright 1995-1997, Lehrstuhl D fuer Mathematik, RWTH Aachen, Germany
7 *Y Copyright 1997, Frank Celler, Huerth, Germany
8 **
9 ** This file contains functions for popping up dialogs. Two functions are
10 ** exported:
11 **
12 ** CreatePopupDialog( <app>, <top>, <name>, <bt>, <def>, <pix> )
13 ** -------------------------------------------------------------
14 **
15 ** 'CreatePopupDialog' creates a popup dialog structure. A popup shell of
16 ** type "transientShellWidgetClass" is created together with a dialog widget
17 ** and buttons according to <bt>. None of these widgets are realised, this
18 ** is done by calling 'PopupDialog'. The default button activated by
19 ** pressing "return" is <def>.
20 **
21 ** Possible buttons are: PD_YES, PD_NO, PD_OK, PD_CANCEL, PD_ABORT, PD_RETRY
22 ** PD_APPEND, PD_OVERWRITE
23 **
24 ** PopupDialog( <dialog>, <message>, <deflt>, <result> )
25 ** -----------------------------------------------------
26 **
27 ** 'PopupDialog' will pop up a dialog created with 'CreatePopupDialog'. It
28 ** then grabs the keyboard and returns only if a button or "return" is
29 ** pressed. A pointer to the result is stored in <result> and the number of
30 ** the button pressed is returned. If "return" was hit by the user the
31 ** button number is the number given as <def> in 'CreatePopupDialog'.
32 **
33 ** The layout of the popup dialog is basically:
34 **
35 ** +-----------------------------------------+
36 ** | |
37 ** | pixmap some text <message> |
38 ** | <pix> |
39 ** | |
40 ** | [[[ INPUT FIELD (default: <deflt>) ]]] |
41 ** | |
42 ** | Btn1 Btn2 ... BtnN |
43 ** | |
44 ** +-----------------------------------------+
45 **
46 ** PopupDialogBrokenWM()
47 ** ---------------------
48 **
49 ** Some window manager don't handle transient shell widgets correctly. In
50 ** this case calling 'PopupDialogBrokenWM' will toggle a flag such that
51 ** a override shell widet is used instead.
52 */
53 #include "utils.h"
54 #include "popdial.h" /* this package */
55
56
57 /****************************************************************************
58 **
59
60 *F ButtonSelected( <w>, <cld>, <cd> ) . . . . . . callback for button click
61 */
62 static struct { String name; Int flag; } buttons[] =
63 {
64 { "yes", PD_YES },
65 { "no", PD_NO },
66 { "OK", PD_OK },
67 { "cancel", PD_CANCEL },
68 { "abort", PD_ABORT },
69 { "retry", PD_RETRY },
70 { "append", PD_APPEND },
71 { "overwrite", PD_OVERWRITE }
72 };
73
ButtonSelected(w,cld,cd)74 static void ButtonSelected ( w, cld, cd )
75 Widget w;
76 XtPointer cld;
77 XtPointer cd;
78 {
79 Int i;
80 Int * res = (int*) cld;
81 String name;
82
83 /* find name in <buttons> and set result */
84 XtVaGetValues( w, XtNlabel, (XtArgVal)&name, (String)NULL );
85 for ( i = 0; i < XtNumber(buttons); i++ )
86 if ( ! strcmp( buttons[i].name, name ) )
87 (*res) |= buttons[i].flag;
88 }
89
90
91 /****************************************************************************
92 **
93 *F CreatePopupDialog( <app>, <top>, <name>, <button>, <def>, <pix> ) create
94 */
95 #include "bitmaps/return.bm"
96
97 static Boolean BrokenWM = False;
98
CreatePopupDialog(app,top,name,bt,def,pix)99 TypePopupDialog CreatePopupDialog ( app, top, name, bt, def, pix )
100 XtAppContext app;
101 Widget top;
102 String name;
103 Int bt;
104 Int def;
105 Pixmap pix;
106 {
107 Display * dp;
108 TypePopupDialog dialog;
109 Int i;
110 static Pixmap symbol = 0;
111
112
113 /* create pixmap for default button */
114 if ( symbol == 0 )
115 {
116 dp = XtDisplay(top);
117 symbol = XCreateBitmapFromData( dp, DefaultRootWindow(dp),
118 return_bits, return_width, return_height );
119 }
120
121 /* create a new popup variable */
122 dialog = (TypePopupDialog) XtMalloc( sizeof( struct _popup_dialog ) );
123 dialog->topLevel = top;
124
125 if ( BrokenWM )
126 dialog->popupShell = XtVaCreatePopupShell(
127 name, overrideShellWidgetClass, top,
128 XtNallowShellResize, (XtArgVal)True,
129 (String)NULL );
130 else
131 dialog->popupShell = XtVaCreatePopupShell(
132 name, transientShellWidgetClass, top,
133 XtNallowShellResize, (XtArgVal)True,
134 XtNtransientFor, (XtArgVal)top,
135 (String)NULL );
136 if ( pix == 0 )
137 dialog->dialog = XtVaCreateManagedWidget(
138 "xgapDialog", dialogWidgetClass,
139 dialog->popupShell,
140 (String)NULL );
141 else
142 dialog->dialog = XtVaCreateManagedWidget(
143 "xgapDialog", dialogWidgetClass,
144 dialog->popupShell,
145 XtNicon, (XtArgVal)pix,
146 (String)NULL );
147 dialog->button = bt;
148 dialog->context = app;
149 dialog->defaultButton = def;
150
151 /* add buttons to the dialog */
152 for ( i = 0; i < XtNumber(buttons); i++ )
153 if ( bt & buttons[i].flag )
154 {
155 if ( buttons[i].flag == def )
156 dialog->buttons[i] = XtVaCreateManagedWidget(
157 buttons[i].name, commandWidgetClass,
158 dialog->dialog,
159 XtNleftBitmap, (XtArgVal)symbol,
160 (String)NULL );
161 else
162 dialog->buttons[i] = XtVaCreateManagedWidget(
163 buttons[i].name, commandWidgetClass,
164 dialog->dialog,
165 (String)NULL );
166 XtAddCallback( dialog->buttons[i],
167 XtNcallback,
168 ButtonSelected,
169 &(dialog->result) );
170 }
171 else
172 dialog->buttons[i] = 0;
173 return dialog;
174 }
175
176
177 /****************************************************************************
178 **
179 *V NormalFont . . . . . . . . . . . . . . . . . normal font for text output
180 **
181 ** see xcmds.c, imported here by Max 11.3.1999, see below
182 */
183 extern XFontStruct * NormalFont;
184
185 /****************************************************************************
186 **
187 *F PopupDialogBrokenWM() . . . . . . . . . . . . . . toggle <BrokenWM> flag
188 */
PopupDialogBrokenWM()189 void PopupDialogBrokenWM ( )
190 {
191 BrokenWM = ! BrokenWM;
192 }
193
194
195 /****************************************************************************
196 **
197 *F PopupDialog( <dialog>, <message>, <deflt>, <result> ) . . . . . . . do it
198 */
199 static Cursor BlobCursor = 0;
200
PopupDialog(dialog,message,deflt,result)201 Int PopupDialog ( dialog, message, deflt, result )
202 TypePopupDialog dialog;
203 String message;
204 String deflt;
205 String * result;
206 {
207 Display * display;
208 Position x1, y1, tmp;
209 Dimension w1, h1, bw;
210 Window root;
211 Window child;
212 Int x2, y2, x3, y3;
213 UInt bt;
214 Int i;
215 Int textlen, deflen;
216
217 /* create font cursor */
218 display = XtDisplay(dialog->popupShell);
219 if ( BlobCursor == 0 )
220 BlobCursor = XCreateFontCursor( display, XC_dot );
221
222 /* set message and default answer in dialog */
223 /* Changes by Max: 11.3.1999:
224 XtVaSetValues( dialog->dialog,
225 XtNlabel, " ",
226 XtNvalue, " ",
227 0, 0 );*/
228 XtVaSetValues( dialog->dialog,
229 XtNlabel, (XtArgVal)message,
230 XtNvalue, (XtArgVal)deflt,
231 (String)NULL );
232 /* get size of popup dialog */
233 XtVaGetValues( dialog->popupShell,
234 XtNwidth, (XtArgVal)&w1,
235 (String)NULL );
236 textlen = strlen(message)*NormalFont->max_bounds.width + 80;
237 deflen = strlen(deflt)*NormalFont->max_bounds.width + 60;
238 if (textlen > deflen) {
239 if (textlen < w1)
240 textlen = w1;
241 } else {
242 if (deflen < w1)
243 textlen = w1;
244 else
245 textlen = deflen;
246 }
247 XtVaSetValues( dialog->dialog,
248 XtNwidth,textlen,
249 0,NULL );
250 /* End of changes by Max. */
251
252 XtRealizeWidget( dialog->popupShell );
253
254 /* get size of popup dialog */
255 XtVaGetValues( dialog->popupShell,
256 XtNwidth, (XtArgVal)&w1,
257 XtNheight, (XtArgVal)&h1,
258 XtNborderWidth, (XtArgVal)&bw,
259 (String)NULL );
260
261 /* get position of the mouse pointer */
262 XQueryPointer( display, XtWindow(dialog->popupShell),
263 &root, &child, &x2, &y2, &x3, &y3, &bt );
264
265 /* find a nice position for the dialog */
266 tmp = DisplayWidth( display, DefaultScreen(display) );
267 x1 = x2 - (bw+w1)/2;
268 if ( tmp-w1-2*bw < x1 ) x1 = tmp-w1-2*bw;
269 if ( x1 < 0 ) x1 = 0;
270 tmp = DisplayHeight( display, DefaultScreen(display) );
271 y1 = y2 - (bw+h1)/2;
272 if ( tmp-h1-2*bw < y1 ) y1 = tmp-h1-2*bw;
273 if ( y1 < 0 ) y1 = 0;
274
275 /* move the popup dialog to this position */
276 XtVaSetValues( dialog->popupShell,
277 XtNx, (XtArgVal)x1,
278 XtNy, (XtArgVal)y1,
279 (String)NULL );
280
281 /* pop up shell */
282 XtPopup( dialog->popupShell, XtGrabExclusive );
283 for ( i = 0; i < XtNumber(buttons); i++ )
284 if ( dialog->buttons[i] )
285 XDefineCursor( display,
286 XtWindow(dialog->buttons[i]), BlobCursor );
287
288
289 /* and grab keyboard */
290 XGrabKeyboard( display, XtWindow(dialog->dialog), False,
291 GrabModeAsync, GrabModeAsync, CurrentTime );
292
293 /* wait until at least one button is selected */
294 dialog->result = 0;
295 while ( ( dialog->result & dialog->button ) == 0 )
296 {
297 XEvent event;
298 char str[128];
299 KeySym keysym;
300 Int len;
301
302 /* get next application event */
303 XtAppNextEvent(dialog->context, &event);
304
305 /* is the event a key event */
306 if ( event.type == KeyPress )
307 {
308 if ( dialog->defaultButton != 0 )
309 {
310
311 /* convert key event into text string and check for return */
312 len = XLookupString((XKeyEvent*)&event,str,128,&keysym,0);
313 if ( len != 0 && ( str[0] == '\n' || str[0] == '\r' ) )
314 {
315 dialog->result |= dialog->defaultButton;
316 continue;
317 }
318 }
319 }
320
321 /* dipatch event normally */
322 XtDispatchEvent(&event);
323 }
324
325 /* return answer string in <result> */
326 if ( result )
327 *result = XawDialogGetValueString(dialog->dialog);
328
329 /* remove pop up menu from screen */
330 XtPopdown(dialog->popupShell);
331 return dialog->result & dialog->button;
332 }
333
334
335 /****************************************************************************
336 **
337
338 *E popdial.c . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here
339 */
340
341