ACC SHELL

Path : /usr/share/YaST2/modules/
File Upload :
Current File : //usr/share/YaST2/modules/Popup.ycp

/**
 * File:	modules/Popup.ycp
 * Package:	yast2
 * Summary:	Commonly used popup dialogs
 * Authors:	Gabriele Strattner <gs@suse.de>
 *		Stefan Hundhammer <sh@suse.de>
 *		Arvin Schnell <arvin@suse.de>
 * Flags:	Stable
 *
 * $Id: Popup.ycp 60396 2010-01-15 12:50:06Z aschnell $
 *
 * Contains commonly used popup dialogs
 * for general usage, e.g. Popup::YesNo(), Popup::ContinueCancel().
 * <br>
 * See also <a href="../wizard/README.popups">README.popups</a>
 */

{

//////////////////////////////////////////////////////////////////
//
// General module rules:
//
//   * Always check that opening a dialig succeeded.
//   * Don't close a dialog if opening wasn't successful.
//   * Don't wait for user input opening wasn't successful.
//
//////////////////////////////////////////////////////////////////

module "Popup";

textdomain "base";

import "Label";
import "Mode";
import "Directory";
import "String";
import "Icon";

boolean feedback_open = false;

// default size of the richtext widget in richtext popups
integer default_width = 60;
integer default_height = 10;



/**
 * Internal function that returns a popup dialog with an additional label.
 *
 * @param headline	headline to show or Popup::NoHeadline()
 * @param message	message text to show
 * @param icon_name	icon name (with full path) or Popup::NoIcon()
 * @param button_box	term with one or more buttons
 * @param label		second label with id `label which can be used e.g. for time out value displaying
 *
 * @return term the layout contents as a term
 */
define term popupLayoutInternalTypeWithLabel( string headline,
					  string message,
					  string icon_name,
					  term button_box,
					  string label,
					  boolean richtext,
					  integer width,
					  integer height )
{
    term content = `Empty();
    term heading = `VSpacing(0.2);
    term icon    = `Empty();

    if ( size( icon_name ) > 0 )
    {
	map ui_capabilities = UI::GetDisplayInfo();

	if ( ui_capabilities[ "HasImageSupport" ]:false )
	{
	    icon = `Image( icon_name, "" );
	}
    }

    term rt = `VWeight(1,
	`VBox(
	    `HSpacing(width),
	    `HBox(
		`VSpacing(height),
		// display the message in the widget "as is":
		// escape all tags, replace new lines by <br> tag
		`RichText(mergestring(splitstring(String::EscapeTags(message), "\n"), "<br>"))
	    )
	)
    );


    if ( size( headline ) > 0 )
    {
	content =
	`VBox (
	    `VSpacing (0.4),
	    `HBox (
		`Top (icon),
		`HSpacing (1),
		`VBox (
		    `Left (`Heading (headline)),
		    `VSpacing (0.2),
		    richtext ? rt : `Left( `Label( message ) ),
		    `VSpacing (0.2),
		    (label != nil && label != "") ? `Label (`id (`label), label) : `Empty()
		)
	    )
	);
    }
    else // no headline
    {
	content =
	`VBox (
	    `VSpacing(0.4),
	    `HBox(
		`Top (icon),
		`HSpacing (1),
		`VBox (
		    richtext ? rt : `VCenter (`Label( message ) ),
		    `VSpacing(0.2),
		    (label != nil && label != "") ? `Label(`id(`label), label ) : `Empty()
		)
	    )
	);
    }

    term dialog =
	`HBox(
	      `HSpacing(1),
	      `VBox(
		    `VSpacing(0.2),
		    content,
		    richtext ? `Empty() : `VStretch(),
		    button_box,
		    richtext ? `Empty() : `VStretch(),
		    `VSpacing(0.2)
		    ),
	      `HSpacing(1)
	      );

    return dialog;
}

/**
 * Internal function - wrapper for popupLayoutInternalTypeWithLabel call
 */
define term popupLayoutInternal( string headline, string message, string icon_name, term button_box ) {
    return popupLayoutInternalTypeWithLabel(headline, message, icon_name, button_box, nil, false, 0, 0);
}

/**
 * Internal function - wrapper for popupLayoutInternalTypeWithLabel call
 */
define term popupLayoutInternalRich( string headline, string message, string icon_name, term button_box, integer width, integer height ) {
    return popupLayoutInternalTypeWithLabel(headline, message, icon_name, button_box, nil, true, width, height);
}


/**
 * Internal version of AnyTimedMessage
 *
 * Show a message with optional headline above and
 * wait until user clicked "OK" or until a timeout runs out.
 *
 * @param headline	optional headline or Popup::NoHeadline()
 * @param message	the message (maybe multi-line) to display.
 * @param icon_name	icon name (with full path) or Popup::NoIcon()
 * @param timeout	After timeout seconds dialog will be automatically closed
 *
 * @return void
 **/
define void anyTimedMessageTypeInternal(string headline,
				    string message,
				    string icon_name,
				    integer timeout,
				    boolean richtext,
				    integer width,
				    integer height )
{
    term button_box = `ButtonBox (
	// FIXME: BNC #422612, Use `opt(`noSanityCheck) later
	`PushButton (`id (`stop), `opt (`cancelButton), Label::StopButton()),
	`PushButton (`id (`ok_msg), `opt (`default, `okButton), Label::OKButton())
    );

    boolean success = (boolean) UI::OpenDialog(
		   `opt(`decorated),
		   popupLayoutInternalTypeWithLabel( headline, message, icon_name,
						 button_box, sformat("%1", timeout), richtext, width, height )
		   );

    if (success == true)
	UI::SetFocus(`id(`ok_msg));

    symbol button = nil;

    while ( timeout > 0 && button != `ok_msg)
    {
	button = (symbol) UI::TimeoutUserInput( 1000 );

	if (button == `stop)
	{
	    while (UI::UserInput() != `ok_msg){};
	    break;
	}

	timeout = timeout - 1;

	if (success == true)
	    UI::ChangeWidget(`id(`label), `Value, sformat("%1", timeout ));
    }

    if (success == true)
	UI::CloseDialog();
}

/**
 * Internal function - wrapper for anyTimedMessageTypeInternal call
 */
define void anyTimedMessageInternal(string headline,
				    string message,
				    string icon_name,
				    integer timeout )
{
    anyTimedMessageTypeInternal(headline, message, icon_name, timeout, false, 0, 0);
}

/**
 * Internal function - wrapper for anyTimedMessageTypeInternal call
 */
define void anyTimedRichMessageInternal(string headline,
				    string message,
				    string icon_name,
				    integer timeout,
				    integer width,
				    integer height )
{
    anyTimedMessageTypeInternal(headline, message, icon_name, timeout, true, width, height);
}

/**
 * Indicator for empty headline for popups that can optionally have one
 *
 * This is really just an alias for the empty string "", but it is
 * slightly better readable.
 *
 * @return empty string ("")
 */
global define string NoHeadline()
{
    return "";
}


/**
 * Indicator for empty icon for popups that can have one - for code readability.
 **/
global define string NoIcon()
{
    return "";
}

/**
 * Button box for the AnyQuestion Dialog (internal function).
 *
 * @param yes_button_message	label on affirmative buttons (on left side)
 * @param no_button_message	label on negating button (on right side)
 * @param focus			`focus_yes (first button) or `focus_no (second button)
 *
 * @return term button box
 */
define term AnyQuestionButtonBox (
	string yes_button_message,
	string no_button_message,
	symbol focus )
{
    term yes_button = `Empty();
    term no_button = `Empty();

    if ( focus == `focus_no )
    {
	yes_button = `PushButton (`id (`yes), `opt (`okButton), yes_button_message);
	no_button  = `PushButton (`id (`no_button), `opt(`default, `cancelButton), no_button_message);
    }
    else
    {
	yes_button = `PushButton (`id (`yes), `opt (`default, `okButton), yes_button_message);
	no_button  = `PushButton (`id (`no_button), `opt (`cancelButton), no_button_message);
    }

    term button_box =  `ButtonBox (
			     yes_button,
			     no_button
			     );
    return button_box;
}


/**
 * Generic question popup with two buttons.
 *
 * Style guide hint: The first button has to have the semantics of "yes",
 * "OK", "continue" etc., the second its opposite ("no", "cancel", ...).
 * NEVER use this generic question popup to simply exchange the order of
 * yes/no, continue/cancel or ok/cancel buttons!
 *
 * @param headline		headline or Popup::NoHeadline()
 * @param message		message string
 * @param yes_button_message	label on affirmative buttons (on left side)
 * @param no_button_message	label on negating button (on right side)
 * @param focus			`focus_yes (first button) or `focus_no (second button)
 * @screenshot screenshots/AnyQuestion.png
 *
 * @return true:  first button has been clicked
 *	 false: second button has been clicked
 *
 * @see YesNo
 * @see ContinueCancel
 *
 * @example Popup::AnyQuestion( Label::WarningMsg(), "Do really want to ...?", "Install", "Don't do it", `focus_no );
 */
global define boolean AnyQuestion( string headline,
				   string message,
				   string yes_button_message,
				   string no_button_message,
				   symbol focus )
{
    term button_box = AnyQuestionButtonBox ( yes_button_message, no_button_message, focus);
    boolean success = (boolean) UI::OpenDialog( 
		   `opt(`decorated),
		   popupLayoutInternal( headline, message, Icon::IconPath ("question"), button_box )
		   );

    any ret = nil;

    if (success == true) {
	ret = UI::UserInput();
	UI::CloseDialog();
    }

    return ret == `yes;
}


/**
 * Generic error question popup with two buttons.
 *
 * Style guide hint: The first button has to have the semantics of "yes",
 * "OK", "continue" etc., the second its opposite ("no", "cancel", ...).
 * NEVER use this generic question popup to simply exchange the order of
 * yes/no, continue/cancel or ok/cancel buttons!
 *
 * @param headline		headline or Popup::NoHeadline()
 * @param message		message string
 * @param yes_button_message	label on affirmative buttons (on left side)
 * @param no_button_message	label on negating button (on right side)
 * @param focus			`focus_yes (first button) or `focus_no (second button)
 * @screenshot screenshots/AnyQuestion.png
 *
 * @return true:  first button has been clicked
 *	 false: second button has been clicked
 *
 * @see YesNo
 * @see ContinueCancel
 *
 * @example Popup::ErrorAnyQuestion( Label::WarningMsg(), "Do really want to ...?", "Install", "Don't do it", `focus_no );
 */
global boolean ErrorAnyQuestion(string headline,
				string message,
				string yes_button_message,
				string no_button_message,
				symbol focus)
{
    term button_box = AnyQuestionButtonBox ( yes_button_message, no_button_message, focus);
    boolean success = (boolean) UI::OpenDialog( 
		   `opt(`decorated),
		   popupLayoutInternal( headline, message, Icon::IconPath ("error"), button_box )
		   );

    any ret = nil;

    if (success == true) {
	ret = UI::UserInput();
	UI::CloseDialog();
    }

    return ret == `yes;
}


/**
 * Timed question popup with two buttons and time display
 *
 * @param headline		headline or Popup::NoHeadline()
 * @param message		message string
 * @param yes_button_message	label on affirmative buttons (on left side)
 * @param no_button_message	label on negating button (on right side)
 * @param focus			`focus_yes (first button) or `focus_no (second button)
 * @param timeout_seconds	timeout, if 0, normal behaviour
 * @return boolean              True if Yes, False if no
 * @see AnyQuestion
 */
global define boolean TimedAnyQuestion( string headline,
				   string message,
				   string yes_button_message,
				   string no_button_message,
				   symbol focus ,
				   integer timeout_seconds)
{
    term button_box = AnyQuestionButtonBox ( yes_button_message, no_button_message, focus);
    term timed =
	`ReplacePoint(`id(`replace_buttons) ,
		      `VBox(
			    `HCenter(
				     `Label(`id(`remaining_time), "" + timeout_seconds)
				     ),
			    `ButtonBox (
				  // FIXME: BNC #422612, Use `opt(`noSanityCheck) later
				  `PushButton (`id (`timed_stop), `opt (`cancelButton), Label::StopButton()),
				  `PushButton (`id (`timed_ok), `opt (`default, `key_F10, `okButton), Label::OKButton())
				  ),
			    `VSpacing(0.2)
			    )
		      );


    boolean success = (boolean) UI::OpenDialog(
		   `opt(`decorated),
		   popupLayoutInternal( headline, message, Icon::IconPath ("question"), timed )
		   );

    any which_input = nil;

    while (timeout_seconds > 0) {
	which_input = UI::TimeoutUserInput( 1000 );

	if (which_input == `timed_ok)
	    break;
	if (which_input == `timed_stop)
	{
	    UI::ReplaceWidget(`id(`replace_buttons), button_box);
	    while (which_input == `timed_stop)
		which_input = UI::UserInput();
	    break;
	}
	timeout_seconds = timeout_seconds - 1;
	if (success == true) UI::ChangeWidget (`id(`remaining_time), `Value, ""+timeout_seconds);
    }

    if (success == true) UI::CloseDialog();

    return which_input == `yes;
}


/**
 * Timed error question popup with two buttons and time display
 *
 * @param headline		headline or Popup::NoHeadline()
 * @param message		message string
 * @param yes_button_message	label on affirmative buttons (on left side)
 * @param no_button_message	label on negating button (on right side)
 * @param focus			`focus_yes (first button) or `focus_no (second button)
 * @param timeout_seconds	timeout, if 0, normal behaviour
 * @return boolean              True if Yes, False if no
 * @see AnyQuestion
 */
global boolean TimedErrorAnyQuestion( string headline,
				   string message,
				   string yes_button_message,
				   string no_button_message,
				   symbol focus ,
				   integer timeout_seconds)
{
    term button_box = AnyQuestionButtonBox ( yes_button_message, no_button_message, focus);
    term timed =
	`ReplacePoint(`id(`replace_buttons) ,
		      `VBox(
			    `HCenter(
				     `Label(`id(`remaining_time), "" + timeout_seconds)
				     ),
			    `ButtonBox (
				  // FIXME: BNC #422612, Use `opt(`noSanityCheck) later
				  `PushButton (`id (`timed_stop), `opt (`cancelButton), Label::StopButton()),
				  `PushButton (`id (`timed_ok), `opt (`default, `key_F10, `okButton), Label::OKButton())
				  ),
			    `VSpacing(0.2)
			    )
		      );


    boolean success = (boolean) UI::OpenDialog(
		   `opt(`decorated),
		   popupLayoutInternal( headline, message, Icon::IconPath ("error"), timed )
		   );

    any which_input = nil;

    while (timeout_seconds > 0) {
	which_input = UI::TimeoutUserInput( 1000 );

	if (which_input == `timed_ok)
	    break;
	if (which_input == `timed_stop)
	{
	    UI::ReplaceWidget(`id(`replace_buttons), button_box);
	    while (which_input == `timed_stop)
		which_input = UI::UserInput();
	    break;
	}
	timeout_seconds = timeout_seconds - 1;
	if (success == true) UI::ChangeWidget (`id(`remaining_time), `Value, ""+timeout_seconds);
    }

    if (success == true) UI::CloseDialog();

    return which_input == `yes;
}


/**
 * Dialog which displays the "message" and has a <b>Continue</b>
 * and a <b>Cancel</b> button.
 *
 * This popup should be used to confirm possibly dangerous actions and if
 * it's useful to display a short headline (without headline
 * Popup::ContinueCancel() can be used).
 * The default button is Continue.
 *
 * Returns true if Continue is clicked.
 *
 * @screenshot screenshot/ContinueCancelHeadline.png
 *
 * @param  headline short headline or Popup::NoHeadline()
 * @param  message  message string
 * @return boolean
 *
 * @example Popup::ContinueCancelHeadline ( "Short Header", "Going on with action....?" );
 *
 * @see	ContinueCancel
 * @see	YesNo
 * @see	AnyQuestion
 */
global define boolean ContinueCancelHeadline (string headline, string message)
{
    boolean ret = AnyQuestion( headline,
			       message,
			       Label::ContinueButton(),
			       Label::CancelButton(),
			       `focus_yes
			       );

    y2debug("ContinueCancelHeadline returned: %1", ret );

    return ret;
}


/**
 * Dialog which displays the "message" and has a <b>Continue</b>
 * and a <b>Cancel</b> button.
 *
 * This popup should be used to confirm possibly dangerous actions.
 * The default button is Continue.
 * Returns true if Continue is clicked.
 *
 * @screenshot screenshots/ContinueCancel.png
 *
 * @param  message  message string
 * @return boolean
 *
 * @example Popup::ContinueCancel ( "Please insert required CD-ROM." );
 *
 * @see	AnyQuestion
 */
global define boolean ContinueCancel (string message)
{

    boolean ret = ContinueCancelHeadline( NoHeadline(), message );
    y2debug("ContinueCancel returned: %1", ret );

    return ret;
}


/**
 * This dialog displays "message" (a question) and has a <b>Yes</b> and
 * a <b>No</b> button.
 *
 * It should be used for decisions about two about equivalent paths,
 * not for simple confirmation - use "Popup::ContinueCancel()" for those.
 * A short headline can be displayed (without headline you can use Popup::YesNo()).
 *
 * The default button is Yes.
 *
 * Returns true if <b>Yes</b> is clicked.
 *
 * @screenshot screenshots/YesNoHeadline.png
 *
 * @param  headline	short headline or Popup::NoHeadline()
 * @param  message	message string
 * @return boolean	true if [Yes] has been pressed
 *
 * @example  Popup::YesNoHeadline ( "Resize Windows Partition?", "... explanation of dangers ..." );
 *
 * @see	YesNo
 * @see	AnyQuestion
 */
global define boolean YesNoHeadline(string headline, string message)
{

    boolean ret = AnyQuestion( headline,
			       message,
			       Label::YesButton(),
			       Label::NoButton(),
			       `focus_yes
			       );

    y2debug("YesNoHeadline returned: %1", ret );

    return ret;
}


/**
 * Display a yes/no question and wait for answer.
 *
 * Should be used for decisions about two about equivalent paths,
 * not for simple confirmation - use "Popup::ContinueCancel()" for those.
 * The default button is Yes.
 * Returns true if <b>Yes</b> is clicked.
 *
 * @screenshot screenshots/YesNo.png
 *
 * @param  message	message string
 * @return boolean	true if [Yes] has been pressed
 *
 * @example  Popup::YesNo ( "Create a backup of the config files?" );
 *
 * @see	YesNoHeadline
 * @see	ContinueCancel
 * @see	AnyQuestion
 */
global define boolean YesNo(string message)
{
    boolean ret = YesNoHeadline( NoHeadline(), message);

    y2debug("YesNo returned: %1", ret );

    return ret;
}


/**
 * Show a long text that might need scrolling.
 *
 * Pass a RichText widget with the parameters appropriate for your text -
 * i.e. without special parameters for HTML-like text or with
 * `opt(`plainText) for plain ASCII text without HTML tags.
 *
 * @screenshot screenshots/LongText.png
 *
 * @param  headline short headline
 * @param  richtext  text input is `Richtext()
 * @param  hdim  initial horizontal dimension of the popup
 * @param  vdim  initial vertical dimension of the popup
 *
 * @example Popup::LongText ( "Package description", `Richtext("<p>Hello, this is a long description .....</p>"), 50, 20 );
 */
global define void LongText( string headline, term richtext,
			     integer hdim, integer vdim )
{
    boolean success = (boolean) UI::OpenDialog (
	`opt (`decorated),
	`HBox (
	    `VSpacing(vdim),
	    `VBox (
		`HSpacing(hdim),
		`Left (`Heading (headline)),
		`VSpacing(0.2),
		richtext,	// scrolled text
		`ButtonBox (
			`PushButton (`id (`ok), `opt (`default, `key_F10, `okButton), Label::OKButton())
		)
	    )
	)
    );

    if (success == true) {
	UI::SetFocus(`id(`ok ) );
	UI::UserInput();
	UI::CloseDialog();
    }
}


/**
 * Show a question that might need scrolling.
 *
 * @param  headline short headline
 * @param  richtext  text input as a rich text
 * @param  hdim  initial horizontal dimension of the popup
 * @param  vdim  initial vertical dimension of the popup
 * @param  yes_button_message message on the left/true button
 * @param  no_button_message message on the right/false button
 * @param  focus `focus_yes, `focus_no, `focus_none
 * @return left button pressed?
 */
global define boolean AnyQuestionRichText (string headline,
					   string richtext,
					   integer hdim, integer vdim,
					   string yes_button_message,
					   string no_button_message,
					   symbol focus)
{
    term yes_button = `PushButton (
	`id (`ok),
	(focus == `focus_yes ?
	    `opt (`default, `key_F10, `okButton)
	    :
	    `opt (`key_F10, `okButton)
	),
	yes_button_message);

    term no_button = `PushButton (
	`id (`cancel),
	(focus == `focus_no ?
	    `opt (`default, `key_F9)
	    :
	    `opt (`key_F9)
	),
	no_button_message);

    term d = `HBox (
	`VSpacing (vdim),
	`VBox (
	    `HSpacing (hdim),
	    size (headline) > 0 ? `Left(`Heading( headline )) : `Empty (),
	    `VSpacing(0.2),
	    `RichText (richtext),
	    `ButtonBox (
		yes_button,
		no_button
		)
	    )
	);

    boolean success = (boolean) UI::OpenDialog (`opt (`decorated), d);
    any ui = nil;

    if (success == true) {
	ui = UI::UserInput ();
	UI::CloseDialog ();
    }

    return ui == `ok;
}


/**
 * Confirmation for "Abort" button during installation.
 *
 * According to the "severity" parameter an appropriate text will be
 * displayed indicating what the user has to expect when he really aborts now.
 *
 * @screenshot screenshots/ConfirmAbort.png
 *
 * @param severity		`painless, `incomplete, `unusable
 *
 * @return boolean
 *
 * @example Popup::ConfirmAbort ( `painless );
 */
global define boolean ConfirmAbort( symbol severity )
{
    string what_will_happen = "";

    // Confirm user request to abort installation
    string abort_label = _("Really abort the installation?");
    // Button that will really abort the installation
    string abort_button = _("&Abort Installation");
    // Button that will continue with the installation
    string continue_button = _("&Continue Installation");
    // Dialog icon
    string icon_name = "warning";

    if ( severity == `painless )
    {
	if (Mode::repair ())
	{
	    // Confirm user request to abort System Repair
	    abort_label = _("Really abort YaST System Repair?");
	    // Button that will really abort the repair
	    abort_button = _("Abort System Repair");
	    // Button that will continue with the repair
	    continue_button = _("&Continue System Repair");
	}
	else
	{
	    // Warning text for aborting an installation before anything is installed
	    what_will_happen = _("If you abort the installation now,
Linux will not be installed.
Your hard disk will remain untouched.");
	}
	// icon_name = "info";
    }
    else if ( severity == `incomplete )
    {
	// Warning text for aborting an installation during the install process
	// - After some installation steps have been performed - e.g.
	// disks formatted / some packages already installed
	what_will_happen = _("If you abort the installation now, you will
have an incomplete Linux system
that might or might not be usable.
You might need to reinstall.
");
    }
    else if ( severity == `unusable )
    {
	// Warning text for aborting an installation during the install process
	// right in the middle of some critical process (e.g. formatting)
	what_will_happen = _("If you abort the installation now,
Linux will be unusable.
You will need to reinstall.");
    }
    else
    {
	y2error ("Unknown symbol for ConfirmAbort");
    }

    string message = abort_label + "\n\n" + what_will_happen;

    term button_box = AnyQuestionButtonBox (abort_button, continue_button, `focus_no);
    boolean success = (boolean) UI::OpenDialog (
	`opt (`decorated),
	popupLayoutInternal (NoHeadline(), message, Icon::IconPath (icon_name), button_box)
    );

    any user_ret = nil;
    if (success == true) {
	user_ret = UI::UserInput();
	UI::CloseDialog();
    }

    boolean ret = (user_ret == `yes);

    y2debug("ConfirmAbort returned: %1", ret);

    return ret;
}


/**
 * Confirmation popup when user clicked "Abort".
 *
 * Set "have changes" to "true" when there are changes that will be lost.
 * Note: If there are none, it is good policy to ask for confirmation
 * anyway, but of course with "have_changes" set to "false" so the user
 * isn't warned about changes that might be lost.
 *
 * @param have_changes	true:  There are changes that will be lost
 *			false: No changes
 *
 * @return	true: "abort" confirmed;
 *		false: don't abort
 */
global define boolean ReallyAbort( boolean have_changes )
{
    symbol focus = `focus_yes;

    // Confirm aborting the program
    string message = _("Really abort?");

    if ( have_changes )
    {
	focus = `focus_no;

	// Additional hint when trying to abort program in spite of changes
	message = message + "\n" + _("All changes will be lost!");
    }

    boolean ret = AnyQuestion( NoHeadline(),
			   message,
			   Label::YesButton(),
			   Label::NoButton(),
			   focus );

    y2debug("ReallyAbort returned: %1", ret );

    return ret;
}


/**
 * Generic message popup with Details button - internal
 *
 * Show a message with optional headline above and
 * wait until user clicked "OK" or "Details". On "Details", show window with detailed information.
 *
 * @param headline	optional headline or Popup::NoHeadline()
 * @param message	the message (maybe multi-line) to display.
 * @param details	the detailed information text
 */
define void anyMessageDetailsInternalType(string headline, string message, string details, string icon_name, boolean richtext, integer width, integer height )
{
    term button_box =  `ButtonBox (
	`PushButton (`id(`ok_msg), `opt (`default, `okButton), Label::OKButton()),
	// FIXME: BNC #422612, Use `opt(`noSanityCheck) later
	// button label
	`PushButton (`id(`details), `opt (`cancelButton), _("&Details..."))
    );

    boolean success = (boolean) UI::OpenDialog (
	`opt(`decorated),
	richtext ? popupLayoutInternalRich(headline, message, icon_name, button_box, width, height)
		 : popupLayoutInternal( headline, message, icon_name, button_box )
    );

    UI::SetFocus(`id(`ok_msg) );

    while (true)
    {
	any ret	= UI::UserInput();
	if (ret	== `details)
	{
	    boolean success2 = (boolean) UI::OpenDialog (`opt(`decorated ), `HBox (`VSpacing(default_height),
		`VBox (
		    `HSpacing (default_width),
		    `VSpacing (0.5),
		    `RichText (mergestring(splitstring(String::EscapeTags(details), "\n"), "<br>")),
		    `VSpacing (),
		    `ButtonBox (
			`PushButton (`id (`ok), `opt (`default, `key_F10, `okButton), Label::OKButton())
		    )
		)
	    ));
	    if (success2 == true) {
		UI::UserInput();
		UI::CloseDialog();
	    }
	}
	else break;
    }
    if (success == true) UI::CloseDialog();
}

