home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / boot / i386 / root / usr / share / YaST2 / modules / Keyboard.ycp < prev    next >
Text File  |  2006-11-29  |  41KB  |  1,519 lines

  1. /**
  2.  * File:
  3.  *   Keyboard.ycp
  4.  *
  5.  * Module:
  6.  *   Keyboard
  7.  *
  8.  * Summary:
  9.  *   Provide information regarding the keyboard.
  10.  *
  11.  * Authors:
  12.  *   Thomas Roelz <tom@suse.de>
  13.  *
  14.  * Maintainer:    Jiri Suchomel <jsuchome@suse.cz>
  15.  *
  16.  * $Id: Keyboard.ycp 32769 2006-09-08 09:29:15Z jsuchome $
  17.  *
  18.  * Usage:
  19.  * ------
  20.  * This module provides the following data for public access via Keyboard::<var-name>.
  21.  *
  22.  *      !!! These are to be used READ_ONLY !!!
  23.  *
  24.  * Set in the constructor after the first import (only after probing):
  25.  *
  26.  *    kb_model
  27.  *    XkbLayout
  28.  *    unique_key
  29.  *
  30.  * Set after having called SetLanguage( keyboard ).
  31.  *
  32.  *    XkbModel
  33.  *    XkbVariant
  34.  *    XkbOptions
  35.  *    LeftAlt
  36.  *    RightAlt
  37.  *    ScrollLock
  38.  *    RightCtl
  39.  *    Apply
  40.  *    keymap
  41.  *    compose_table
  42.  *    current_kbd
  43.  *    ckb_cmd
  44.  *    xkb_cmd
  45.  *
  46.  *
  47.  * This module provides the following functions for public access via Keyboard::<func-name>(...)
  48.  *
  49.  *    Keyboard()            - Module constructor.
  50.  *                        If saved module data exists in continue mode, these are read in.
  51.  *                       Otherwise Hardware is probed.
  52.  *
  53.  *    MakeProposal()            - return user-readable description of keyboard
  54.  *
  55.  *    Probe()                - Force new hardware probing and set public data accordingly.
  56.  *
  57.  *    Save()                - Save module data to /var/lib/YaST2/Keyboard_data.ycp
  58.  *
  59.  *    Restore()            - Load module data from /var/lib/YaST2/Keyboard_data.ycp
  60.  *
  61.  *    SetLanguage()            - Set public data to values corresponding to the given language.
  62.  *
  63.  *    GetKeyboardForLanguage()    - Get the keyboard language for a given language code.
  64.  *
  65.  *     Set()                - Set the keyboard to the given keyboard language.
  66.  *     SetConsole()            - Set the console keyboard to the given keyboard language.
  67.  *
  68.  *     SetX11()            - Set the X11 keyboard to the given keyboard language.
  69.  *
  70.  *    Selection()            - Get map of translated keyboards to be displayed in the GUI.
  71.  *
  72.  */
  73.  
  74. {
  75.  
  76.     module "Keyboard";
  77.     textdomain "country";
  78.  
  79.     import "Arch";
  80.     import "AsciiFile";
  81.     import "Directory";
  82.     import "Label";
  83.     import "Language";
  84.     import "Linuxrc";
  85.     import "Misc";
  86.     import "Mode";
  87.     import "Package";
  88.     import "ProductFeatures";
  89.     import "Stage";
  90.     import "XLibAPI";
  91.     import "XVersion";
  92.  
  93.     // ------------------------------------------------------------------------
  94.     // START: Globally defined data to be accessed via Keyboard::<variable>
  95.     // ------------------------------------------------------------------------
  96.  
  97.     // kb_model string
  98.     //
  99.     global string kb_model = "pc104";
  100.  
  101.     // XkbModel string
  102.     //
  103.     global string XkbModel = "";
  104.  
  105.     // XkbLayout string
  106.     // Only some keyboards do report this information (e.g. sparc).
  107.     //
  108.     global string XkbLayout = "";
  109.  
  110.     // XkbVariant string
  111.     //
  112.     global string XkbVariant = "";
  113.  
  114.     // keymap string for ncurses
  115.     //
  116.     global string keymap = "us.map.gz";
  117.  
  118.     // compose_table entry
  119.     //
  120.     global string compose_table = "clear winkeys shiftctrl latin1.add";
  121.  
  122.     // X11 Options string
  123.     //
  124.     global string XkbOptions = "";
  125.  
  126.     // X11 LeftAlt
  127.     //
  128.     global string LeftAlt = "";
  129.  
  130.     // X11 RightAlt
  131.     //
  132.     global string RightAlt = "";
  133.  
  134.     // X11 RightCtl
  135.     //
  136.     global string RightCtl = "";
  137.  
  138.     // X11 ScrollLock
  139.     //
  140.     global string ScrollLock = "";
  141.  
  142.     // Apply string fuer xbcmd
  143.     //
  144.     global string Apply = "";
  145.  
  146.     // The console keyboard command
  147.     //
  148.     global string ckb_cmd = "";
  149.  
  150.     // The X11 keyboard command
  151.     //
  152.     global string xkb_cmd = "";
  153.  
  154.     // The keyboard currently set.
  155.     //
  156.     global string current_kbd = "";
  157.  
  158.     /**
  159.      * keyboard set on start
  160.      */
  161.     global string keyboard_on_entry    = "";
  162.  
  163.     /**
  164.      * expert values on start
  165.      */
  166.     global map expert_on_entry        = $[];
  167.  
  168.     // The default keyboard if set.
  169.     //
  170.     global string default_kbd = "";
  171.  
  172.     // Flag indicating if the user has chosen a keyboard.
  173.     // To be set from outside.
  174.     //
  175.     global boolean user_decision = false;
  176.  
  177.     // unique key
  178.     //
  179.     global string unique_key = "";
  180.  
  181.     // state of Expert settings
  182.     global boolean ExpertSettingsChanged = false;
  183.  
  184.     // --------------------------------------------------------------
  185.     // END: Globally defined data to be accessed via Keyboard::<variable>
  186.     // --------------------------------------------------------------
  187.  
  188.  
  189.     // --------------------------------------------------------------
  190.     // START: Locally defined data
  191.     // --------------------------------------------------------------
  192.  
  193.     // if Keyboard::Restore() was called
  194.     boolean restore_called = false;
  195.  
  196.     // User readable description, access via Keyboard::MakeProposal()
  197.     //
  198.     string name = "";
  199.  
  200.     // Keyboard description from DB
  201.     //
  202.     list kbd_descr = [];
  203.  
  204.     string kbd_tty = "tty1 tty2 tty3 tty4 tty5 tty6 tty8 tty9 tty10 tty11 tty12 tty13 tty14 tty15 tty16 tty17 tty18 tty19 tty20";
  205.  
  206.     string kbd_rate = "";
  207.     string kbd_delay = "";
  208.     string kbd_numlock = "";
  209.     string kbd_capslock = "";
  210.     string kbd_scrlock = "";
  211.     string kbd_disable_capslock = "";
  212.  
  213.     list keyboardprobelist = [];    // List of all probed keyboards
  214.  
  215.     // parameters for dumpkeys command - see bug #116143
  216.     map charsets    = $[
  217.     "Pl02.map.gz"            : "iso-8859-2",
  218.     "br-abnt2.map.gz"        : "iso-8859-15",
  219.     "cz-us-qwertz.map.gz"        : "iso-8859-2",
  220.     "cz-lat2-us.map.gz"        : "iso-8859-2",
  221.     "de-lat1-nd.map.gz"        : "iso-8859-15",
  222.     "de-latin1-nodeadkeys.map.gz"    : "iso-8859-15",
  223.     "es.map.gz"            : "iso-8859-15",
  224.     "fr-latin1.map.gz"        : "iso-8859-15",
  225.     "gr.map.gz"            : "iso-8859-7",
  226.     "hu.map.gz"            : "iso-8859-2",
  227.     "it.map.gz"            : "iso-8859-15",
  228.     "no-latin1.map.gz"        : "iso-8859-15",
  229.     "pt-latin1.map.gz"        : "iso-8859-15",
  230.     "ru1.map.gz"            : "koi8-r",
  231.     "sk-qwertz.map.gz"        : "iso-8859-2",
  232.     "sk-qwerty.map.gz"        : "iso-8859-2",
  233.     "slovene.map.gz"        : "iso-8859-2"
  234.     ];
  235.  
  236.     // ----------------------------------------------------------------------
  237.     // END: Locally defined data
  238.     // ----------------------------------------------------------------------
  239.  
  240.     // function prototypes
  241.     global define void Set (string keyboard);
  242.  
  243. // ------------------------------------------------------------------
  244. // START: Globally defined functions
  245. // ------------------------------------------------------------------
  246.  
  247. /**
  248.  * GetKbdSysconfig()
  249.  *
  250.  * Restore the the non-keyboard values from sysconfig.
  251.  */
  252.  
  253. define void GetKbdSysconfig()
  254.     ``{
  255.     // Read the the variables not touched by the module to be able to
  256.     // store them again on Save().
  257.     //
  258.     kbd_tty = Misc::SysconfigRead( .sysconfig.keyboard.KBD_TTY, kbd_tty );
  259.     kbd_rate = Misc::SysconfigRead( .sysconfig.keyboard.KBD_RATE, kbd_rate );
  260.     kbd_delay = Misc::SysconfigRead( .sysconfig.keyboard.KBD_DELAY, kbd_delay );
  261.     kbd_numlock = Misc::SysconfigRead( .sysconfig.keyboard.KBD_NUMLOCK,
  262.                                        kbd_numlock );
  263.     kbd_capslock = Misc::SysconfigRead( .sysconfig.keyboard.KBD_CAPSLOCK,
  264.                                         kbd_capslock );
  265.     kbd_scrlock = Misc::SysconfigRead( .sysconfig.keyboard.KBD_SCRLOCK,
  266.                                        kbd_scrlock );
  267.     kbd_disable_capslock =
  268.     Misc::SysconfigRead( .sysconfig.keyboard.KBD_DISABLE_CAPS_LOCK,
  269.                          kbd_disable_capslock );
  270.  
  271.     y2milestone( "rate:%1 delay:%2 numlock:%3 capslock:%4 scrlock:%5 disclock:%6",
  272.          kbd_rate, kbd_delay, kbd_numlock, kbd_capslock,
  273.          kbd_scrlock, kbd_disable_capslock );
  274.     y2milestone( "tty:%1", kbd_tty );
  275.     }
  276.  
  277. /*
  278.  * get_reduced_keyboard_db()
  279.  *
  280.  * Read the Keyboard DB and select entries for current XkbModel and architecture.
  281.  *
  282.  * @return  Reduced keyboard DB (map)
  283.  */
  284.  
  285. define map<string,list> get_reduced_keyboard_db() {
  286.     /*
  287.      * The keyboard DB is a very big map containing entries for all known keyboard
  288.      * languages. Each of these entries contains a map of the different known
  289.      * architectures and each of these architectures contains a map for the different
  290.      * kb_models possible on the given architecture. This innermost map finally contains
  291.      * data relevant for ncurses.
  292.      *
  293.      * $[
  294.      *    "english-us":
  295.      *     [
  296.      *      ...language stuff...
  297.      *      $[   "i386" :
  298.      *           $[ "pc104":
  299.      *              $[   "ncurses": "us.map.gz" ]],
  300.      *
  301.      * What now follows is code that cuts out from this map the unnecessary
  302.      * architectures and XkbModels. The different languages are kept.
  303.      *
  304.      * Load the keyboard DB.
  305.      * Do not hold this database in a permanent module variable (it's very large).
  306.      */
  307.  
  308.     // eval is necessary for translating the texts needed to be translated
  309.     map<string,list> all_keyboards = (map<string,list>)
  310.     eval(SCR::Read( .target.yast2, "keyboard_raw.ycp" ));
  311.  
  312.     if (all_keyboards == nil) all_keyboards = $[];
  313.  
  314.     // The new reduced map of keyboard data.
  315.     //
  316.     map<string,list> keyboards = $[];
  317.     string arch = Arch::architecture ();
  318.     if( arch == "ppc64" )
  319.     {
  320.     arch = "ppc";
  321.     }
  322.     y2milestone( "get_reduced_keyboard_db: Arch::architecture () %1 used %2",
  323.                  Arch::architecture (), arch );
  324.  
  325.     // loop over all languages
  326.     foreach (string kb_lang, list description, all_keyboards, {
  327.  
  328.     if (size (description) == 2)
  329.     {
  330.         // Skip langage specific naming of keyboard languages.
  331.         // Select the keyboard data.
  332.         //
  333.         map keyboards_archi = description[1]:$[];        // all architectures
  334.  
  335.         // Select current architecture.
  336.         //
  337.         map keyboard_archi = keyboards_archi[arch]:$[];
  338.  
  339.         // Get the data for the current kb_model in the current architecture.
  340.         //
  341.         map keyboard_model = keyboard_archi[kb_model]:$[];
  342.  
  343.         if( size( keyboard_model ) > 0 )    // found an entry
  344.         {
  345.         // Add the data found (as list) to the new map under the current
  346.         // language key.
  347.         //
  348.         list keyboard_selected = [];    // temporary list
  349.  
  350.         // Add the language stuff.
  351.         //
  352.         keyboard_selected = add( keyboard_selected, description[0]:"" );
  353.  
  354.         // Add the Qt- and ncurses-data.
  355.         //
  356.         keyboard_selected = add( keyboard_selected, keyboard_model );
  357.  
  358.         // Add this list to the reduced keyboard map under the current language key.
  359.         //
  360.         keyboards[kb_lang] = keyboard_selected;
  361.         }
  362.     }
  363.     });
  364.  
  365.     return keyboards;
  366. };    // get_reduced_keyboard_db()
  367.  
  368.     /**
  369.      * Return a map for conversion from keymap to YaST2 keyboard code()
  370.      * Get the map of translated keyboard names.
  371.      * @param   -
  372.      * @return  map of $[ keyboard_code : keyboard_name, ...] for all known
  373.      *      keyboards. 'keyboard_code' is used internally in Set and Get
  374.      *      functions. 'keyboard_name' is a user-readable string.
  375.      *      Uses Language::language for translation.
  376.      *
  377.      */
  378.     global define map<string, string> keymap2yast() {
  379.  
  380.     return mapmap (string code, list kbd_value, get_reduced_keyboard_db(), {
  381.         map code_map    = kbd_value[1]:$[];
  382.         list codel    = splitstring (code_map["ncurses"]:"", ".");
  383.         return  $[ codel[0]:"": code ];
  384.     });
  385.     }
  386.  
  387. /**
  388.  * GetX11KeyData()
  389.  *
  390.  * Get the keyboard info for X11 for the given keymap
  391.  *
  392.  * @param    name of the keymap
  393.  *
  394.  * @return  map containing the x11 config data
  395.  *
  396.  */
  397. global define map GetX11KeyData (string keymap) {
  398.  
  399.     string cmd    = "/usr/sbin/xkbctrl";
  400.     map x11data = $[];
  401.  
  402.     if (SCR::Read(.target.size, cmd) > 0 )
  403.     {
  404.     string file = Directory::tmpdir + "/xkbctrl.out";
  405.     cmd    = cmd + " " + keymap;
  406.     SCR::Execute (.target.bash, cmd + " > " + file );
  407.     x11data = (map)SCR::Read(.target.ycp, file );
  408.     }
  409.     else
  410.     {
  411.     y2warning ("/usr/sbin/xkbctrl not found");
  412.     }
  413.     return x11data;
  414. }
  415.  
  416.   /**
  417.    * Return human readable (and translated) name of the given keyboard map
  418.    * @param kbd keyboard map
  419.    * @return string
  420.    */
  421.   define string GetKeyboardName (string kbd) {
  422.  
  423.     map keyboards    = get_reduced_keyboard_db ();
  424.     list descr        = keyboards[kbd]:[];
  425.     string ret        = kbd;
  426.  
  427.     if (descr != [])
  428.     {
  429.     locale translate    = descr[0]:kbd;
  430.     ret = (string)eval(translate);
  431.     }
  432.     return ret;
  433.   }
  434.  
  435.   /**
  436.    * GetExpertValues()
  437.    *
  438.    * Return the values for the various expert settings in a map
  439.    *
  440.    * @return  map with values filled in
  441.    *
  442.    */
  443.   global define map GetExpertValues() {
  444.     map ret = $[ "rate"     : kbd_rate,
  445.                  "delay"    : kbd_delay,
  446.                  "numlock"  : kbd_numlock,
  447.                  "capslock" : kbd_capslock=="yes" ? true : false,
  448.                  "scrlock"  : kbd_scrlock=="yes" ? true : false,
  449.                  "tty"      : kbd_tty,
  450.                  "discaps"  : kbd_disable_capslock=="yes" ? true : false ];
  451.     return( ret );
  452.   }
  453.  
  454. /**
  455.  * Get the system_language --> keyboard_language conversion map.
  456.  *
  457.  * @return  conversion map
  458.  *
  459.  * @see    get_xkblayout2keyboard()
  460.  */
  461.  
  462. define map get_lang2keyboard() {
  463.  
  464.     map base_lang2keyboard = (map)SCR::Read(.target.yast2, "lang2keyboard.ycp");
  465.     if (base_lang2keyboard == nil) base_lang2keyboard = $[];
  466.  
  467.     return union (base_lang2keyboard, Language::GetLang2KeyboardMap ());
  468. }
  469.  
  470.  
  471.  
  472. /**
  473.  * GetKeyboardForLanguage()
  474.  *
  475.  * Get the keyboard language for the given system language.
  476.  *
  477.  * @param    System language code, e.g. "en_US".
  478.  *        Default keyboard language to be returned if nothing found.
  479.  *
  480.  * @return  The keyboard language for this language, e.g. "english-us"
  481.  *        or the default value if nothing found.
  482.  *
  483.  */
  484. global define string GetKeyboardForLanguage( string sys_language,
  485.                                              string default_keyboard) {
  486.  
  487.     map lang2keyboard    = get_lang2keyboard();
  488.     string kb        = lang2keyboard[sys_language]:"";
  489.  
  490.     if (kb == "")
  491.     {
  492.     sys_language    = substring (sys_language, 0,2);
  493.     kb        = lang2keyboard[sys_language]:default_keyboard;
  494.     }
  495.     y2milestone( "GetKeyboardForLanguage lang:%1 def:%2 ret:%3",
  496.          sys_language, default_keyboard, kb);
  497.     return kb;
  498. }
  499.  
  500.  
  501.  
  502. /**
  503.  * run X11 configuration after inital boot
  504.  */
  505. define boolean x11_setup_needed () {
  506.  
  507.     return
  508.     Arch::x11_setup_needed () &&
  509.     ! (Linuxrc::serial_console() || Linuxrc::vnc() || Linuxrc::usessh()) &&
  510.     ((Stage::initial () && !Linuxrc::text ()) ||
  511.      Package::Installed ("yast2-x11"));
  512. }
  513.  
  514. /**
  515.  * SetLanguage()
  516.  *
  517.  * Set language specific module data to reflect the given language.
  518.  *
  519.  * @param    Keyboard language e.g.  "english-us"
  520.  *
  521.  * @return  true    - Success. Language set in public data.
  522.  *        false    - Error. Language not set.
  523.  *
  524.  */
  525.  
  526. global define boolean SetLanguage (string keyboard) {
  527.  
  528.     y2milestone ("Setting keyboard to: <%1>", keyboard );
  529.  
  530.     // Get the reduced keyboard DB.
  531.     //
  532.     map keyboards = get_reduced_keyboard_db();
  533.  
  534.     y2debug( "reduced kbd db %1", keyboards );
  535.     // Get the entry from the reduced local map for the given language.
  536.     //
  537.     kbd_descr = keyboards[keyboard]:[];
  538.  
  539.     y2milestone ("Description for keyboard <%1>: <%2>",keyboard, kbd_descr);
  540.  
  541.     if ( kbd_descr != [] )    // keyboard found
  542.     {
  543.         // Get keymap for ncurses
  544.         //
  545.         keymap = kbd_descr[1, "ncurses"]:"us.map.gz";
  546.         locale translate = kbd_descr[0]:keyboard;
  547.         name = (string)eval(translate);
  548.  
  549.         map x11data = GetX11KeyData( keymap );
  550.         y2milestone( "x11data=%1", x11data );
  551.  
  552.         XkbModel = x11data["XkbModel"]:"pc104";
  553.         XkbLayout = x11data["XkbLayout"]:"";
  554.         XkbVariant = x11data["XkbVariant"]:"basic";
  555.         XkbOptions = x11data["XkbOptions"]:"";
  556.         LeftAlt = x11data["LeftAlt"]:"";
  557.         RightAlt = x11data["RightAlt"]:"";
  558.         ScrollLock = x11data["ScrollLock"]:"";
  559.         RightCtl = x11data["RightCtl"]:"";
  560.         Apply = x11data["Apply"]:"";
  561.  
  562.         // Build the compose table entry.
  563.         //
  564.         compose_table = "clear ";
  565.  
  566.         if ( XkbModel == "pc104" || XkbModel == "pc105" )
  567.         {
  568.         compose_table = compose_table + "winkeys shiftctrl ";
  569.         }
  570.  
  571.         // Check for "compose" entry in keytable, might define
  572.         // a different encoding (i.e. "latin2").
  573.         //
  574.         string compose = kbd_descr[1,"compose"]:"latin1.add";
  575.  
  576.         compose_table = compose_table + compose;
  577.     }
  578.     else    // Language not found.
  579.     {
  580.         return false;    // Error
  581.     }
  582.  
  583.     // Console command...
  584.     //
  585.     // dumpkeys may need -c parameter (see #116143)
  586.     string dumpkeys = " ; dumpkeys";
  587.     if (haskey (charsets, keymap))
  588.     {
  589.         dumpkeys = sformat ("%1 -c %2 ", dumpkeys, charsets[keymap]:"");
  590.     }
  591.     ckb_cmd = "/bin/loadkeys " + keymap + dumpkeys + " | loadkeys -u";
  592.     // FIXME should be "/bin/loadkeys -u " + keymap (see bug 44223)
  593.  
  594.     // X11 command...
  595.     // do not try to run this with remote X display
  596.     if (size (Apply) >0 && x11_setup_needed ())
  597.     {
  598.         xkb_cmd = XVersion::binPath () + "/setxkbmap " + Apply;
  599.     }
  600.     else
  601.     {
  602.         xkb_cmd = "";
  603.     }
  604.  
  605.     // Store keyboard just set.
  606.     //
  607.     current_kbd = keyboard;
  608.  
  609.     // On first assignment store default keyboard.
  610.     //
  611.     if ( default_kbd == "" )    // not yet assigned
  612.     {
  613.         default_kbd = current_kbd;
  614.     }
  615.  
  616.     return true;    // OK
  617. } // SetLanguage()
  618.  
  619.  
  620. /**
  621.  * Restore()
  622.  *
  623.  * Restore the the data from sysconfig.
  624.  *
  625.  * @return  true    - Data could be restored
  626.  *        false    - Restore not successful
  627.  *
  628.  * @see    Save()
  629.  */
  630. global define boolean Restore () {
  631.  
  632.     boolean ret        = false;
  633.     restore_called    = true;
  634.     GetKbdSysconfig();
  635.  
  636.     if (!Stage::initial ())
  637.     {
  638.     // Read YaST2 keyboard var.
  639.     //
  640.     current_kbd = Misc::SysconfigRead(.sysconfig.keyboard.YAST_KEYBOARD,"");
  641.     integer pos = find (current_kbd, ",");
  642.     if (pos != nil && pos > 0)
  643.     {
  644.         kb_model    = substring (current_kbd, pos + 1);
  645.         current_kbd    = substring (current_kbd, 0, pos);
  646.     }
  647.  
  648.     y2milestone ("current_kbd %1 model %2", current_kbd, kb_model);
  649.     if (current_kbd == "")
  650.     {
  651.         y2milestone("Restoring data failed");
  652.         ret = false;
  653.     }
  654.     else
  655.     {
  656.         if (!Mode::config ())
  657.         {
  658.         // Restore module data.
  659.         //
  660.         SetLanguage( current_kbd );
  661.         y2milestone("Restored data (sysconfig) for keyboard: <%1>",current_kbd);
  662.         }
  663.         else
  664.         {
  665.         // for cloning, to be shown in Summary
  666.         name    = GetKeyboardName (current_kbd);
  667.         }
  668.  
  669.         ret = true;
  670.     }
  671.     }
  672.     else
  673.     {
  674.     ret = true;
  675.     }
  676.     return ret;
  677. } // Restore()
  678.  
  679. /*
  680.  * get_xkblayout2keyboard()
  681.  *
  682.  * Get the xkblayout --> keyboard_language conversion map.
  683.  *
  684.  * @return  conversion map
  685.  *
  686.  * @see    get_lang2keyboard()
  687.  */
  688.  
  689. define map get_xkblayout2keyboard()
  690.     ``{
  691.     // The xkblayout --> keyboard_language conversion map.
  692.     //
  693.     map xkblayout2keyboard = (map)SCR::Read( .target.yast2,
  694.                                              "xkblayout2keyboard.ycp" );
  695.  
  696.     if ( xkblayout2keyboard == nil ) xkblayout2keyboard = $[];
  697.  
  698.     return( xkblayout2keyboard );
  699.     }    // get_xkblayout2keyboard()
  700.  
  701.  
  702. /**
  703.  * XkblayoutToKeyboard()
  704.  *
  705.  * Convert X11 keyboard layout name to yast2 name for keyboard description.
  706.  * e.g. "de" --> "german"
  707.  *
  708.  * @param  string x11_layout
  709.  *
  710.  * @return         string  yast2 name for keyboard description
  711.  */
  712.  
  713. define string XkblayoutToKeyboard( string x11_layout )
  714.     ``{
  715.     map xkblayout2keyboard = get_xkblayout2keyboard();
  716.  
  717.     // Now get the YaST2 internal representation of this keyboard layout.
  718.     //
  719.     string ret = xkblayout2keyboard[x11_layout]:"";
  720.     y2milestone(" XkblayoutToKeyboard x11:%1 ret:%2", x11_layout, ret );
  721.      return( ret );
  722.      }
  723.  
  724. /**
  725.  * Probe keyboard and set local module data.
  726.  */
  727.  
  728. define void probe_settings()
  729.     ``{
  730.     /*
  731.      * First assign the kb_model. This is e.g. "pc104".
  732.      * Aside from being used directly for writing the XF86Config file this is later on
  733.      * used to search the YaST2 keyboards database (it's a key in a map).
  734.      */
  735.  
  736.     // Probe the keyboard.
  737.     //
  738.     if (!Mode::config ())
  739.     {
  740.     keyboardprobelist = (list)SCR::Read( .probe.keyboard );
  741.  
  742.     y2milestone("Probed keyboard: <%1>", keyboardprobelist );
  743.  
  744.     // Get the first keyboard from the list (it should exist).
  745.     //
  746.     map keyboardmap1 = keyboardprobelist[0]:$[];
  747.  
  748.     // Get the unique_key
  749.     //
  750.     unique_key = keyboardmap1["unique_key"]:"";
  751.  
  752.     // Get the keyboard data for this first keyboard.
  753.     //
  754.     map keyboardmap2 = keyboardmap1["keyboard", 0]:$[];
  755.  
  756.     // Assign the XkbModel.
  757.     //
  758.     kb_model = keyboardmap2["xkbmodel"]:"pc104";
  759.  
  760.     y2milestone("kb_model: <%1>", kb_model );
  761.  
  762.     // Assign the XkbLayout.
  763.     // Only some keyboards do report this information (e.g. sparc).
  764.     //
  765.     XkbLayout = keyboardmap2["xkblayout"]:"";
  766.  
  767.     y2milestone("Xkblayout: <%1>", XkbLayout );
  768.     }
  769.     else
  770.     {
  771.     kb_model = "pc104";
  772.     }
  773.  
  774.     return;
  775.     };    // probe_settings()
  776.  
  777. /**
  778.  * Probe()
  779.  *
  780.  * Allow for intentional probing by applications.
  781.  *
  782.  * @see    Keyboard()
  783.  */
  784. global define void Probe() {
  785.  
  786.     y2milestone( "Keyboard::Probe" );
  787.     probe_settings();
  788.  
  789.     // Set the module to the current system language to achieve a consistent
  790.     // state. This may be superfluous because a client may do it also but
  791.     // just in case...
  792.     //
  793.     string default_keyboard = "";
  794.  
  795.     // Some keyboards (i.e. sparc) report their layout, try to use this information here
  796.     //
  797.     if( XkbLayout != "" )    // we do have hardware info
  798.     {
  799.     default_keyboard = GetKeyboardForLanguage( XkbLayout, default_keyboard);
  800.     }
  801.     else // no hardware info ==> select default keyboard dependent on system language
  802.     {
  803.     default_keyboard = GetKeyboardForLanguage( Language::language, "english-us" );
  804.     }
  805.  
  806.     // Set the module state.
  807.     //
  808.     SetLanguage( default_keyboard );
  809.  
  810.     if (Stage::initial ())
  811.     {
  812.     string keytable = Linuxrc::InstallInf ("Keytable");
  813.     // set the keyboard from linuxrc
  814.     if (keytable != nil)
  815.     {
  816.         y2milestone ("linuxrc keyboard: %1", keytable);
  817.         map map2yast = (map) union (keymap2yast (), $[
  818.         "dk"        : "danish",
  819.         "de-lat1-nd"    : "german",
  820.         ]);
  821.         if (issubstring (keytable, ".map.gz"))
  822.         keytable = substring (keytable, 0, find (keytable, ".map.gz"));
  823.         if (map2yast[keytable]:"" != "")
  824.         {
  825.         Set (map2yast[keytable]:"");
  826.         // do not reset it in proposal
  827.         user_decision    = true;
  828.         }
  829.     }
  830.     // set keyboard now (before proposal - see bug #113664)
  831.     else if (Language::preselected != "en_US")
  832.     {
  833.         y2milestone ("language (%1) was preselected -> setting keyboard to %2",
  834.         Language::preselected, default_keyboard);
  835.         Set (default_keyboard);
  836.     }
  837.     }
  838.     y2milestone( "End Probe %1", default_keyboard );
  839. } // Probe()
  840.  
  841.  
  842. /**
  843.  * Keyboard()
  844.  *
  845.  * The module constructor.
  846.  * Sets the proprietary module data defined globally for public access.
  847.  * This is done only once (and automatically) when the module is loaded for the first time.
  848.  *
  849.  * @see    Probe()
  850.  */
  851. global define void Keyboard() {
  852.  
  853.     if (Mode::config ())
  854.     return;
  855.  
  856.     // We have three possible sources of information:
  857.     //
  858.     // Newly probed data:    - installation initial mode --> probing
  859.     // sysconfig:        - installation continue mode or normal mode
  860.     // XF86Config:        - restoring from sysconfig failed and running system
  861.     //
  862.     y2milestone( "Keyboard::Keyboard init:%1 update:%2", Stage::initial (),
  863.          Mode::update () );
  864.     boolean success = false;
  865.  
  866.     // If not in initial mode try to restore from sysconfig.
  867.     //
  868.     if (!Stage::initial ())
  869.     {
  870.     success = Restore();
  871.  
  872.     // If this failed and we are in a running system try to restore from XF86Config.
  873.     //
  874.     if (!success && Mode::normal () && x11_setup_needed ())
  875.     {
  876.         // Get the current layout from XF86Config and
  877.         // set keyboard module accordingly.
  878.  
  879.         string current_layout = XLibAPI::getXkbLayout ();
  880.  
  881.         y2milestone("keyboard layout YaST2: %1", current_layout );
  882.  
  883.         // Set the keyboard variables to this value if possible.
  884.         //
  885.         if ( current_layout != "" )
  886.         {
  887.         SetLanguage( current_layout );
  888.         y2milestone("Restored data (XF86Config) for keyboard: <%1>", current_kbd );
  889.         success = true;
  890.         }
  891.         }
  892.     }
  893.     else
  894.     {
  895.     GetKbdSysconfig();
  896.     }
  897.  
  898.     // In initial mode or if restoring failed do probe.
  899.     //
  900.     if( Stage::initial () || !success )    // initial mode or no restore success
  901.     {
  902.     // On module entry probe the hardware and set all those data
  903.     // needed for public access.
  904.     //
  905.     Probe();
  906.     }
  907.  
  908.     return;
  909. }    // Keyboard()
  910.  
  911. /**
  912.  * Just store inital values - read was done in constructor
  913.  */
  914. global define boolean Read () {
  915.  
  916.     keyboard_on_entry        = current_kbd;
  917.     expert_on_entry        = GetExpertValues ();
  918.     ExpertSettingsChanged    = false;
  919.     y2debug ("keyboard_on_entry: %1", keyboard_on_entry);
  920.     return true;
  921. }
  922.  
  923. /**
  924.  * was anything modified?
  925.  */
  926. global define boolean Modified () {
  927.     return (current_kbd != keyboard_on_entry || ExpertSettingsChanged);
  928. }
  929.  
  930.  
  931. /**
  932.  * Updates the X11 keyboard settings (using SaX library)
  933.  * @return boolean - success
  934.  */
  935.  
  936. global define boolean xf86_update() {
  937.  
  938.     y2milestone ("Storing current keyboard settings into X11 config file...");
  939.  
  940.     map xkbctrl2SaX    = $[
  941.     "ModeShift"    : "SaX::XKB_MAP_MODESHIFT",
  942.     "Compose"    : "SaX::XKB_MAP_COMPOSE",
  943.     "ModeLock"    : "SaX::XKB_MAP_MODELOCK",
  944.     "ScrollLock"    : "SaX::XKB_MAP_SCROLLLOCK",
  945.     "Meta"        : "SaX::XKB_MAP_META",
  946.     "Control"    : "SaX::XKB_MAP_CONTROL"
  947.     ];
  948.  
  949.     XLibAPI::setXkbLayout (XkbLayout);
  950.     XLibAPI::setXkbModel (XkbModel);
  951.     XLibAPI::setXkbVariant (XkbLayout, XkbVariant);
  952.     XLibAPI::setXkbMappings ($[
  953.     "SaX::XKB_LEFT_ALT"    : xkbctrl2SaX[LeftAlt]:LeftAlt,
  954.     "SaX::XKB_RIGHT_ALT"    : xkbctrl2SaX[RightAlt]:RightAlt,
  955.     "SaX::XKB_SCROLL_LOCK"    : xkbctrl2SaX[ScrollLock]:ScrollLock,
  956.     "SaX::XKB_RIGHT_CTL"    : xkbctrl2SaX[RightCtl]:RightCtl
  957.     ]);
  958.     if (XkbOptions != "")
  959.     XLibAPI::setXkbOptions (splitstring (XkbOptions, ","));
  960.     return XLibAPI::Write ();
  961. }
  962.  
  963.  
  964. /**
  965.  * Save the current data into a file to be read after a reboot.
  966.  *
  967.  * @param    boolean update_x11: true if X11 config should be updated
  968.  */
  969. global define void Save (boolean update_x11) {
  970.  
  971.     if (Mode::update ())
  972.     {
  973.     string kbd = Misc::SysconfigRead (.sysconfig.keyboard.YAST_KEYBOARD,"");
  974.     if (size(kbd)==0)
  975.     {
  976.         string kmap = Misc::SysconfigRead(.sysconfig.keyboard.KEYTABLE, "");
  977.         if (size(kmap)>0)
  978.         {
  979.         map data = GetX11KeyData( kmap );
  980.         if (size(data["XkbLayout"]:"")>0)
  981.         {
  982.             kbd = XkblayoutToKeyboard( data["XkbLayout"]:"" );
  983.             kbd = kbd + "," + data["XkbModel"]:"pc104";
  984.             SCR::Write (.sysconfig.keyboard.YAST_KEYBOARD, kbd );
  985.             SCR::Write (.sysconfig.keyboard.YAST_KEYBOARD.comment,
  986. "\n# The YaST-internal identifier of the attached keyboard.\n#\n");
  987.             SCR::Write (.sysconfig.keyboard, nil );    // flush
  988.         }
  989.         }
  990.     }
  991.     return;
  992.     }
  993.  
  994.     // Write some sysconfig variables.
  995.     // Set keytable, compose_table and tty list.
  996.     //
  997.     SCR::Write(.sysconfig.keyboard.YAST_KEYBOARD, current_kbd+","+kb_model );
  998.     SCR::Write(.sysconfig.keyboard.YAST_KEYBOARD.comment,
  999.        "\n# The YaST-internal identifier of the attached keyboard.\n#\n");
  1000.  
  1001.     SCR::Write(.sysconfig.keyboard.KEYTABLE, keymap );
  1002.     SCR::Write(.sysconfig.keyboard.COMPOSETABLE, compose_table );
  1003.     SCR::Write(.sysconfig.keyboard.KBD_TTY, kbd_tty );
  1004.     SCR::Write(.sysconfig.keyboard.KBD_RATE, kbd_rate );
  1005.     SCR::Write(.sysconfig.keyboard.KBD_DELAY, kbd_delay );
  1006.     SCR::Write(.sysconfig.keyboard.KBD_NUMLOCK, kbd_numlock );
  1007.     SCR::Write(.sysconfig.keyboard.KBD_CAPSLOCK, kbd_capslock );
  1008.     SCR::Write(.sysconfig.keyboard.KBD_SCRLOCK, kbd_scrlock );
  1009.     SCR::Write(.sysconfig.keyboard.KBD_DISABLE_CAPS_LOCK, kbd_disable_capslock);
  1010.     SCR::Write(.sysconfig.keyboard, nil );    // flush
  1011.  
  1012.     // As a preliminary step mark all keyboards except the one to be configured
  1013.     // as configured = no and needed = no. Afterwards this one keyboard will be
  1014.     // marked as configured = yes and needed = yes. This has to be done  to
  1015.     // prevent any problems that may occur if the user plugs in and out different
  1016.     // keyboards or if a keyboard is selected from the database despite the fact
  1017.     // that a keyboard has been probed. Otherwise the config popup may nag the user
  1018.     // again and again.
  1019.     //
  1020.     // In order to get a list of *ALL* keyboards that have ever been conected to
  1021.     // the system we must do a *manual* probing (accessing the libhd database).
  1022.     // Doing only a "normal" probing would deliver only the *currently* attached
  1023.     // keyboards which in turn would not allow to "unmark" all keyboards that may
  1024.     // have been removed.
  1025.     //
  1026.     // Do *NOT* use probe_settings() here because this would newly assign the global
  1027.     // "unique_key" which is not what we want here. It may have been cleared
  1028.     // intentionally due to the users selection of a keyboard from the YaST database.
  1029.     // Furthermore this would assign a unique_key even if there is no keyboard attached
  1030.     // (if there _was_ a keyboard attached).
  1031.     //
  1032.     // Manual probing
  1033.     keyboardprobelist = (list)SCR::Read(.probe.keyboard.manual);
  1034.  
  1035.     integer list_size = size( keyboardprobelist );
  1036.  
  1037.     if (list_size > 0)
  1038.     {
  1039.     integer i = 0;
  1040.  
  1041.     while ( i < list_size )    // Loop over all keyboards
  1042.     {
  1043.         map    current_keyboard = keyboardprobelist[i]:$[];
  1044.         string current_key   = current_keyboard["unique_key"]:"";
  1045.  
  1046.         if ( current_key != "" )
  1047.         {
  1048.         // OK, there is a key to mark...
  1049.         //
  1050.         if ( current_key != unique_key )
  1051.             {
  1052.             // OK, this key is _not_ the key of the keyboard to be configured.
  1053.             // If the user selected a keyboard from the database Keyboard::unique_key
  1054.             // has been set to "" there which also applies here.
  1055.             // ==> Mark with "no".
  1056.             //
  1057.             SCR::Write( .probe.status.configured, current_key, `no );
  1058.             y2milestone("Marked keyboard <%1> as configured = no", current_key );
  1059.  
  1060.             SCR::Write( .probe.status.needed, current_key, `no );
  1061.             y2milestone("Marked keyboard <%1> as needed = no", current_key );
  1062.             }
  1063.         else
  1064.             {
  1065.             y2milestone("Skipping active key <%1> --> to be configured", current_key );
  1066.             }
  1067.         }
  1068.  
  1069.         i = i + 1;    // next keyboard
  1070.     }
  1071.     }
  1072.     else
  1073.     {
  1074.     y2milestone("No probed keyboards. Not unconfiguring any keyboards");
  1075.     }
  1076.  
  1077.     // Only if the keyboard has been probed in this run the unique_key
  1078.     // is not empty. Only in this case mark the device as "configured".
  1079.     // In any other case the device should already be configured and
  1080.     // the marking can't be done because the unique_key is missing.
  1081.     // ==> Only mark after probing!
  1082.     //
  1083.     if( unique_key != "" )
  1084.     {
  1085.     SCR::Write( .probe.status.configured, unique_key, `yes );
  1086.     y2milestone("Marked keyboard <%1> as configured", unique_key );
  1087.  
  1088.     if( ! Linuxrc::serial_console () )
  1089.         {
  1090.         SCR::Write( .probe.status.needed, unique_key, `yes );
  1091.         y2milestone("Marked keyboard <%1> as needed", unique_key );
  1092.         }
  1093.     }
  1094.     else
  1095.     {
  1096.     y2milestone("NOT marking keyboard as configured (no unique_key)");
  1097.     }
  1098.  
  1099.     // Adapt the X11 config file content to match the current settings
  1100.     if (x11_setup_needed() && update_x11 &&(Mode::normal() || Stage::reprobe()))
  1101.     {
  1102.     xf86_update();
  1103.     }
  1104.  
  1105.     y2milestone("Saved data for keyboard: <%1>", current_kbd );
  1106.  
  1107.     return;
  1108. }    // Save()
  1109.  
  1110.  
  1111. /**
  1112.  * Name()
  1113.  * Just return the keyboard name, without setting anything.
  1114.  * @return string user readable description.
  1115.  */
  1116.  
  1117. global define string Name() {
  1118.     return name;
  1119. }
  1120.  
  1121. /**
  1122.  * Set the console keyboard to the given keyboard language.
  1123.  *
  1124.  * @param    Keyboard language e.g.  "english-us"
  1125.  *
  1126.  * @return  The loadkeys command that has been executed to do it.
  1127.  *        (also stored in Keyboard::ckb_cmd)
  1128.  */
  1129. global define string SetConsole (string keyboard) {
  1130.  
  1131.     if (Mode::test ())
  1132.     {
  1133.     y2milestone("Test mode - NOT setting keyboard" );
  1134.     }
  1135.     else if (Arch::board_iseries () || Arch::s390())// workaround for bug #39025
  1136.     {
  1137.     y2milestone ("not calling loadkeys on iseries");
  1138.     }
  1139.     else
  1140.     {
  1141.     SetLanguage (keyboard);    // (retranslation)
  1142.  
  1143.     y2milestone("Setting console keyboard to: <%1>", current_kbd );
  1144.     y2milestone("loadkeys command: <%1>", ckb_cmd );
  1145.  
  1146.     SCR::Execute (.target.bash, ckb_cmd);
  1147.     UI::SetKeyboard ();
  1148.     }
  1149.     return ckb_cmd;
  1150. };    // SetConsole()
  1151.  
  1152.  
  1153.  
  1154. /**
  1155.  * Set the X11 keyboard to the given keyboard language.
  1156.  *
  1157.  * @param    Keyboard language e.g.  "english-us"
  1158.  *
  1159.  * @return  The xkbset command that has been executed to do it.
  1160.  *        (also stored in Keyboard::xkb_cmd)
  1161.  */
  1162. global define string SetX11 (string keyboard) {
  1163.  
  1164.     if (Mode::test ())
  1165.     {
  1166.     y2milestone ("Test mode - would have called:\n %1", xkb_cmd);
  1167.     }
  1168.     else
  1169.     {
  1170.     // Actually do it only if we are in graphical mode.
  1171.     //
  1172.     boolean textmode    = Linuxrc::text ();
  1173.     if (!Stage::initial ())
  1174.     {
  1175.         map display_info    = UI::GetDisplayInfo ();
  1176.         textmode        = display_info["TextMode"]:false;
  1177.     }
  1178.     if (textmode)
  1179.     {
  1180.         y2milestone("Not setting X keyboard due to text mode");
  1181.     }
  1182.     else if (size (xkb_cmd)>0)
  1183.     {
  1184.         SetLanguage (keyboard);    // (retranslation)
  1185.         y2milestone ("Setting X11 keyboard to: <%1>", current_kbd );
  1186.         y2milestone ("Setting X11 keyboard:\n %1", xkb_cmd );
  1187.         SCR::Execute (.target.bash, xkb_cmd);
  1188.     }
  1189.     }
  1190.     return xkb_cmd;
  1191. };    // SetX11()
  1192.  
  1193.  
  1194.  
  1195. /**
  1196.   * Set()
  1197.   *
  1198.   * Set the keyboard to the given keyboard language.
  1199.   *
  1200.   * @param   Keyboard language e.g.  "english-us"
  1201.   *
  1202.   * @return  void
  1203.   *
  1204.   * @see     SetX11(), SetConsole()
  1205.   */
  1206.  
  1207. global define void Set (string keyboard) {
  1208.  
  1209.     y2milestone ("set to %1", keyboard);
  1210.     if (Mode::config ())
  1211.     {
  1212.     current_kbd    = keyboard;
  1213.     name        = GetKeyboardName (current_kbd);
  1214.     return;
  1215.     }
  1216.  
  1217.     SetConsole (keyboard);
  1218.     SetX11 (keyboard);
  1219.     if (Stage::initial ())
  1220.     {
  1221.         map yinf = $[];
  1222.         AsciiFile::SetDelimiter( yinf, " " );
  1223.         AsciiFile::ReadFile( yinf, "/etc/yast.inf" );
  1224.         list lines = AsciiFile::FindLineField( yinf, 0, "Keytable:" );
  1225.         if( size(lines)>0 )
  1226.             AsciiFile::ChangeLineField( yinf, lines[0]:-1, 1, keymap );
  1227.         else
  1228.             AsciiFile::AppendLine( yinf, ["Keytable:", keymap] );
  1229.         AsciiFile::RewriteFile( yinf, "/etc/yast.inf" );
  1230.     }
  1231. }
  1232.  
  1233.  
  1234. /**
  1235.  * MakeProposal()
  1236.  *
  1237.  * Return proposal string and set system keyboard.
  1238.  *
  1239.  * @param    boolean force_reset
  1240.  *        boolean language_changed
  1241.  *
  1242.  * @return    string    user readable description.
  1243.  *        If force_reset is true reset the module to the keyboard
  1244.  *        stored in default_kbd.
  1245.  */
  1246.  
  1247. global define string MakeProposal (boolean force_reset,boolean language_changed)
  1248. {
  1249.     y2milestone("force_reset: %1", force_reset);
  1250.     y2milestone("language_changed: %1", language_changed);
  1251.  
  1252.     if (force_reset)
  1253.     {
  1254.     // If user wants to reset do it if a default is available.
  1255.     if (default_kbd != "")
  1256.     {
  1257.         Set (default_kbd);    // reset
  1258.     }
  1259.  
  1260.     // Reset user_decision flag.
  1261.     user_decision    = false;
  1262.     restore_called    = false;
  1263.     }
  1264.     else    // no reset
  1265.     {
  1266.     // Only follow the language if the user has never actively chosen
  1267.     // a keyboard. The indicator for this is user_decision which is
  1268.     // set from outside the module.
  1269.     if (user_decision ||
  1270.         (Mode::update () && !Stage::initial ()) ||
  1271.         Mode::autoinst () ||
  1272.         ProductFeatures::GetStringFeature ("globals", "keyboard") != "")
  1273.     {
  1274.         if (language_changed)
  1275.         {
  1276.         y2milestone("User has chosen a keyboard; not following language - only retranslation.");
  1277.  
  1278.         Set (current_kbd);
  1279.         }
  1280.     }
  1281.     else
  1282.     {
  1283.         // User has not yet chosen a keyboard ==> follow language.
  1284.         string local_kbd =
  1285.         GetKeyboardForLanguage ( Language::language, "english-us" );
  1286.         if (local_kbd != "")
  1287.         {
  1288.         Set (local_kbd);
  1289.         }
  1290.         else if (language_changed)
  1291.         {
  1292.         y2error ("Can't follow language - only retranslation");
  1293.         Set (current_kbd);
  1294.         }
  1295.     }
  1296.     }
  1297.     return name;
  1298. }    // MakeProposal()
  1299.  
  1300.  
  1301. /**
  1302.  * CalledRestore()
  1303.  *
  1304.  * Return if the kbd values have already been read from
  1305.  * /etc/sysconfig/keyboard
  1306.  *
  1307.  */
  1308. global define boolean CalledRestore() {
  1309.     return( restore_called );
  1310. };
  1311.  
  1312.     /**
  1313.      * Selection()
  1314.      *
  1315.      * Get the map of translated keyboard names.
  1316.      *
  1317.      * @return    map of $[ keyboard_code : keyboard_name, ...] for all known
  1318.      *        keyboards. 'keyboard_code' is used internally in Set and Get
  1319.      *        functions. 'keyboard_name' is a user-readable string.
  1320.      *
  1321.      */
  1322.   global define map<string, string> Selection() {
  1323.     // Get the reduced keyboard DB.
  1324.     //
  1325.     map<string, list> keyboards = get_reduced_keyboard_db();
  1326.     locale translate = "";
  1327.     string trans_str = "";
  1328.  
  1329.     return mapmap( string keyboard_code, list keyboard_value, keyboards,
  1330.         ``{
  1331.     translate = keyboard_value[0]:"";
  1332.     trans_str = (string)eval(translate);
  1333.     return  $[ keyboard_code: trans_str ];
  1334.     });
  1335.   }
  1336.  
  1337.  
  1338.  
  1339.   /**
  1340.    * SetExpertValues()
  1341.    *
  1342.    * Set the values of the various expert setting
  1343.    *
  1344.    * @param    val     map with new values of expert settings
  1345.    */
  1346.   global define void SetExpertValues( map val ) {
  1347.  
  1348.     map orig_values    = GetExpertValues ();
  1349.  
  1350.     if( haskey(val,"rate") && size(val["rate"]:"")>0 )
  1351.     {
  1352.     kbd_rate = val["rate"]:"";
  1353.     }
  1354.     if( haskey(val,"delay") && size(val["delay"]:"")>0 )
  1355.     {
  1356.     kbd_delay = val["delay"]:"";
  1357.     }
  1358.     if( haskey(val,"numlock") )
  1359.     {
  1360.     kbd_numlock = val["numlock"]:"";
  1361.     }
  1362.     if( haskey(val,"capslock") )
  1363.     {
  1364.     kbd_capslock = (val["capslock"]:false) ? "yes" : "no";
  1365.     }
  1366.     if( haskey(val,"scrlock") )
  1367.     {
  1368.     kbd_scrlock = (val["scrlock"]:false) ? "yes" : "no";
  1369.     }
  1370.     if( haskey(val,"tty") && size(val["tty"]:"")>0 )
  1371.     {
  1372.     kbd_tty = val["tty"]:"";
  1373.     }
  1374.     if( haskey(val,"discaps") )
  1375.     {
  1376.     kbd_disable_capslock = (val["discaps"]:false) ? "yes" : "no";
  1377.     }
  1378.  
  1379.     if (!ExpertSettingsChanged && orig_values != GetExpertValues ())
  1380.     ExpertSettingsChanged = true;
  1381.   }
  1382.  
  1383.   // set the keayboard layout according to given language
  1384.   global define void SetKeyboardForLanguage (string lang) {
  1385.  
  1386.     string lkbd = GetKeyboardForLanguage (lang, "english-us");
  1387.     y2milestone ("language %1 proposed keyboard %2", lang, lkbd);
  1388.     if (lkbd != "")
  1389.     {
  1390.     Set( lkbd );
  1391.     }
  1392.   };
  1393.  
  1394.   global define void SetKeyboardForLang (string lang) {
  1395.     return SetKeyboardForLanguage (lang);
  1396.   }
  1397.  
  1398.   global define void SetKeyboardDefault() {
  1399.  
  1400.     y2milestone( "SetKeyboardDefault to %1", current_kbd );
  1401.     default_kbd = current_kbd;
  1402.   };
  1403.  
  1404.  
  1405.   /**
  1406.    * Special function for update mode only.
  1407.    * Checks for the keyboard layout on the system which should be updated and if it
  1408.    * differs from current one, opens a popup with the offer to change the layout.
  1409.    * See discussion in bug #71069
  1410.    * @param destdir path to the mounted system to update (e.g. "/mnt")
  1411.    */
  1412.   global define void CheckKeyboardDuringUpdate (string destdir) {
  1413.  
  1414.     string target_kbd    = Misc::CustomSysconfigRead (
  1415.     "YAST_KEYBOARD", current_kbd, destdir + "/etc/sysconfig/keyboard");
  1416.     integer pos = find (target_kbd, ",");
  1417.     if (pos != nil && pos > 0)
  1418.     {
  1419.     target_kbd    = substring (target_kbd, 0, pos);
  1420.     }
  1421.  
  1422.     map keyboards = get_reduced_keyboard_db();
  1423.  
  1424.     if (target_kbd != current_kbd && keyboards[target_kbd]:[] != [])
  1425.     {
  1426.     y2milestone ("current_kbd: %1, target_kbd: %2", current_kbd, target_kbd);
  1427.  
  1428.     string target_name = GetKeyboardName (target_kbd);
  1429.  
  1430.     UI::OpenDialog(`opt(`decorated), `HBox(`HSpacing(1.5),
  1431.         `VBox(
  1432.         `HSpacing(40),
  1433.         `VSpacing(0.5),
  1434.         // label text: user can choose the keyboard from the updated system
  1435.         // or continue with the one defined by his language.
  1436.         // 2 radio-buttons follow this label.
  1437.         // Such keyboard layout is used only for the time of the update,
  1438.         // it is not saved to the system.
  1439.         `Left (`Label (_("You are currently using a keyboard layout
  1440. different from the one in the system to update.
  1441. Select the layout to use during update:"))),
  1442.         `VSpacing(0.5),
  1443.         `RadioButtonGroup (`VBox (
  1444.             `Left (`RadioButton (`id (`current), name)),
  1445.             `Left (`RadioButton (`id (`target), target_name, true))
  1446.         )),
  1447.         `VSpacing(0.5),
  1448.         `HBox(
  1449.             `PushButton(`id(`ok),`opt(`default,`key_F10), Label::OKButton()),
  1450.             `PushButton(`id(`cancel), `opt(`key_F9), Label::CancelButton())
  1451.         ),
  1452.         `VSpacing(0.5)),
  1453.         `HSpacing(1.5)
  1454.     ));
  1455.     any ret = UI::UserInput();
  1456.  
  1457.     if (ret == `ok && (boolean) UI::QueryWidget (`id(`target), `Value))
  1458.     {
  1459.         Set (target_kbd);
  1460.         user_decision    = true;
  1461.     }
  1462.  
  1463.         UI::CloseDialog();
  1464.     }
  1465.   }
  1466.  
  1467.   /**
  1468.    * AutoYaST interface function: Get the Keyboard configuration from a map.
  1469.    * @param settings imported map
  1470.    * @return success
  1471.    */
  1472.   global define boolean Import (map settings) {
  1473.  
  1474.     // Read was not called -> do the init
  1475.     if (expert_on_entry == $[])
  1476.     Read ();
  1477.  
  1478.     Set (settings["keymap"]:current_kbd);
  1479.     SetExpertValues (settings["keyboard_values"]:$[]);
  1480.     return true;
  1481.   }
  1482.  
  1483.   /**
  1484.    * AutoYaST interface function: Return the Keyboard configuration as a map.
  1485.    * @return map with the settings
  1486.    */
  1487.   global define map Export () {
  1488.  
  1489.     map diff_values    = $[];
  1490.     foreach (string key, any val, (map<string,any>) GetExpertValues (), {
  1491.     if (expert_on_entry[key]:nil != val)
  1492.         diff_values[key]    = val;
  1493.     });
  1494.     map ret = $[
  1495.     "keymap"        : current_kbd,
  1496.     ];
  1497.     if (diff_values != $[])
  1498.     ret["keyboard_values"]    = diff_values;
  1499.     return ret;
  1500.   }
  1501.  
  1502.   /**
  1503.    * AutoYaST interface function: Return the summary of Keyboard configuration as a map.
  1504.    * @return summary string (html)
  1505.    */
  1506.   global define string Summary () {
  1507.  
  1508.     import "HTML";
  1509.  
  1510.     list<string> ret =  [
  1511.     // summary label
  1512.     sformat (_("Current Keyboard Layout: %1"), name)
  1513.     ];
  1514.     return HTML::List (ret);
  1515.   }
  1516.  
  1517.  
  1518. } // - EOF -
  1519.