1c9e2be55Smrg/* $XConsortium: popup.c,v 2.38 94/08/26 18:04:22 swick Exp $ 2c9e2be55Smrg * 3c9e2be55Smrg * 4c9e2be55Smrg * COPYRIGHT 1989 5c9e2be55Smrg * DIGITAL EQUIPMENT CORPORATION 6c9e2be55Smrg * MAYNARD, MASSACHUSETTS 7c9e2be55Smrg * ALL RIGHTS RESERVED. 8c9e2be55Smrg * 9c9e2be55Smrg * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND 10c9e2be55Smrg * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. 11c9e2be55Smrg * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR 12c9e2be55Smrg * ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. 13c9e2be55Smrg * 14c9e2be55Smrg * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT 15c9e2be55Smrg * RIGHTS, APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN 16c9e2be55Smrg * ADDITION TO THAT SET FORTH ABOVE. 17c9e2be55Smrg * 18c9e2be55Smrg * Permission to use, copy, modify, and distribute this software and its 19c9e2be55Smrg * documentation for any purpose and without fee is hereby granted, provided 20c9e2be55Smrg * that the above copyright notice appear in all copies and that both that 21c9e2be55Smrg * copyright notice and this permission notice appear in supporting 22c9e2be55Smrg * documentation, and that the name of Digital Equipment Corporation not be 23c9e2be55Smrg * used in advertising or publicity pertaining to distribution of the software 24c9e2be55Smrg * without specific, written prior permission. 25c9e2be55Smrg */ 26c9e2be55Smrg/* $XFree86$ */ 27c9e2be55Smrg 28c9e2be55Smrg/* popup.c -- Handle pop-up widgets. */ 29c9e2be55Smrg 30c9e2be55Smrg#include "xmh.h" 31c9e2be55Smrg#include "actions.h" 32c9e2be55Smrg 33c9e2be55Smrg#include <X11/Xaw/Cardinals.h> 34c9e2be55Smrg 35c9e2be55Smrgtypedef struct _PopupStatus { 36c9e2be55Smrg Widget popup; /* order of fields same as CommandStatusRec */ 37c9e2be55Smrg struct _LastInput lastInput; 38c9e2be55Smrg char* shell_command; /* NULL, or contains sh -c command */ 39c9e2be55Smrg} PopupStatusRec, *PopupStatus; 40c9e2be55Smrg 41c9e2be55Smrg/* these are just strings which are used more than one place in the code */ 42c9e2be55Smrgstatic String XmhNconfirm = "confirm"; 43c9e2be55Smrgstatic String XmhNdialog = "dialog"; 44c9e2be55Smrgstatic String XmhNerror = "error"; 45c9e2be55Smrgstatic String XmhNnotice = "notice"; 46c9e2be55Smrgstatic String XmhNokay = "okay"; 47c9e2be55Smrgstatic String XmhNprompt = "prompt"; 48c9e2be55Smrgstatic String XmhNvalue = "value"; 49d859ff80Smrg 50c9e2be55Smrg/* The popups were originally parented from toplevel and neglected the 51c9e2be55Smrg * transientFor resource. In order not to break existing user resource 52c9e2be55Smrg * settings for the popups, transientFor is set independent of the parent, 53c9e2be55Smrg * which remains the toplevel widget. 54c9e2be55Smrg */ 55c9e2be55Smrg 56c9e2be55Smrgstatic void DeterminePopupPosition( 57c9e2be55Smrg Position *x_ptr, 58c9e2be55Smrg Position *y_ptr, 59c9e2be55Smrg Widget *transFor_return) /* return a suitable top level shell */ 60c9e2be55Smrg{ 61c9e2be55Smrg if (lastInput.win != (Window) -1) { 62c9e2be55Smrg if (transFor_return) { 63c9e2be55Smrg Widget source; 64c9e2be55Smrg source = XtWindowToWidget(XtDisplay(toplevel), lastInput.win); 65c9e2be55Smrg while (source && !XtIsWMShell(source)) 66c9e2be55Smrg source = XtParent(source); 67c9e2be55Smrg *transFor_return = source; 68c9e2be55Smrg } 69c9e2be55Smrg /* use the site of the last KeyPress or ButtonPress */ 70c9e2be55Smrg *x_ptr = lastInput.x; 71c9e2be55Smrg *y_ptr = lastInput.y; 72c9e2be55Smrg } else { 73c9e2be55Smrg Widget source; 74c9e2be55Smrg int i = 0; 75c9e2be55Smrg Dimension width, height; 76c9e2be55Smrg Arg args[2]; 77c9e2be55Smrg 78c9e2be55Smrg /* %%% need to keep track of last screen */ 79c9e2be55Smrg /* guess which screen and use the the center of it */ 80c9e2be55Smrg while (i < numScrns && !scrnList[i]->mapped) 81c9e2be55Smrg i++; 82c9e2be55Smrg source = ((i < numScrns) ? scrnList[i]->parent : toplevel); 83c9e2be55Smrg XtSetArg(args[0], XtNwidth, &width); 84c9e2be55Smrg XtSetArg(args[1], XtNheight, &height); 85c9e2be55Smrg XtGetValues(source, args, TWO); 86c9e2be55Smrg XtTranslateCoords(source, (Position) (width / 2), 87c9e2be55Smrg (Position) (height / 2), x_ptr, y_ptr); 88c9e2be55Smrg if (transFor_return) *transFor_return = source; 89c9e2be55Smrg } 90c9e2be55Smrg} 91c9e2be55Smrg 92c9e2be55Smrgstatic Boolean PositionThePopup( 93c9e2be55Smrg Widget popup, 94c9e2be55Smrg Position x, 95c9e2be55Smrg Position y) 96c9e2be55Smrg{ 97c9e2be55Smrg /* Hack. Fix up the position of the popup. The xmh app defaults file 98d859ff80Smrg * contains an Xmh*Geometry specification; the effects of that on 99c9e2be55Smrg * popups, and the lack of any user-supplied geometry specification for 100c9e2be55Smrg * popups, are mitigated here, by giving the popup shell a position. 101c9e2be55Smrg * (Xmh*Geometry is needed in case there is no user-supplied default.) 102c9e2be55Smrg * Returns True if an explicit geometry was inferred; false if the 103c9e2be55Smrg * widget was repositioned to (x,y). 104c9e2be55Smrg */ 105c9e2be55Smrg 106c9e2be55Smrg Arg args[4]; 107c9e2be55Smrg String top_geom, pop_geom; 108c9e2be55Smrg 109c9e2be55Smrg XtSetArg( args[0], XtNgeometry, &top_geom ); 110c9e2be55Smrg XtGetValues( toplevel, args, ONE ); 111c9e2be55Smrg XtSetArg( args[0], XtNgeometry, &pop_geom ); 112c9e2be55Smrg XtGetValues( popup, args, ONE ); 113c9e2be55Smrg 114c9e2be55Smrg if (pop_geom == NULL || pop_geom == top_geom) { 115c9e2be55Smrg /* if same db entry, then ... */ 116c9e2be55Smrg XtSetArg( args[0], XtNgeometry, (String) NULL); 117c9e2be55Smrg XtSetArg( args[1], XtNx, x); 118c9e2be55Smrg XtSetArg( args[2], XtNy, y); 119c9e2be55Smrg XtSetArg( args[3], XtNwinGravity, SouthWestGravity); 120c9e2be55Smrg XtSetValues( popup, args, FOUR); 121c9e2be55Smrg return False; 122c9e2be55Smrg } 123c9e2be55Smrg return True; 124c9e2be55Smrg} 125c9e2be55Smrg 126c9e2be55Smrg 127c9e2be55Smrgstatic void CenterPopupPosition( 128c9e2be55Smrg Widget widget, 129c9e2be55Smrg Widget popup, 130c9e2be55Smrg Position px, 131c9e2be55Smrg Position py) 132c9e2be55Smrg{ 133c9e2be55Smrg Position x, y; 134c9e2be55Smrg Position nx, ny; 135c9e2be55Smrg Arg args[3]; 136c9e2be55Smrg 137c9e2be55Smrg if (widget == NULL) return; 138c9e2be55Smrg XtSetArg(args[0], XtNx, &x); 139c9e2be55Smrg XtSetArg(args[1], XtNy, &y); 140c9e2be55Smrg XtGetValues(popup, args, TWO); 141c9e2be55Smrg if (x == px && y == py) { 142c9e2be55Smrg 143c9e2be55Smrg /* Program sets geometry. Correct our earlier calculations. */ 144c9e2be55Smrg 145c9e2be55Smrg nx = (GetWidth(widget) - GetWidth(popup)) / 2; 146c9e2be55Smrg ny = (GetHeight(widget) - GetHeight(popup)) / 2; 147c9e2be55Smrg if (nx < 0) nx = 0; 148c9e2be55Smrg if (ny < 0) ny = 0; 149c9e2be55Smrg XtTranslateCoords(widget, nx, ny, &x, &y); 150c9e2be55Smrg XtSetArg(args[0], XtNx, x); 151c9e2be55Smrg XtSetArg(args[1], XtNy, y); 152c9e2be55Smrg XtSetArg(args[2], XtNwinGravity, CenterGravity); 153c9e2be55Smrg XtSetValues(popup, args, THREE); 154c9e2be55Smrg } 155c9e2be55Smrg} 156d859ff80Smrg 157c9e2be55Smrg 158c9e2be55Smrg/* Insure that the popup is wholly showing on the screen. 159c9e2be55Smrg Optionally center the widget horizontally and/or vertically 160c9e2be55Smrg on current position. 161c9e2be55Smrg */ 162c9e2be55Smrg 163c9e2be55Smrgstatic void InsureVisibility( 164c9e2be55Smrg Widget popup, 165c9e2be55Smrg Widget popup_child, 166c9e2be55Smrg Position x, /* assert: current position = (x,y) */ 167c9e2be55Smrg Position y, 168c9e2be55Smrg Boolean centerX, 169c9e2be55Smrg Boolean centerY) 170c9e2be55Smrg{ 171c9e2be55Smrg Position root_x, root_y; 172c9e2be55Smrg Dimension width, height, border; 173c9e2be55Smrg Arg args[3]; 174c9e2be55Smrg 175c9e2be55Smrg 176c9e2be55Smrg XtSetArg( args[0], XtNwidth, &width ); 177c9e2be55Smrg XtSetArg( args[1], XtNheight, &height ); 178c9e2be55Smrg XtSetArg( args[2], XtNborderWidth, &border ); 179c9e2be55Smrg XtGetValues( popup, args, THREE ); 180c9e2be55Smrg 181c9e2be55Smrg XtTranslateCoords(popup_child, (Position)0, (Position)0, &root_x, &root_y); 182c9e2be55Smrg if (centerX) root_x -= width/2 + border; 183c9e2be55Smrg if (centerY) root_y -= height/2 + border; 184c9e2be55Smrg if (root_x < 0) root_x = 0; 185c9e2be55Smrg if (root_y < 0) root_y = 0; 186c9e2be55Smrg border <<= 1; 187c9e2be55Smrg 188c9e2be55Smrg if ((int)(root_x + width + border) > WidthOfScreen(XtScreen(toplevel))) { 189c9e2be55Smrg root_x = WidthOfScreen(XtScreen(toplevel)) - width - border; 190c9e2be55Smrg } 191c9e2be55Smrg if ((int)(root_y + height + border) > HeightOfScreen(XtScreen(toplevel))) { 192c9e2be55Smrg root_y = HeightOfScreen(XtScreen(toplevel)) - height - border; 193c9e2be55Smrg } 194c9e2be55Smrg 195c9e2be55Smrg if (root_x != x || root_y != y) { 196c9e2be55Smrg XtSetArg( args[0], XtNx, root_x ); 197c9e2be55Smrg XtSetArg( args[1], XtNy, root_y ); 198c9e2be55Smrg XtSetValues( popup, args, TWO ); 199c9e2be55Smrg } 200c9e2be55Smrg} 201c9e2be55Smrg 202c9e2be55Smrg 203c9e2be55Smrg/*ARGSUSED*/ 204c9e2be55Smrgvoid DestroyPopup( 205c9e2be55Smrg Widget widget, /* unused */ 206c9e2be55Smrg XtPointer client_data, 207c9e2be55Smrg XtPointer call_data) /* unused */ 208c9e2be55Smrg{ 209c9e2be55Smrg Widget popup = (Widget) client_data; 210c9e2be55Smrg XtPopdown(popup); 211c9e2be55Smrg XtDestroyWidget(popup); 212c9e2be55Smrg} 213c9e2be55Smrg 214c9e2be55Smrgvoid WMDeletePopup( 215c9e2be55Smrg Widget popup, /* transient shell */ 216c9e2be55Smrg XEvent* event) 217c9e2be55Smrg{ 218c9e2be55Smrg String shellName; 219c9e2be55Smrg String buttonName; 220c9e2be55Smrg Widget button; 221c9e2be55Smrg 222c9e2be55Smrg shellName = XtName(popup); 223c9e2be55Smrg if (strcmp(shellName, XmhNconfirm) == 0) 224c9e2be55Smrg buttonName = "*no"; 225c9e2be55Smrg else if (strcmp(shellName, XmhNprompt) == 0) 226c9e2be55Smrg buttonName = "*cancel"; 227c9e2be55Smrg else if (strcmp(shellName, XmhNnotice) == 0) 228c9e2be55Smrg buttonName = "*confirm"; 229c9e2be55Smrg else if (strcmp(shellName, XmhNerror) == 0) 230c9e2be55Smrg buttonName = "*OK"; 231c9e2be55Smrg else 232c9e2be55Smrg return; /* WM may kill us */ 233c9e2be55Smrg 234c9e2be55Smrg button = XtNameToWidget(popup, buttonName); 235c9e2be55Smrg if (! button) return; 236c9e2be55Smrg XtCallActionProc(button, "set", event, (String*)NULL, ZERO); 237c9e2be55Smrg XtCallActionProc(button, "notify", event, (String*)NULL, ZERO); 238c9e2be55Smrg XtCallActionProc(button, "unset", event, (String*)NULL, ZERO); 239c9e2be55Smrg} 240c9e2be55Smrg 241c9e2be55Smrgstatic void TheUsual( 242c9e2be55Smrg Widget popup) /* shell */ 243c9e2be55Smrg{ 244c9e2be55Smrg XtInstallAllAccelerators(popup, popup); 245c9e2be55Smrg XtAugmentTranslations(popup, app_resources.wm_protocols_translations); 246c9e2be55Smrg XtRealizeWidget(popup); 247c9e2be55Smrg XDefineCursor(XtDisplay(popup), XtWindow(popup), app_resources.cursor); 248d859ff80Smrg (void) XSetWMProtocols(XtDisplay(popup), XtWindow(popup), 249c9e2be55Smrg protocolList, XtNumber(protocolList)); 250c9e2be55Smrg} 251c9e2be55Smrg 252c9e2be55Smrg 253c9e2be55Smrg/*ARGSUSED*/ 254c9e2be55Smrgvoid XmhPromptOkayAction( 255c9e2be55Smrg Widget w, /* the "value" widget in the Dialog box */ 256c9e2be55Smrg XEvent *event, /* unused */ 257c9e2be55Smrg String *params, /* unused */ 258c9e2be55Smrg Cardinal *num_params) /* unused */ 259c9e2be55Smrg{ 260c9e2be55Smrg XtCallCallbacks(XtNameToWidget(XtParent(w), XmhNokay), XtNcallback, 261c9e2be55Smrg (XtPointer)XtParent(w)); 262c9e2be55Smrg} 263c9e2be55Smrg 264c9e2be55Smrg 265c9e2be55Smrgvoid PopupPrompt( 266c9e2be55Smrg Widget transientFor, /* required to be a top-level shell */ 267c9e2be55Smrg String question, /* the prompting string */ 268c9e2be55Smrg XtCallbackProc okayCallback) /* CreateFolder() */ 269c9e2be55Smrg{ 270c9e2be55Smrg Widget popup; 271c9e2be55Smrg Widget dialog; 272c9e2be55Smrg Widget value; 273c9e2be55Smrg Position x, y; 274c9e2be55Smrg Boolean positioned; 275c9e2be55Smrg Arg args[3]; 276c9e2be55Smrg static XtTranslations PromptTextTranslations = NULL; 277c9e2be55Smrg 278c9e2be55Smrg DeterminePopupPosition(&x, &y, (Widget*)NULL); 279c9e2be55Smrg XtSetArg(args[0], XtNallowShellResize, True); 280c9e2be55Smrg XtSetArg(args[1], XtNinput, True); 281c9e2be55Smrg XtSetArg(args[2], XtNtransientFor, transientFor); 282c9e2be55Smrg popup = XtCreatePopupShell(XmhNprompt, transientShellWidgetClass, toplevel, 283c9e2be55Smrg args, THREE); 284c9e2be55Smrg positioned = PositionThePopup(popup, x, y); 285c9e2be55Smrg 286c9e2be55Smrg XtSetArg(args[0], XtNlabel, question); 287c9e2be55Smrg XtSetArg(args[1], XtNvalue, ""); 288c9e2be55Smrg dialog = XtCreateManagedWidget(XmhNdialog, dialogWidgetClass, popup, args, 289c9e2be55Smrg TWO); 290c9e2be55Smrg XtSetArg(args[0], XtNresizable, True); 291c9e2be55Smrg XtSetValues( XtNameToWidget(dialog, "label"), args, ONE); 292c9e2be55Smrg value = XtNameToWidget(dialog, XmhNvalue); 293c9e2be55Smrg XtSetValues( value, args, ONE); 294c9e2be55Smrg if (! PromptTextTranslations) 295c9e2be55Smrg PromptTextTranslations = XtParseTranslationTable 296c9e2be55Smrg ("<Key>Return: XmhPromptOkayAction()\n\ 297c9e2be55Smrg Ctrl<Key>R: no-op(RingBell)\n\ 298c9e2be55Smrg Ctrl<Key>S: no-op(RingBell)\n"); 299c9e2be55Smrg XtOverrideTranslations(value, PromptTextTranslations); 300c9e2be55Smrg 301c9e2be55Smrg XawDialogAddButton(dialog, XmhNokay, okayCallback, (XtPointer) dialog); 302c9e2be55Smrg XawDialogAddButton(dialog, "cancel", DestroyPopup, (XtPointer) popup); 303c9e2be55Smrg TheUsual(popup); 304c9e2be55Smrg InsureVisibility(popup, dialog, x, y, !positioned, False); 305c9e2be55Smrg XtPopup(popup, XtGrabNone); 306c9e2be55Smrg} 307c9e2be55Smrg 308c9e2be55Smrg 309c9e2be55Smrg/* ARGSUSED */ 310c9e2be55Smrgstatic void FreePopupStatus( 311c9e2be55Smrg Widget w, /* unused */ 312c9e2be55Smrg XtPointer closure, 313c9e2be55Smrg XtPointer call_data) /* unused */ 314c9e2be55Smrg{ 315c9e2be55Smrg PopupStatus popup = (PopupStatus)closure; 316c9e2be55Smrg XtPopdown(popup->popup); 317c9e2be55Smrg XtDestroyWidget(popup->popup); 318c9e2be55Smrg if (popup->shell_command) 319c9e2be55Smrg XtFree(popup->shell_command); 320c9e2be55Smrg XtFree((char *) closure); 321c9e2be55Smrg} 322c9e2be55Smrg 323c9e2be55Smrg 324c9e2be55Smrgvoid PopupNotice( 325c9e2be55Smrg String message, 326c9e2be55Smrg XtCallbackProc callback, 327c9e2be55Smrg XtPointer closure) 328c9e2be55Smrg{ 329c9e2be55Smrg PopupStatus popup_status = (PopupStatus)closure; 330c9e2be55Smrg Widget transientFor; 331c9e2be55Smrg Widget dialog; 332c9e2be55Smrg Widget value; 333c9e2be55Smrg Position x, y; 334c9e2be55Smrg Arg args[3]; 335c9e2be55Smrg char command[65], label[128]; 336c9e2be55Smrg 337c9e2be55Smrg if (popup_status == (PopupStatus)NULL) { 338c9e2be55Smrg popup_status = XtNew(PopupStatusRec); 339c9e2be55Smrg popup_status->lastInput = lastInput; 340c9e2be55Smrg popup_status->shell_command = (char*)NULL; 341c9e2be55Smrg } 342c9e2be55Smrg if (! popup_status->shell_command) { 343c9e2be55Smrg /* MH command */ 344c9e2be55Smrg if (sscanf( message, "%64s", command ) != 1) 345c9e2be55Smrg (void) strcpy( command, "system" ); 346c9e2be55Smrg else { 347c9e2be55Smrg int l = strlen(command); 348c9e2be55Smrg if (l && command[--l] == ':') 349c9e2be55Smrg command[l] = '\0'; 350c9e2be55Smrg } 35166d665a3Smrg snprintf(label, sizeof(label), "%.64s command returned:", command); 352c9e2be55Smrg } else { 353c9e2be55Smrg /* arbitrary shell command */ 354c9e2be55Smrg int len = strlen(popup_status->shell_command); 35566d665a3Smrg snprintf(label, sizeof(label), "%.88s %s\nshell command returned:", 35666d665a3Smrg popup_status->shell_command, 35766d665a3Smrg ((len > 88) ? "[truncated]" : "")); 358c9e2be55Smrg } 359c9e2be55Smrg 360c9e2be55Smrg DeterminePopupPosition(&x, &y, &transientFor); 361c9e2be55Smrg XtSetArg( args[0], XtNallowShellResize, True ); 362c9e2be55Smrg XtSetArg( args[1], XtNinput, True ); 363c9e2be55Smrg XtSetArg( args[2], XtNtransientFor, transientFor); 364c9e2be55Smrg popup_status->popup = XtCreatePopupShell(XmhNnotice, 365c9e2be55Smrg transientShellWidgetClass, toplevel, args, THREE); 366c9e2be55Smrg PositionThePopup(popup_status->popup, x, y); 367c9e2be55Smrg 368c9e2be55Smrg XtSetArg( args[0], XtNlabel, label ); 369c9e2be55Smrg XtSetArg( args[1], XtNvalue, message ); 370c9e2be55Smrg dialog = XtCreateManagedWidget(XmhNdialog, dialogWidgetClass, 371c9e2be55Smrg popup_status->popup, args, TWO); 372c9e2be55Smrg 373c9e2be55Smrg /* The text area of the dialog box will not be editable. */ 374c9e2be55Smrg value = XtNameToWidget(dialog, XmhNvalue); 375c9e2be55Smrg XtSetArg( args[0], XtNeditType, XawtextRead); 376c9e2be55Smrg XtSetArg( args[1], XtNdisplayCaret, False); 377c9e2be55Smrg XtSetValues( value, args, TWO); 378c9e2be55Smrg XtOverrideTranslations(value, NoTextSearchAndReplace); 379c9e2be55Smrg 380c9e2be55Smrg XawDialogAddButton( dialog, XmhNconfirm, 381c9e2be55Smrg ((callback != (XtCallbackProc) NULL) 382d859ff80Smrg ? callback : (XtCallbackProc) FreePopupStatus), 383c9e2be55Smrg (XtPointer) popup_status 384c9e2be55Smrg ); 385c9e2be55Smrg 386c9e2be55Smrg TheUsual(popup_status->popup); 387c9e2be55Smrg InsureVisibility(popup_status->popup, dialog, x, y, False, False); 388c9e2be55Smrg XtPopup(popup_status->popup, XtGrabNone); 389c9e2be55Smrg} 390c9e2be55Smrg 391c9e2be55Smrg 392c9e2be55Smrgvoid PopupConfirm( 393c9e2be55Smrg Widget center_widget, /* where to center; may be NULL */ 394c9e2be55Smrg String question, 395c9e2be55Smrg XtCallbackList affirm_callbacks, 396c9e2be55Smrg XtCallbackList negate_callbacks) 397c9e2be55Smrg{ 398c9e2be55Smrg Widget popup; 399c9e2be55Smrg Widget dialog; 400c9e2be55Smrg Widget button; 401c9e2be55Smrg Widget transientFor; 402c9e2be55Smrg Position x, y; 403c9e2be55Smrg Arg args[3]; 404c9e2be55Smrg static XtCallbackRec callbacks[] = { 405c9e2be55Smrg {DestroyPopup, (XtPointer) NULL}, 406c9e2be55Smrg {(XtCallbackProc) NULL, (XtPointer) NULL} 407c9e2be55Smrg }; 408c9e2be55Smrg 409c9e2be55Smrg DeterminePopupPosition(&x, &y, &transientFor); 410c9e2be55Smrg XtSetArg(args[0], XtNinput, True); 411c9e2be55Smrg XtSetArg(args[1], XtNallowShellResize, True); 412c9e2be55Smrg XtSetArg(args[2], XtNtransientFor, transientFor); 413c9e2be55Smrg popup = XtCreatePopupShell(XmhNconfirm, transientShellWidgetClass, 414c9e2be55Smrg toplevel, args, THREE); 415d859ff80Smrg PositionThePopup(popup, x, y); 416c9e2be55Smrg 417c9e2be55Smrg XtSetArg(args[0], XtNlabel, question); 418c9e2be55Smrg dialog = XtCreateManagedWidget(XmhNdialog, dialogWidgetClass, popup, args, 419c9e2be55Smrg ONE); 420d859ff80Smrg 421c9e2be55Smrg callbacks[0].closure = (XtPointer) popup; 422c9e2be55Smrg XtSetArg(args[0], XtNcallback, callbacks); 423d859ff80Smrg button = XtCreateManagedWidget("yes", commandWidgetClass, dialog, 424c9e2be55Smrg args, ONE); 425c9e2be55Smrg if (affirm_callbacks) 426c9e2be55Smrg XtAddCallbacks(button, XtNcallback, affirm_callbacks); 427c9e2be55Smrg 428d859ff80Smrg button = XtCreateManagedWidget("no", commandWidgetClass, dialog, 429c9e2be55Smrg args, ZERO); 430c9e2be55Smrg XtAddCallback(button, XtNcallback, DestroyPopup, (XtPointer) popup); 431c9e2be55Smrg if (negate_callbacks) 432c9e2be55Smrg XtAddCallbacks(button, XtNcallback, negate_callbacks); 433c9e2be55Smrg 434c9e2be55Smrg TheUsual(popup); 435c9e2be55Smrg CenterPopupPosition(center_widget ? center_widget : transientFor, 436c9e2be55Smrg popup, x, y); 437c9e2be55Smrg InsureVisibility(popup, dialog, x, y, False, False); 438c9e2be55Smrg XtPopup(popup, XtGrabNone); 439c9e2be55Smrg} 440c9e2be55Smrg 441c9e2be55Smrg 442c9e2be55Smrgvoid PopupError( 443c9e2be55Smrg Widget widget, /* transient for this top-level shell, or NULL */ 444c9e2be55Smrg String message) 445c9e2be55Smrg{ 446c9e2be55Smrg Widget transFor, error_popup, dialog; 447c9e2be55Smrg Position x, y; 448c9e2be55Smrg Boolean positioned; 449c9e2be55Smrg Arg args[3]; 450c9e2be55Smrg static XtCallbackRec callbacks[] = { 451c9e2be55Smrg {DestroyPopup, (XtPointer) NULL}, 452c9e2be55Smrg {(XtCallbackProc) NULL, (XtPointer) NULL} 453c9e2be55Smrg }; 454c9e2be55Smrg 455c9e2be55Smrg transFor = widget; 456c9e2be55Smrg DeterminePopupPosition(&x, &y, transFor ? (Widget*)NULL : &transFor); 457c9e2be55Smrg 458c9e2be55Smrg XtSetArg(args[0], XtNallowShellResize, True); 459c9e2be55Smrg XtSetArg(args[1], XtNinput, True); 460c9e2be55Smrg XtSetArg(args[2], XtNtransientFor, transFor); 461c9e2be55Smrg error_popup = XtCreatePopupShell(XmhNerror, transientShellWidgetClass, 462c9e2be55Smrg toplevel, args, THREE); 463c9e2be55Smrg positioned = PositionThePopup(error_popup, x, y); 464c9e2be55Smrg 465c9e2be55Smrg XtSetArg(args[0], XtNlabel, message); 466c9e2be55Smrg dialog = XtCreateManagedWidget(XmhNdialog, dialogWidgetClass, error_popup, 467c9e2be55Smrg args, ONE); 468c9e2be55Smrg callbacks[0].closure = (XtPointer) error_popup; 469c9e2be55Smrg XtSetArg(args[0], XtNcallback, callbacks); 470c9e2be55Smrg XawDialogAddButton(dialog, "OK", DestroyPopup, (XtPointer) error_popup); 471c9e2be55Smrg TheUsual(error_popup); 472c9e2be55Smrg InsureVisibility(error_popup, dialog, x, y, !positioned, !positioned); 473c9e2be55Smrg XtPopup(error_popup, XtGrabNone); 474c9e2be55Smrg} 475c9e2be55Smrg 476c9e2be55Smrg/*ARGSUSED*/ 477c9e2be55Smrgvoid PopupWarningHandler( 478c9e2be55Smrg String name, 479c9e2be55Smrg String type, 480c9e2be55Smrg String class, 481c9e2be55Smrg String msg, 482c9e2be55Smrg String *params, 483c9e2be55Smrg Cardinal *num) 484c9e2be55Smrg{ 485c9e2be55Smrg char *ptr; 486c9e2be55Smrg int i; 487c9e2be55Smrg String par[10]; 488c9e2be55Smrg char message[500]; 489c9e2be55Smrg char buffer[500]; 490c9e2be55Smrg static Boolean allowPopup = True; /* protect against recursion */ 491c9e2be55Smrg 492c9e2be55Smrg XtGetErrorDatabaseText(name, type, class, msg, buffer, 500); 493c9e2be55Smrg 494c9e2be55Smrg if (params && num && *num) { 495c9e2be55Smrg i = (*num <= 10) ? *num : 10; 496c9e2be55Smrg memmove( (char*)par, (char*)params, i * sizeof(String)); 497c9e2be55Smrg bzero( &par[i], (10-i) * sizeof(String)); 498c9e2be55Smrg if (*num > 10) 499c9e2be55Smrg par[9] = "(truncated)"; 50066d665a3Smrg snprintf(message, sizeof(message), buffer, par[0], par[1], par[2], 50166d665a3Smrg par[3], par[4], par[5], par[6], par[7], par[8], par[9]); 502c9e2be55Smrg ptr = message; 503c9e2be55Smrg } else { 504c9e2be55Smrg ptr = buffer; 505c9e2be55Smrg } 506c9e2be55Smrg if (allowPopup) { 507c9e2be55Smrg allowPopup = False; 508d859ff80Smrg PopupError((Widget)NULL, ptr); 509c9e2be55Smrg allowPopup = True; 510c9e2be55Smrg } else { 511c9e2be55Smrg fprintf(stderr, ptr); 512c9e2be55Smrg } 513c9e2be55Smrg} 514