/**
 * File:
 *	inst_keyboard.ycp
 *
 * Authors:
 *	Klaus   Kämpf <kkaempf@suse.de>
 *	Michael Hager <mike@suse.de>
 *	Stefan  Hundhammer <sh@suse.de>
 *
 * Summary:
 *	Let the user choose keyboard
 *
 * $Id: inst_keyboard.ycp 20876 2005-01-24 16:53:24Z nashif $
 */
{
    textdomain "country";

    // dont ask for keyboard on S/390 or serial console

    import "Arch";
    import "Mode";
    import "Popup";
    import "GetInstArgs";

    // After import "Arch" and "Mode"
    //
    if ( Arch::s390 () )
    {
	return `next;
    }

    import "Keyboard";
    import "Label";
    import "Language";
    import "Misc";
    import "Stage";
    import "Wizard";

define symbol KeyboardExpertDialog()
    ``{

    symbol ret = `none;
    // help text for keyboard expert screen
    string help_text = _("<p>
Here, fine tune various settings of the keyboard module.
These settings are written into the file <b>/etc/sysconfig/keyboard</b>.
</p>
");

    // general help trailer
    help_text = help_text + _("<p>
If unsure, use the default values already selected.
</p>");

    // label text

    UI::OpenDialog( `opt(`decorated  ),
		    `HBox(
			`HWeight(30, `RichText( help_text )),
			`HStretch(),
			`HSpacing(1),
			`HWeight(70,
			    `VBox(
				`HSpacing( 60 ),
				// heading text
				`Heading( _("Keyboard Expert Dialog") ),
				`VSpacing(`opt(`vstretch), 1),
				`Left(`TextEntry( `id(`rate),
						  // label text
				                  _("Repeat &Rate"))),
				`Left(`TextEntry( `id(`delay),
					    // label text
				            _("De&lay before Repetition Starts")) ),
				`VSpacing(`opt(`vstretch), 1),
				`Frame(
				    // label text
				    _("Start-up States"),
				    `VBox(
					`Left(`ComboBox( 
					    `id(`numlock),
					     // label text
					     _("&Num Lock On"),
					     [ `item( `id("bios"), 
					              _("BIOS Settings")), 
					       `item( `id("yes"), _("Yes")),
					       `item( `id("no"), _("No")),
					       `item( `id("untouched"), 
						      _("<Untouched>")) ] )),
					`VSpacing(`opt(`vstretch), 1),
					`Left(`CheckBox( `id(`capslock),
							 // label text
					                 _("Ca&ps Lock On") )),
					`Left(`CheckBox( `id(`scrlock),
							 // label text
							 _("&Scroll Lock On") )))),
				`VSpacing(`opt(`vstretch), 1),
				`Left(`TextEntry( `id(`tty),
					    // label text
				            _("&Devices on which the values for Num Lock, Caps Lock, and
Scroll Lock should be set
") )),
				`VSpacing(`opt(`vstretch), 1),
				`Left(`CheckBox( `id(`discaps),
					   // label text
				           _("&Disable Caps Lock")) ),
				`VSpacing(1),
				`VStretch(),
				`HBox(
				     `PushButton(`id(`ok), `opt(`default),
						 Label::OKButton() ),
				     `PushButton(`id(`cancel),
				                 Label::CancelButton() )
				     )
				))
			 ));
    map val = Keyboard::GetExpertValues();
    map val_on_entry = val;
    y2milestone( "map %1", val );
    UI::ChangeWidget( `id(`rate), `Value, val["rate"]:"" );
    UI::ChangeWidget( `id(`rate), `ValidChars, "0123456789." );
    UI::ChangeWidget( `id(`delay), `Value, val["delay"]:"" );
    UI::ChangeWidget( `id(`delay), `ValidChars, "0123456789" );
    string tmp = val["numlock"]:"";
    if( tmp == "" )
	{
	tmp = "untouched";
	}
    UI::ChangeWidget( `id(`numlock), `Value, tmp );
    UI::ChangeWidget( `id(`capslock), `Value, val["capslock"]:false );
    UI::ChangeWidget( `id(`scrlock), `Value, val["scrlock"]:false );
    UI::ChangeWidget( `id(`tty), `Value, val["tty"]:"" );
    UI::ChangeWidget( `id(`discaps), `Value, val["discaps"]:false );
    repeat
	{
	ret = (symbol)UI::UserInput();
	if( ret == `ok )
	    {
	    val = $[];
	    val["rate"] = UI::QueryWidget( `id(`rate), `Value );
	    val["delay"] = UI::QueryWidget( `id(`delay), `Value );
	    val["numlock"] = "";
	    tmp = (string)UI::QueryWidget( `id(`numlock), `Value );
	    y2milestone( "tmp %1", tmp );
	    if( contains( ["bios", "yes", "no"], tmp ) )
		{
		val["numlock"] = tmp;
		}
	    val["capslock"] = UI::QueryWidget( `id(`capslock), `Value );
	    val["scrlock"] = UI::QueryWidget( `id(`scrlock), `Value );
	    val["tty"] = UI::QueryWidget( `id(`tty), `Value );
	    val["discaps"] = UI::QueryWidget( `id(`discaps), `Value );
	    y2milestone( "map ok %1", val );
	    Keyboard::SetExpertValues( val );
	    if (val != val_on_entry)
		Keyboard::ExpertSettingsChanged = true;

	    }
	} until ( ret == `cancel || ret == `ok );
    UI::CloseDialog();
    };

    /* ----------------------------------------------------------------------
     * Keyboard
     * ----------------------------------------------------------------------*/


    if (Mode::config ())
    {
	import "AutoinstGeneral";
	if (AutoinstGeneral::keyboard["keymap"]:"" != "")
	{
	    Keyboard::current_kbd = AutoinstGeneral::keyboard["keymap"]:"";
	    if (haskey(AutoinstGeneral::keyboard, "keyboard_values")
		&& AutoinstGeneral::keyboard["keyboard_values"]:$[] != $[])
	    {
		Keyboard::SetExpertValues(AutoinstGeneral::keyboard["keyboard_values"]:$[]);
	    }
	}
	else
	{
	    Keyboard::current_kbd =  Keyboard::GetKeyboardForLanguage( AutoinstGeneral::language, "english-us" );
	}
    }


    // Memorize the current keyboard language to be able to restore it.
    //
    string keyboard_on_entry = Keyboard::current_kbd;
    string cur_kbd = Keyboard::current_kbd;

    term keyboardsel = `dummy();
    string keyboard = "";

    // Create keyboard selection box with the default selection.
    // First build a map sorted by translations.
    //
    list<term> keyboardlist_by_translation = maplist (
	string code, string name, Keyboard::Selection(), ``(
	    `item (`id(code), name, Keyboard::current_kbd == code)
	));

    keyboardlist_by_translation = sort (
	term a, term b, keyboardlist_by_translation, {
	    list lsorted	= lsort ([a[1]:"", b[1]:""]);
	    return (lsorted[0]:"" == a[1]:"" && a[1]:"" != b[1]:"");
	});

    keyboardsel = `SelectionBox( `id( `keyboard ), `opt(`notify,`immediate),
		// title for selection box 'keyboard layout'
		_("&Keyboard layout"),
		keyboardlist_by_translation);

    // title for input field to test the keyboard setting
    // (no more than about 25 characters!)
    term test = `TextEntry( _("Keyboard &test:") );
    if (Mode::config ())
	test = `Empty();

    // Put test widget below selection list.
    //
    keyboardsel = `VBox(
		keyboardsel,
		test,
		`VSpacing( 0.8 ),
		// push button
		`PushButton( `id(`expert), _("E&xpert Settings") )
	     );

    /* ----------------------------------------------------------------------
     * Build dialog
     * ----------------------------------------------------------------------*/

    if (Mode::config ())
	Wizard::HideAbortButton();
    else
	Wizard::OpenAcceptDialog();


    term contents =
	    `VBox(
		`HBox(
		    `HWeight ( 20, `HStretch() ),
		    `HWeight ( 50, keyboardsel ),
		    `HWeight ( 20, `HStretch() )
		),
		`VSpacing()
	    );

    // help text for keyboard screen
    string help_text = _("<p>
Choose the <b>keyboard layout</b> to use for
installation and in the installed system.
</p>
");

    // general help trailer
    help_text = help_text + _("<p>
If unsure, use the default values already selected.
</p>");

    // Screen title for keyboard screen
    Wizard::SetContents( _("Keyboard Configuration"), contents,
			 help_text, GetInstArgs::enable_back(), 
			 GetInstArgs::enable_next() );

    Wizard::SetDesktopIcon("keyboard");
    if ( Stage::initial () )
	Wizard::SetTitleIcon( "keyboard" );

    // Initially set the current keyboard to establish a consistent state.
    //

    if (!Mode::config ())
    {
	Keyboard::Set( Keyboard::current_kbd );
    }

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

    any ret = nil;

    
    repeat
	{
	ret = Wizard::UserInput();



	if (ret == `abort && Popup::ConfirmAbort(`painless) && !Mode::config ())
	{
	    Wizard::CloseDialog();
	    return `abort;
	}

	if( ret==`expert )
	    {
	    KeyboardExpertDialog();
	    }

	if( ret == `next || ret == `keyboard )
	    {
	    // Get the selected keyboard.
	    //
	    keyboard = (string)UI::QueryWidget( `id( `keyboard ), `CurrentItem );

	    y2milestone( "on entry %1 current %2 ret %3", keyboard_on_entry,
			 cur_kbd, keyboard );

	    // Set it in Keyboard module.
	    //
	    if ( Mode::config ())
	    {
		import "AutoinstGeneral";
		y2milestone("Autoyast keyboard: %1", keyboard);
		AutoinstGeneral::keyboard["keymap"]  = keyboard;
	    }
	    else if( cur_kbd != keyboard )
	    {
		Keyboard::Set( keyboard );
		cur_kbd = keyboard;
	    }


	    if( ret == `next && !Mode::config ())
		{
		// User wants to keep his changes.
		// Set user_decision flag in keyboard module.
		//
		Keyboard::user_decision = true;

		if ( keyboard_on_entry != Keyboard::current_kbd )
		    {
		    // User has chosen a different keyboard from the database.
		    // ==> clear unique_key in the keyboard module to achieve
		    // configured = no and needed = no in Keyboard::Save() for
		    // _ALL_ keyboards.
		    //
		    y2milestone("Clearing unique key <%1> due to manual selection",
				Keyboard::unique_key );

		    Keyboard::unique_key = "";
		    }
		}
	    }
	} until ( ret == `next || ret == `back || ret == `cancel );

    if( ( ret == `back || ret == `cancel ) && !Mode::config () )
	{
	y2milestone("`back or `cancel restoring: <%1>", keyboard_on_entry );

	// Reset keyboard to initial state.
	//
	Keyboard::Set( keyboard_on_entry );
	}

    Wizard::CloseDialog();

    return (symbol)ret;
    }
