/// <summary> The generic callback procedure, that marshals to the widget specific callback procedure. </summary> /// <param name="widget"> The widget, that initiated the callback procedure. <see cref="System.IntPtr"/> </param> /// <param name="clientData"> Additional callback data from the client. <see cref="System.IntPtr"/> </param> /// <param name="callData"> Additional data defined for the call. <see cref="System.IntPtr"/> </param> /// <remarks> The prototype must match the XtCallbackProc delegate. </remarks> public static void MarshalCallback(IntPtr widget, IntPtr clientData, IntPtr callData) { // Debug code. // IntPtr hName = Xtlib.XtName (widget); // string sName = Marshal.PtrToStringAuto(hName); // Console.WriteLine (CLASS_NAME + "::MarshalCallback () INFORMATION: Widget name is: " + sName); if (_list.ContainsKey(widget)) { _list[widget] (widget, clientData, callData); return; } // Subsequent code is an extension for Motif. // Motif menu bars and menus assign "XmNsimpleCallback" to their child widgets. IntPtr parentWidget = Xtlib.XtParent(widget); if (parentWidget != IntPtr.Zero && _list.ContainsKey(parentWidget)) { _list[parentWidget] (widget, clientData, callData); return; } else { // Debug code. Console.WriteLine(CLASS_NAME + "::MarshalCallback () WARNING: Widget (" + Xtlib.XtNameAsString(widget) + ") pointer and widget's parent pointer are not registered."); } }
/// <summary> Register a "configure notify action" to application context, translate the "configure notify action", add/overwrite /// the shell widget's translation table and set windows manager protocol hook for the shell widget. </summary> /// <param name="appContext"> The application's context to register the action to. <see cref="System.IntPtr"/> </param> /// <param name="configureNotifyAction"> The action to register to the application's context. <see cref="XtActionProc"/> </param> /// <remarks> This method can be called *** BEFORE *** XtRealizeWidget (). </remarks> public void RegisterConfigureNotifyAction(IntPtr appContext, XtActionProc configureNotifyAction) { try { // Register (instance method) action procedure to runtime action marshaller and let it map the signal to the (global static) action procedure. IntPtr configureNotifyActionPtr = ActionMarshaler.Add(_shell, X11.XEventName.ConfigureNotify, configureNotifyAction); // Create an actions record, to provide the application's context with a "action-name" to "action-procedure" translation. XtActionsRec[] actionProcs = new XtActionsRec[] { new XtActionsRec(X11Utils.StringToSByteArray(XtWmShell.COFIGURE_NOTIFY_ACTION_NAME + "\0"), configureNotifyActionPtr) }; // Register the actions record to the application's context. Xtlib.XtAppAddActions(appContext, actionProcs, (XCardinal)1); // Create a compiled translation table, to provide the widget with a "message" to "action-name" translation. IntPtr translationTable = Xtlib.XtParseTranslationTable("<Configure>: " + XtWmShell.COFIGURE_NOTIFY_ACTION_NAME + "()"); // Merge new translations to the widget, overriding existing ones. Xtlib.XtOverrideTranslations(_shell, translationTable); } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } }
/// <summary> Implement the HandleDialogEnd event handler. </summary> /// <param name="label"> The label to set to the status bar. <see cref="System.String"/> </param> protected void HandleDlgDialogEnd_QueryForApplicationClose(XtDialog source) { if (source.Result == XtDialog.DialogResult.Ok) { Xtlib.exit(0); } }
/// <summary> The message box cancel callback procedure. </summary> /// <param name="widget"> The widget, that initiated the callback procedure. <see cref="System.IntPtr"/> </param> /// <param name="clientData"> Additional callback data from the client. <see cref="System.IntPtr"/> </param> /// <param name="callData"> Additional data defined for the call. <see cref="System.IntPtr"/> </param> public virtual void DialogCancel([In] IntPtr widget, [In] IntPtr client_data, [In] IntPtr call_data) { Xtlib.XtPopdown(_shell); _result = XtDialog.DialogResult.Cancel; OnDialogEnd(); Dispose(); }
/// <summary> The dialog specific close. </summary> public override void Close() { Xtlib.XtPopdown(_shell); _result = XtDialog.DialogResult.Cancel; OnDialogEnd(); Dispose(); }
// ############################################################################### // ### C O N S T R U C T I O N A N D I N I T I A L I Z A T I O N // ############################################################################### #region Construction /// <summary> The initializing constructor. </summary> /// <param name="toplevelShell"> The toplevel shell that owns the underlaying transient popup shell of this dialog. <see cref="XtApplicationShell"/> </param> /// <param name="toplevelShell"> The shell caption. <see cref="System.String"/> </param> public XtDialog(XtApplicationShell toplevelShell, string caption) { if (toplevelShell == null) { throw new ArgumentNullException("toplevelShell"); } _toplevelShell = toplevelShell; if (!string.IsNullOrEmpty(caption)) { Arg[] shellArgs = { new Arg(XtNames.XtNtitle, X11.X11Utils.StringToSByteArray(caption + "\0")) }; _shell = Xtlib.XtCreatePopupShell(SHELL_RESOURCE_NAME, Xtlib.XawTransientShellWidgetClass(), toplevelShell.Shell, shellArgs, (XCardinal)1); } else { _shell = Xtlib.XtCreatePopupShell(SHELL_RESOURCE_NAME, Xtlib.XawTransientShellWidgetClass(), toplevelShell.Shell, Arg.Zero, 0); } _toplevelShell.AssociatedShells.Add(this); }
// ############################################################################### // ### M E T H O D S // ############################################################################### #region Methods /// <summary> Alloc a color from the default colormap of the display's default screen. </summary> /// <param name="colorname"> The color to alloc. <see cref="System.String"/> </param> /// <returns> The color pixel on success, or the white pixel otherwise. <see cref="X11.TColor"/> </returns> public TColor AllocColorFromDefaultColormap(string colorname) { IntPtr display = Xtlib.XtDisplay(_shell); if (display == IntPtr.Zero) { return(TColor.FallbackWhite); } TInt scrnID = X11lib.XDefaultScreen(display); return(X11lib.XAllocClosestNamedColor(display, X11lib.XDefaultColormap(display, scrnID), colorname)); }
// ############################################################################### // ### M E T H O D S // ############################################################################### #region Methods /// <summary> Load the icon from indicated path and set it as shell icon. </summary> /// <returns> <c>true</c>, if icon was set, <c>false</c> otherwise. </returns> /// <param name='iconPath'> The icon path. </param> public bool SetShellIcon(string iconPath) { bool result = false; if (_shell == IntPtr.Zero) { Console.WriteLine(CLASS_NAME + "::SetShellIcon() ERROR: Member attribute '_shell' null."); return(result); } if (string.IsNullOrEmpty(iconPath)) { Console.WriteLine(CLASS_NAME + "::SetShellIcon() ERROR: Paramerter 'iconPath' null or empty."); return(result); } IntPtr display = Xtlib.XtDisplay(_shell); IntPtr window = Xtlib.XtWindow(_shell); TInt screenNumber = Xtlib.XDefaultScreen(display); using (X11Graphic appIcon = new X11Graphic(display, (int)screenNumber, IntPtr.Zero, X11lib.XDefaultDepth(display, screenNumber), iconPath)) { _appIconPixMap = appIcon.CreateIndependentGraphicPixmap(display, window); _appMaskPixMap = appIcon.CreateIndependentMaskPixmap(display, window); if (_appIconPixMap != IntPtr.Zero && _appMaskPixMap != IntPtr.Zero) { X11lib.XWMHints wmHints = new X11lib.XWMHints(); IntPtr wmAddr = X11lib.XAllocWMHints(ref wmHints); wmHints.flags = X11lib.XWMHintMask.IconPixmapHint | X11lib.XWMHintMask.IconPositionHint | X11lib.XWMHintMask.IconMaskHint; wmHints.icon_pixmap = _appIconPixMap; wmHints.icon_mask = _appMaskPixMap; wmHints.icon_x = 0; wmHints.icon_y = 0; X11lib.XSetWMHints(display, window, ref wmHints); X11lib.XFree(wmAddr); result = true; } else { Console.WriteLine(CLASS_NAME + "::SetShellIcon () ERROR: Can not create application icon."); } } return(result); }
/// <summary> Register a "delete window action" to application context, translate the "delete /// window action", add/overwrite the shell widget's translation table and set windows manager /// protocol hook for the shell widget. </summary> /// <param name="appContext"> The application's context to register the action to. /// <see cref="System.IntPtr"/> </param> /// <param name="deleteWindowAction"> The action to register to the application's context. /// <see cref="XtActionProc"/> </param> /// <remarks> This must be done *** AFTER *** XtRealizeWidget (). </remarks> public void RegisterDeleteWindowAction(IntPtr appContext, XtActionProc deleteWindowAction) { try { // Register (instance method) action procedure to runtime action marshaller // and let it map the signal to the (global static) action procedure. IntPtr deleteWindowActionPtr = ActionMarshaler.Add(_shell, X11.XEventName.ClientMessage, deleteWindowAction); // Create an actions record, to provide the application's context // with a "action-name" to "action-procedure" translation. XtActionsRec[] actionProcs = new XtActionsRec[] { new XtActionsRec(X11Utils.StringToSByteArray(XtWmShell.DELETE_WINDOW_ACTION_NAME + "\0"), deleteWindowActionPtr) }; // Register the actions record to the application's context. Xtlib.XtAppAddActions(appContext, actionProcs, (XCardinal)1); // Create a compiled translation table, to provide the widget with // a "message" to "action-name" translation. IntPtr translationTable = Xtlib.XtParseTranslationTable("<Message>WM_PROTOCOLS: " + XtWmShell.DELETE_WINDOW_ACTION_NAME + "()"); // Merge new translations to the widget, overriding existing ones. Xtlib.XtOverrideTranslations(_shell, translationTable); /// The delete message from the windows manager. Closing an app via window /// title functionality doesn't generate a window message - it only generates a /// window manager message, thot must be routed to the window (message loop). IntPtr wmDeleteMessage = IntPtr.Zero; // Hook the closing event from windows manager. // Must be done *** AFTER *** XtRealizeWidget () to determine display and window! wmDeleteMessage = X11lib.XInternAtom(Xtlib.XtDisplay(_shell), "WM_DELETE_WINDOW", false); if (X11lib.XSetWMProtocols(Xtlib.XtDisplay(_shell), Xtlib.XtWindow(_shell), ref wmDeleteMessage, (X11.TInt) 1) == 0) { Console.WriteLine(CLASS_NAME + "::RegisterDeleteWindowAction () " + "WARNING: Failed to register 'WM_DELETE_WINDOW' event."); } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } }
/// <summary> Initializing constructor. </summary> /// <param name="appResourceName"> The ressource name of the application. <see cref="System.String"/> </param> /// <param name="shellResourceName"> The ressource name of the root shell. <see cref="System.String"/> </param> /// <param name="fallbackResources"> The fallback ressources to apply. <see cref="Xt.XtFallbackRessources"/> </param> public XtApplicationShell(string appResourceName, string shellResourceName, Xt.XtFallbackRessources fallbackResources) { if (_instance != null) { Console.WriteLine(CLASS_NAME + "::ctr () ERROR: Already an instance created."); } _appResourceName = appResourceName; IntPtr argv = (string.IsNullOrEmpty(shellResourceName) ? IntPtr.Zero : (new XtStringArray(shellResourceName, '|')).Data); TInt argc = (TInt)(argv != IntPtr.Zero ? 1 : 0); _shell = Xtlib.XtAppInitialize(ref _appContext, _appResourceName, IntPtr.Zero, 0, ref argc, argv, fallbackResources.Marshal(), IntPtr.Zero, 0); _instance = this; }
// ############################################################################### // ### D E S T R U C T I O N // ############################################################################### #region Destruction /// <summary> IDisposable implementation. </summary> public override void Dispose() { Console.WriteLine(CLASS_NAME + "::Dispose ()"); // Memory and resources, that are assigned to underlaying Athena widget's // instance structure are destroyed by XtDestroyWidget (). // This typically inclused the GCs, pixmaps and local copies of strings. // They are typically assigned during XtCreateWidget () or XtSetValues (). if (_shell != IntPtr.Zero) { Xtlib.XtDestroyWidget(_shell); _shell = IntPtr.Zero; } this.DisposeByParent(); }
// ############################################################################### // ### A T T R I B U T E S // ############################################################################### #region Attributes #endregion // ############################################################################### // ### C O N S T R U C T I O N A N D I N I T I A L I Z A T I O N // ############################################################################### #region Construction /// <summary> The initializing constructor. </summary> /// <param name="toplevelShell"> The toplevel shell that owns the underlaying transient popup shell of this dialog. <see cref="XtApplicationShell"/> </param> /// <param name="toplevelShell"> The shell caption. <see cref="System.String"/> </param> public XtGrabExclusiveAthenaDialog(XtApplicationShell toplevelShell, string caption) : base(toplevelShell, caption) { if (toplevelShell == null) { throw new ArgumentNullException("toplevelShell"); } // The dialog widget needs the final size of all child widgets during layout calculation to prevent child widget overlapping. Or in other words: // Child widget overlapping will happen, if XtNicon is set after dialog widget's layout calculation, because XtMakeResizeRequest () can't be called. // Currently the dialog widget isn't realized and therefor it hasn't a window. That's why we use the toplevel shell's window instead. IntPtr logo = IntPtr.Zero; if (!(Xtlib.XtIsRealized(toplevelShell.Shell) == (TBoolean)0)) { IntPtr display = Xtlib.XtDisplay(toplevelShell.Shell); IntPtr window = Xtlib.XtWindow(toplevelShell.Shell); logo = X11lib.XCreateBitmapFromData(display, window, XtResources.BIG_EXCLAMATION_ICON_BITS, XtResources.BIG_ICON_WIDTH, XtResources.BIG_ICON_HEIGHT); } Arg[] formArgs = { new Arg(XtNames.XtNlabel, X11.X11Utils.StringToSByteArray("Enter data string:\0")), new Arg(XtNames.XtNvalue, X11.X11Utils.StringToSByteArray("\0")), new Arg(XtNames.XtNicon, (XtArgVal)logo) }; _dialogForm = Xtlib.XtCreateManagedWidget(DIALOG_RESOURCE_NAME, Xtlib.XawDialogWidgetClass(), _shell, formArgs, (XCardinal)3); Arg[] okArgs = { new Arg(XtNames.XtNlabel, X11.X11Utils.StringToSByteArray("OK\0")) }; _okCommand = Xtlib.XtCreateManagedWidget(_okCmdName, Xtlib.XawCommandWidgetClass(), _dialogForm, okArgs, (XCardinal)1); Xtlib.XtAddCallback(_okCommand, XtNames.XtNcallback, CallBackMarshaler.Add(_okCommand, this.DialogOk), IntPtr.Zero); Arg[] cancelArgs = { new Arg(XtNames.XtNlabel, X11.X11Utils.StringToSByteArray("Cancel\0")) }; _cancelCommand = Xtlib.XtCreateManagedWidget(_cancelCmdName, Xtlib.XawCommandWidgetClass(), _dialogForm, cancelArgs, (XCardinal)1); Xtlib.XtAddCallback(_cancelCommand, XtNames.XtNcallback, CallBackMarshaler.Add(_cancelCommand, this.DialogCancel), IntPtr.Zero); }
/// <summary> Run the shell. </summary> public void Run() { if (_appContext == IntPtr.Zero) { Console.WriteLine(CLASS_NAME + "::Run () ERROR: Application context pointer is zero."); return; } if (_shell == IntPtr.Zero) { Console.WriteLine(CLASS_NAME + "::Run () ERROR: Application shell pointer is zero."); return; } try { // Register a "configure notify action" to application context, translate the "configure notify action", add/overwrite // the shell widget's translation table and set windows manager protocol hook for the shell widget. // This must be can *** BEFORE *** XtRealizeWidget (). RegisterConfigureNotifyAction(_appContext, this.ConfigureNotifyAction); Xtlib.XtRealizeWidget(_shell); SetShellIcon(IconPath); // Register a "delete window action" to application context, translate the "delete window action", add/overwrite // the shell widget's translation table and set windows manager protocol hook for the shell widget. // This must be done *** AFTER *** XtRealizeWidget (). RegisterDeleteWindowAction(_appContext, this.DeleteWindowAction); Xtlib.XtAppMainLoop(_appContext); } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } }
// ############################################################################### // ### M E T H O D S // ############################################################################### #region Methods /// <summary> Run the shell. </summary> /// <param name="appContext"> The application context that identifies the application. <see cref="System.IntPtr"/> </param> /// <returns> Zero on success, or negative nonzero otherwise. <see cref="System.Int32"/> </returns> public int Run(IntPtr appContext) { if (appContext == IntPtr.Zero) { Console.WriteLine(CLASS_NAME + "::Run () ERROR: Application context pointer is zero."); return(-1); } try { bool firstRun = false; if (!(Xtlib.XtIsRealized(_shell) != 0)) { firstRun = true; } Xtlib.XtPopup(_shell, XtGrabKind.XtGrabExclusive); if (firstRun && XtApplicationShell.Instance != null) { SetShellIcon(XtApplicationShell.Instance.IconPath); } // Register a "delete window action" to application context, translate the "delete window action", add/overwrite // the shell widget's translation table and set windows manager protocol hook for the shell widget. // This must be done *** AFTER *** XtRealizeWidget (). RegisterDeleteWindowAction(_toplevelShell.AppContext, this.DeleteWindowAction); } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); } return(0); }
/// <summary> Dispose by parent. </summary> public virtual void DisposeByParent() { // Memory and resources, that are assigned to underlaying Athena widget's // instance structure (and thereby owned there) are destroyed by XtDestroyWidget (). // This typically inclused the GCs, pixmaps and local copies of strings. // They are typically assigned during XtCreateWidget () or XtSetValues (). if (_shell != IntPtr.Zero) { IntPtr display = Xtlib.XtDisplay(_shell); if (_appIconPixMap != IntPtr.Zero) { X11lib.XFreePixmap(display, _appIconPixMap); } if (_appMaskPixMap != IntPtr.Zero) { X11lib.XFreePixmap(display, _appMaskPixMap); } Xtlib.XtDestroyWidget(_shell); _shell = IntPtr.Zero; } }
/// <summary> The generic callback procedure, that marshals to the widget specific callback procedure. </summary> /// <param name="widget"> The widget, that is source of the event. <see cref="System.IntPtr"/> </param> /// <param name="xevent"> The event, that is invoked. <see cref="XEvent"/> </param> /// <param name="parameters"> Additional parameters (as String[]). <see cref="System.IntPtr"/> </param> /// <param name="num_params"> The number of additional parameters. <see cref="XCardinal"/> </param> /// <remarks> The prototype must match the XtActionProc delegate. </remarks> public static void MarshalAction(IntPtr widget, ref X11.XEvent xevent, IntPtr parameters, ref X11.XCardinal num_params) { ActionKey actionKey = new ActionKey(widget, xevent.type); if (_list.ContainsKey(actionKey)) { _list[actionKey] (widget, ref xevent, parameters, ref num_params); } else { // Debug code. Console.WriteLine(CLASS_NAME + "::MarshalAction () WARNING: Widget (" + Xtlib.XtNameAsString(widget) + ") pointer is not registered."); } }
// ############################################################################### // ### A T T R I B U T E S // ############################################################################### #region Attributes #endregion // ############################################################################### // ### C O N S T R U C T I O N A N D I N I T I A L I Z A T I O N // ############################################################################### #region Construction public XtGrabExclusiveMessageBox(XtApplicationShell toplevelShell, string message, string caption, DialogIcon icontype) : base(toplevelShell, caption) { if (toplevelShell == null) { throw new ArgumentNullException("toplevelShell"); } Arg[] formArgs = { new Arg(XtNames.XtNbackground, (XtArgVal)toplevelShell.AllocColorFromDefaultColormap(X11ColorNames.Gray80).P) }; _dialogForm = Xtlib.XtCreateManagedWidget(DIALOG_RESOURCE_NAME, Xtlib.XawFormWidgetClass(), _shell, formArgs, (XCardinal)1); // The dialog widget needs the final size of all child widgets during layout calculation to prevent child widget overlapping. Or in other words: // Child widget overlapping will happen, if XtNicon is set after dialog widget's layout calculation, because XtMakeResizeRequest () can't be called. // Currently the dialog widget isn't realized and therefor it hasn't a window. That's why we use the toplevel shell's window instead. IntPtr logo = IntPtr.Zero; if (!(Xtlib.XtIsRealized(toplevelShell.Shell) == (TBoolean)0) && icontype != XtDialog.DialogIcon.None) { IntPtr display = Xtlib.XtDisplay(toplevelShell.Shell); IntPtr window = Xtlib.XtWindow(toplevelShell.Shell); if (icontype == DialogIcon.Information) { logo = X11lib.XCreateBitmapFromData(display, window, XtResources.BIG_INFORMATION_ICON_BITS, XtResources.BIG_ICON_WIDTH, XtResources.BIG_ICON_HEIGHT); } else if (icontype == DialogIcon.Question) { logo = X11lib.XCreateBitmapFromData(display, window, XtResources.BIG_QUESTION_ICON_BITS, XtResources.BIG_ICON_WIDTH, XtResources.BIG_ICON_HEIGHT); } else if (icontype == DialogIcon.Exclamation) { logo = X11lib.XCreateBitmapFromData(display, window, XtResources.BIG_EXCLAMATION_ICON_BITS, XtResources.BIG_ICON_WIDTH, XtResources.BIG_ICON_HEIGHT); } else // if (icontype == DialogIcon.Stop) { logo = X11lib.XCreateBitmapFromData(display, window, XtResources.BIG_STOP_ICON_BITS, XtResources.BIG_ICON_WIDTH, XtResources.BIG_ICON_HEIGHT); } } Arg[] msgArgs = { new Arg(XtNames.XtNlabel, X11.X11Utils.StringToSByteArray(message + "\0")), new Arg(XtNames.XtNbackground, (XtArgVal)toplevelShell.AllocColorFromDefaultColormap(X11ColorNames.Gray80).P), new Arg(XtNames.XtNborderWidth, (XtArgVal)0), new Arg(XtNames.XtNleftBitmap, (XtArgVal)logo) }; _messageLabel = Xtlib.XtCreateManagedWidget(_msgLblName, Xtlib.XawLabelWidgetClass(), _dialogForm, msgArgs, (XCardinal)4); Arg[] okArgs = { new Arg(XtNames.XtNlabel, X11.X11Utils.StringToSByteArray("Yes\0")), new Arg(XtNames.XtNfromVert, _messageLabel) }; _okCommand = Xtlib.XtCreateManagedWidget(_okCmdName, Xtlib.XawCommandWidgetClass(), _dialogForm, okArgs, (XCardinal)2); Xtlib.XtAddCallback(_okCommand, XtNames.XtNcallback, CallBackMarshaler.Add(_okCommand, this.DialogOk), IntPtr.Zero); Arg[] cancelArgs = { new Arg(XtNames.XtNlabel, X11.X11Utils.StringToSByteArray("No\0")), new Arg(XtNames.XtNfromVert, _messageLabel), new Arg(XtNames.XtNfromHoriz, _okCommand) }; _cancelCommand = Xtlib.XtCreateManagedWidget(_cancelCmdName, Xtlib.XawCommandWidgetClass(), _dialogForm, cancelArgs, (XCardinal)3); Xtlib.XtAddCallback(_cancelCommand, XtNames.XtNcallback, CallBackMarshaler.Add(_cancelCommand, this.DialogCancel), IntPtr.Zero); }
// ############################################################################### // ### M E T H O D S // ############################################################################### #region Methods /// <summary> Add a widget specific callback registration. </summary> /// <param name="widget"> The widget to register the callback for. <see cref="System.IntPtr"/> </param> /// <param name="callback"> The callback to execute. <see cref="XtCallbackProc"/> </param> /// <returns> The managed code to native code marshalable generic callback procedure. <see cref="System.IntPtr"/> </returns> public static IntPtr Add(IntPtr widget, XtCallbackProc callback) { if (widget == IntPtr.Zero) { Console.WriteLine(CLASS_NAME + "::Add () WARNING: Widget is zero."); } if (callback == null) { Console.WriteLine(CLASS_NAME + "::Add () WARNING: Callback is zero."); } if (_list.ContainsKey(widget)) { // Debug code. Console.WriteLine(CLASS_NAME + "::Add() WARNING: Callback already registered for widget (" + Xtlib.XtNameAsString(widget) + "). Perform refresh."); _list[widget] = callback; } else { _list.Add(widget, callback); } return(_callbackPtr); }