/**
 * Generic message popup - internal
 *
 * Show a message with optional headline above and
 * wait until user clicked "OK".
 *
 * @param headline	optional headline or Popup::NoHeadline()
 * @param message	the message (maybe multi-line) to display.
 */
define void anyMessageInternalType(string headline, string message, string icon_name, boolean richtext, integer width, integer height )
{
    term button_box =  `ButtonBox (
	`PushButton (`id (`ok_msg), `opt (`default, `key_F10, `okButton), Label::OKButton())
    );

    boolean success = (boolean) UI::OpenDialog(
		   `opt(`decorated),
		   richtext ? popupLayoutInternalRich(headline, message, icon_name, button_box, width, height) :
			popupLayoutInternal( headline, message, icon_name, button_box )
		   );

    if (success == true) {
	UI::SetFocus(`id(`ok_msg) );
	UI::UserInput();
	UI::CloseDialog();
    }
}

/**
 * Internal function - wrapper for anyMessageInternal call
 */
define void anyMessageInternal(string headline, string message, string icon_name ) {
    anyMessageInternalType(headline, message, icon_name, false, 0, 0);
}

/**
 * Internal function - wrapper for anyMessageInternal call
 */
define void anyMessageInternalRich(string headline, string message, string icon_name, integer width, integer height) {
    anyMessageInternalType(headline, message, icon_name, true, width, height);
}

/**
 * Internal function - wrapper for anyMessageDetailsInternalType call
 */
define void anyMessageDetailsInternal (string headline, string message, string details, string icon_name) {
    anyMessageDetailsInternalType (headline, message, details, icon_name, false, 0, 0);
}


/**
 * Generic message popup - internal
 *
 * Show a message with optional headline above and
 * wait until user clicked "OK".
 *
 * @param headline	optional headline or Popup::NoHeadline()
 * @param message	the message (maybe multi-line) to display.
 */
define void anyRichMessageInternal(string headline, string message, string icon_name, integer width, integer height )
{
    term button_box =  `ButtonBox (
	`PushButton (`id(`ok_msg), `opt (`default, `key_F10), Label::OKButton())
    );

    boolean success = (boolean) UI::OpenDialog(
		   `opt(`decorated),
		   popupLayoutInternalRich( headline, message, icon_name, button_box, width, height )
		   );

    if (success == true) {
	UI::SetFocus(`id(`ok_msg) );
	UI::UserInput();
	UI::CloseDialog();
    }
}


/**
 * Generic message popup
 *
 * Show a message with optional headline above and
 * wait until user clicked "OK".
 *
 * @param headline	optional headline or Popup::NoHeadline()
 * @param message	the message (maybe multi-line) to display.
 * @param icon_name	icon name (with full path) or Popup::NoIcon()
 */
global define void AnyMessage(string headline, string message)
{
    anyMessageInternal( headline, message, Icon::IconPath ("info") );
}
    

/**
 * Clear feedback message
 * @return void
 */
global define void ClearFeedback()
{
    if ( feedback_open )
	UI::CloseDialog();
    feedback_open = false;
}


/**
 * Show popup with a headline and a message for feedback
 * @param headline headline of Feedback popup
 * @param message the feedback message
 * @return void
 */
global define void ShowFeedback(string headline, string message)
{
    if (feedback_open)
    {
	UI::CloseDialog();
    }
    term button_box =  `Empty();
    UI::BusyCursor();
    UI::OpenDialog(
		   `opt(`decorated),
		   popupLayoutInternal( headline, message, Icon::IconPath ("warning"), button_box )
		   );

    feedback_open = true;
}

/**
 * Show a simple message and wait until user clicked "OK".
 *
 *
 * @param message message string
 *
 * @example  Popup::Message("This is an information about ... ." );
 *
 * @screenshot screenshots/Message.png
 * @see AnyMessage
 * @see Notify
 * @see Warning
 * @see Error
 */
global define void Message(string message)
{
    anyMessageInternal(NoHeadline(), message, Icon::IconPath ("info"));
}

/**
 * Show a long message and wait until user clicked "OK".
 *
 * @param message message string (may contain rich text tags)
 */
global define void LongMessage(string message)
{
    anyMessageInternalRich(NoHeadline(), message, Icon::IconPath ("info"), default_width, default_height);
}

/**
 * Show a long message and wait until user clicked "OK". Size of the popup window is adjustable.
 *
 * @param message message string (may contain rich text tags)
 * @param width width of the popup window
 * @param height height of the popup window
 */
global define void LongMessageGeometry(string message, integer width, integer height)
{
    anyMessageInternalRich(NoHeadline(), message, Icon::IconPath ("info"), width, height);
}

/**
 * Show a message and wait until user clicked "OK" or time is out
 *
 * @param message message string
 * @param timeout_seconds time out in seconds
 */
global define void TimedMessage(string message, integer timeout_seconds) {
    anyTimedMessageInternal(NoHeadline(), message, Icon::IconPath ("info"), timeout_seconds);
}

/**
 * Show a long message and wait until user clicked "OK" or time is out.
 *
 * @param message message string (may contain rich text tags)
 * @param timeout_seconds time out in seconds
 */
global define void TimedLongMessage(string message, integer timeout_seconds)
{
    anyTimedRichMessageInternal(NoHeadline(), message, Icon::IconPath ("info"), timeout_seconds, default_width, default_height);
}

/**
 * Show a long message and wait until user clicked "OK" or time is out. Size of the popup window is adjustable.
 *
 * @param message message string (may contain rich text tags)
 * @param timeout_seconds time out in seconds
 * @param width width of the popup window
 * @param height height of the popup window
 */
global define void TimedLongMessageGeometry(string message, integer timeout_seconds, integer width, integer height)
{
    anyTimedRichMessageInternal(NoHeadline(), message, Icon::IconPath ("info"), timeout_seconds, width, height );
}

/**
 * Show a message with Details button and wait until user clicked "OK".
 *
 * @param message	message string
 * @param details	detailed information string
 * @example  Popup::MessageDetails("This is an information about ... .", "This service is intended to...");
 *
 * @see Message
 */
global define void MessageDetails (string message, string details) {
    anyMessageDetailsInternal (NoHeadline (), message, details, Icon::IconPath ("info"));
}

/**
 * Show a warning message and wait until user clicked "OK".
 *
 *
 * @param message warning message string
 *
 * @example Popup::Warning("Something is wrong. Please check your configuration." );
 *
 * @screenshot screenshots/Warning.png
 * @see Message
 * @see Notify
 * @see Error
 * @see AnyMessage
 */
global define void Warning(string message)
{
    anyMessageInternal( Label::WarningMsg(), message, Icon::IconPath ("warning") );
}

/**
 * Show a long warning and wait until user clicked "OK".
 *
 * @param message message string (may contain rich text tags)
 */
global define void LongWarning(string message)
{
    anyMessageInternalRich( Label::WarningMsg(), message, Icon::IconPath ("warning"), default_width, default_height );
}

/**
 * Show a long warning and wait until user clicked "OK". Size of the popup window is adjustable
 *
 * @param message message string (may contain rich text tags)
 * @param width width of the popup window
 * @param height height of the popup window
 */
global define void LongWarningGeometry(string message, integer width, integer height)
{
    anyMessageInternalRich( Label::WarningMsg(), message, Icon::IconPath ("warning"), width, height );
}

/**
 * Show a warning message and wait specified amount of time or until user clicked "OK".
 *
 * @screenshot screenshots/TimedWarningPopup.png
 *
 * @param message warning message string
 * @param timeout_seconds time out in seconds
 *
 * @return void
 *
 * @see Warning
 */
global define void TimedWarning(string message, integer timeout_seconds)
{
    anyTimedMessageInternal( Label::WarningMsg(), message, Icon::IconPath ("warning"), timeout_seconds );
}

/**
 * Show a long warning message and wait until user clicked "OK" or time is out.
 *
 * @param message message string (may contain rich text tags)
 * @param timeout_seconds time out in seconds
 */
global define void TimedLongWarning(string message, integer timeout_seconds)
{
    anyTimedRichMessageInternal( Label::WarningMsg(), message, Icon::IconPath ("warning"), timeout_seconds, default_width, default_height );
}

/**
 * Show a long warning and wait until user clicked "OK" or time is out. Size of the popup window is adjustable.
 *
 * @param message message string (may contain rich text tags)
 * @param timeout_seconds time out in seconds
 * @param width width of the popup window
 * @param height height of the popup window
 */
global define void TimedLongWarningGeometry(string message, integer timeout_seconds, integer width, integer height) {
    anyTimedRichMessageInternal( Label::WarningMsg(), message, Icon::IconPath ("warning"), timeout_seconds, width, height );
}

/**
 * Show a warning with Details button and wait until user clicked "OK".
 *
 * @param message	warning message string
 * @param details	detailed information string
 * @example Popup::WarningDetails("Something is wrong. Please check your configuration.", "possible problem is in..." );
 *
 * @see Message
 */
global define void WarningDetails (string message, string details) {
    anyMessageDetailsInternal (Label::WarningMsg(), message, details, Icon::IconPath ("warning"));
}

/**
 * Show an error message and wait until user clicked "OK".
 *
 * @param message	error message string
 *
 * @example  Popup::Error("The configuration was not succesful." );
 * @screenshot screenshots/Error.png
 *
 * @see Message
 * @see Notify
 * @see Warning
 * @see AnyMessage
 */
global define void Error(string message)
{
    anyMessageInternal( Label::ErrorMsg(), message, Icon::IconPath ("error") );
}

/**
 * Show a long error and wait until user clicked "OK".
 *
 * @param message message string (may contain rich text tags)
 */
global define void LongError(string message)
{
    anyMessageInternalRich( Label::ErrorMsg(), message, Icon::IconPath ("error"), default_width, default_height );
}

/**
 * Show a long error message and wait until user clicked "OK". Size of the popup window is adjustable.
 *
 * @param message message string (may contain rich text tags)
 * @param width width of the popup window
 * @param height height of the popup window
 */
global define void LongErrorGeometry(string message, integer width, integer height)
{
    anyMessageInternalRich( Label::ErrorMsg(), message, Icon::IconPath ("error"), width, height);
}

/**
 * Show an error message and wait specified amount of time or until user clicked "OK".
 *
 * @screenshot screenshots/TimedErrorPopup.png
 *
 * @param message	error message string
 * @param timeout_seconds time out in seconds
 *
 * @return void
 *
 * @see Error
 */
global define void TimedError(string message, integer timeout_seconds)
{
    anyTimedMessageInternal( Label::ErrorMsg(), message, Icon::IconPath ("error"), timeout_seconds );
}

/**
 * Show a long error message and wait until user clicked "OK" or time is out.
 *
 * @param message message string (may contain rich text tags)
 * @param timeout_seconds time out in seconds
 */
global define void TimedLongError(string message, integer timeout_seconds)
{
    anyTimedRichMessageInternal( Label::ErrorMsg(), message, Icon::IconPath ("error"), timeout_seconds, default_width, default_height );
}

/**
 * Show a long error message and wait until user clicked "OK" or time is out. Size of the popup window is adjustable.
 *
 * @param message message string (may contain rich text tags)
 * @param timeout_seconds time out in seconds
 * @param width width of the popup window
 * @param height height of the popup window
 */
global define void TimedLongErrorGeometry(string message, integer timeout_seconds, integer width, integer height)
{
    anyTimedRichMessageInternal( Label::ErrorMsg(), message, Icon::IconPath ("error"), timeout_seconds, width, height );
}

/**
 * Show an error message with Details button and wait until user clicked "OK".
 *
 * @param message	error message string
 * @param details	detailed information string
 * @example  Popup::ErrorDetails("The configuration was not succesful.", "Service failed to start");
 *
 * @see Message
 */
global define void ErrorDetails (string message, string details) {
    anyMessageDetailsInternal (Label::ErrorMsg(), message, details, Icon::IconPath ("error"));
}


/**
 * Show a notification message and wait until user clicked "OK".
 *
 * @screenshot screenshots/Notify.png
 *
 * @param  message notify message string
 *
 * @example  Popup::Notify("Your printer is ready for use." );
 *
 * @see Message
 * @see AnyMessage
 */
global define void Notify(string message)
{
    anyMessageInternal( "", message, Icon::IconPath ("info") );
}

/**
 * Show a long notify message and wait until user clicked "OK".
 *
 * @param message message string (may contain rich text tags)
 */
global define void LongNotify(string message)
{
    anyMessageInternalRich( NoHeadline(), message, Icon::IconPath ("info"), default_width, default_height );
}

/**
 * Show a long notify message and wait until user clicked "OK". Size of the popup window is adjustable.
 *
 * @param message message string (may contain rich text tags)
 * @param width width of the popup window
 * @param height height of the popup window
 */
global define void LongNotifyGeometry(string message, integer width, integer height)
{
    anyMessageInternalRich( NoHeadline(), message, Icon::IconPath ("info"), width, height);
}

/**
 * Show a long notify message and wait until user clicked "OK" or the time is out.
 *
 * @param message message string (may contain rich text tags)
 * @param timeout_seconds time out in seconds
 */
global define void TimedNotify(string message, integer timeout_seconds)
{
    anyTimedMessageInternal( NoHeadline(), message, Icon::IconPath ("info"), timeout_seconds );
}

/**
 * Show a long error message and wait until user clicked "OK" or time is out.
 *
 * @param message message string (may contain rich text tags)
 * @param timeout_seconds time out in seconds
 */
global define void TimedLongNotify(string message, integer timeout_seconds)
{
    anyTimedRichMessageInternal( NoHeadline(), message, Icon::IconPath ("info"), timeout_seconds, default_width, default_height );
}

/**
 * Show a long notify message and wait until user clicked "OK" or time is out. Size of the popup window is adjustable.
 *
 * @param message message string (may contain rich text tags)
 * @param timeout_seconds time out in seconds
 * @param width width of the popup window
 * @param height height of the popup window
 */
global define void TimedLongNotifyGeometry(string message, integer timeout_seconds, integer width, integer height)
{
    anyTimedRichMessageInternal( NoHeadline(), message, Icon::IconPath ("info"), timeout_seconds, width, height );
}


/**
 * Show a notify message with Details button and wait until user clicked "OK".
 *
 * @param message	error message string
 * @param details	detailed information string
 *
 * @see Message
 */
global define void NotifyDetails (string message, string details) {
    anyMessageDetailsInternal (NoHeadline(), message, details, Icon::IconPath ("info"));
}

/**
 * Display a message with a timeout
 *
 * Display a message with a timeout and return when the user clicks "OK", "Cancel"
 * or when the timeout expires ("OK" is assumed then).
 *
 * There is also a "stop" button that will stop the countdown. If the
 * user clicks that, the popup will wait forever (or until "OK" or "Cancel" is
 * clicked, of course).
 *
 * @param message		message to display
 * @param timeout_seconds		the timeout in seconds
 *
 * @return true	--> "OK" or timer expired<br>
 *	 false  --> "Cancel"
 *
 * @example boolean ret = Popup::TimedOKCancel("This is a timed message", 2 );
 */
global define boolean TimedOKCancel(string message, integer timeout_seconds)
{
    boolean success = (boolean) UI::OpenDialog(
		   `opt(`decorated),
		   `HBox(
			 `HSpacing(1),
			 `VBox(
			       `VSpacing(0.2),
			       `Label(message),
			       `HCenter(
					`Label(`id(`remaining_time), "" + timeout_seconds)
					),
			       `ButtonBox (
				     `PushButton (`id (`timed_stop), `opt (`customButton), Label::StopButton()),
				     `PushButton (`id (`timed_ok), `opt (`default, `key_F10, `okButton), Label::OKButton()),
				     `PushButton (`id (`timed_cancel), `opt (`key_F9, `cancelButton), Label::CancelButton())
				     ),
			       `VSpacing(0.2)
			       )
			 )
		   );

    any which_input = nil;

    while (timeout_seconds > 0) {
	which_input = UI::TimeoutUserInput( 1000 );
	if (which_input == `timed_ok)
	    break;
	if (which_input == `timed_cancel)
	    break;
	if (which_input == `timed_stop) {
	    while (which_input == `timed_stop)
		which_input = UI::UserInput();
	    break;
	}
	timeout_seconds = timeout_seconds - 1;
	UI::ChangeWidget (`id(`remaining_time), `Value, ""+timeout_seconds);
    }
    if (success == true) UI::CloseDialog();

    return which_input != `timed_cancel;
}


/**
 * Generic question popup with three buttons.
 *
 * @param headline		headline or Popup::NoHeadline()
 * @param message			message string
 * @param yes_button_message	label on affirmative button (on left side)
 * @param no_button_message	label on negating button (middle)
 * @param retry_button_message	label on retry button (on right side)
 * @param focus			`focus_yes (first button), `focus_no (second button) or
 *				`focus_retry (third button)
 *
 * @return - `yes:  first button has been clicked
 *	   - `no: second button has been clicked
 *	   - `retry: third button has been clicked
 *
 * @see AnyQuestion
 *
 * @example Popup::AnyQuestion3( Label::WarningMsg(), _("... failed"), _("Continue"), _("Cancel"), _("Retry"), `focus_yes );
 */
global define symbol AnyQuestion3( string headline,
				   string message,
				   string yes_button_message,
				   string no_button_message,
				   string retry_button_message,
				   symbol focus )
{
    term yes_button = `Empty();
    term no_button = `Empty();
    term retry_button = `Empty();

    if (focus == `focus_no)
    {
	yes_button = `PushButton (`id (`yes), `opt (`key_F10, `okButton), yes_button_message);
	no_button  = `PushButton (`id (`no), `opt(`default, `key_F9, `cancelButton), no_button_message);
	retry_button  = `PushButton (`id(`retry), `opt (`key_F6, `customButton), retry_button_message);
    }
    else if (focus == `focus_yes)
    {
	yes_button = `PushButton (`id(`yes), `opt(`default, `key_F10, `okButton), yes_button_message);
	no_button  = `PushButton (`id(`no), `opt (`key_F9, `cancelButton), no_button_message);
	retry_button  = `PushButton (`id(`retry), `opt (`key_F6, `customButton), retry_button_message);
    }
    else
    {
	yes_button = `PushButton (`id (`yes), `opt (`key_F10, `okButton), yes_button_message);
	no_button  = `PushButton (`id (`no), `opt (`key_F9, `cancelButton), no_button_message);
	retry_button  = `PushButton (`id(`retry), `opt (`default, `key_F6, `customButton), retry_button_message);
    }

    term button_box =  `ButtonBox (
			     yes_button,
			     no_button,
			     retry_button
			     );

    boolean success = (boolean) UI::OpenDialog(
		   `opt(`decorated),
		   popupLayoutInternal( headline, message, Icon::IconPath ("question"), button_box )
		   );

    symbol ret = nil;

    if (success == true) {
	ret = (symbol) UI::UserInput();
	UI::CloseDialog();
    }

    return ret;
}


/**
 * Special error popup for YCP modules that don't work.
 *
 * The user can choose one of:
 * - "back" - go back to the previous module
 * - "next" - skip this faulty module and directly go to the next one
 * - "again" - try it again (after fixing something in the code, of course)
 * - "cancel" - exit program
 *
 * @screenshot screenshots/ModuleError.png
 *
 * @param text	 string
 * @return symbol `back, `again, `cancel, `next
 *
 * @example Popup::ModuleError( "The module " + symbolof(argterm) + " does not work." );
 */
global define symbol ModuleError(string text)
{
    boolean success = (boolean) UI::OpenDialog(
		   `opt(`decorated, `warncolor),
		   `HBox(
			 `HSpacing(1),
			 `VBox(
			       `VSpacing(0.2),
			       `Heading(text),
			       `ButtonBox (
				     `PushButton(`id(`back),   `opt (`key_F8, `customButton),  Label::BackButton()),
				     `PushButton(`id(`again),  `opt (`key_F6, `customButton),  Label::RetryButton()),
				     `PushButton(`id(`cancel), `opt (`key_F9, `cancelButton),  Label::QuitButton()),
				     `PushButton(`id(`next),   `opt (`key_F10, `okButton),     Label::NextButton())
				     ),
			       `VSpacing(0.2)
			       ),
			 `HSpacing(1)
			 )
		   );
    symbol ret = nil;

    if (success == true) {
	ret = (symbol) UI::UserInput();
	UI::CloseDialog();
    }

    return ret;
}


/**
 * Generic message popup
 *
 * Show a message with optional headline above and
 * wait until user clicked "OK" or until a timeout runs out.
 *
 * @param headline	optional headline or Popup::NoHeadline()
 * @param message	the message (maybe multi-line) to display.
 * @param timeout	After timeout seconds dialog will be automatically closed
 *
 * @return void
 *
 */
global define void AnyTimedMessage(string headline, string message, integer timeout)
{
    anyTimedMessageInternal( headline, message, nil, timeout );
}

global define void AnyTimedRichMessage(string headline, string message, integer timeout)
{
    anyTimedRichMessageInternal( headline, message, nil, timeout, default_width, default_height );
}



// it is misaligned because there used to be UI() around it

/**
 * Show the contents of an entire file in a popup.
 *
 * @param headline	headline text
 * @param text	text to show
 * @param timeout	text to show
 *
 * @example Popup::ShowText ("Boot Messages", "kernel panic", 10);
 */
global define void ShowTextTimed (string headline, string text,
				  integer timeout)
{
    term heading = `Empty( );

    if ( size(headline) == 0 )
    {
	heading = `VSpacing(0.2);
    }
    else
    {
	heading = `Heading( headline );
    }

    boolean success = (boolean) UI::OpenDialog( `opt(`decorated ),
		    `VBox(
			  `HSpacing( 70 ),	// force width
			  heading,
			  `VWeight( 1,
				    `HBox(
					  `VSpacing( 18 ),	// force height
					  `HSpacing( 0.7 ),
					  `RichText(`id(`text), `opt(`plainText), text),
					  `HSpacing( 0.7 )
					  )
				    ),
                          `VSpacing( 0.3 ),
                          `Label(`id(`label), sformat("%1", timeout)),
                          `VSpacing(0.2),
                          `ButtonBox (
                              `PushButton(`id (`ok_msg), `opt(`default, `key_F10, `okButton), Label::OKButton())
                          ),
			  `VSpacing( 0.3 )
			  )
		    );

    symbol button = nil;

    while ( timeout > 0 && button != `ok_msg)
    {
	button = (symbol) UI::TimeoutUserInput( 1000 );
	timeout = timeout - 1;

	UI::ChangeWidget(`id(`label), `Value, sformat("%1", timeout ));
    }

    if (success == true) UI::CloseDialog();
}


/**
 * Show the contents of an entire file in a popup.
 *
 * @param headline	headline text
 * @param text	text to show
 *
 * @example Popup::ShowText ("Boot Messages", "kernel panic");
 */
global define void ShowText (string headline, string text)
{
    term heading = `Empty( );

    if ( size(headline) == 0 )
    {
	heading = `VSpacing(0.2);
    }
    else
    {
	heading = `Heading( headline );
    }

    boolean success = (boolean) UI::OpenDialog( `opt(`decorated ),
		    `VBox(
			  `HSpacing( 70 ),	// force width
			  heading,
			  `VWeight( 1,
				    `HBox(
					  `VSpacing( 18 ),	// force height
					  `HSpacing( 0.7 ),
					  `RichText(`id(`text), `opt(`plainText), text),
					  `HSpacing( 0.7 )
					  )
				    ),
			  `VSpacing( 0.3 ),
			  `ButtonBox (
			      `PushButton (`opt (`default, `key_F10, `okButton), Label::OKButton())
			  ),
			  `VSpacing (0.3)
			)
		    );

    if (success == true) {
	UI::UserInput();
	UI::CloseDialog();
    }
}

/**
 * Show the contents of an entire file in a popup.
 *
 * Notice: This is a WFM function, NOT an UI function!
 *
 * @param headline	headline text
 * @param filename	filename with path of the file to show
 *
 * @example Popup::ShowFile ("Boot Messages", "/var/log/boot.msg");
 */
global define void ShowFile (string headline, string filename)
{
    string text = (string)SCR::Read (.target.string, filename);

    ShowText (headline, text);
}


}
/* EOF */

ACC SHELL 2018