home *** CD-ROM | disk | FTP | other *** search
/ Chip 2000 May / Chip_2000-05_cd2.bin / suse / inst-sys / lib / YaST2 / clients / printconf.ycp < prev    next >
Encoding:
Text File  |  2000-03-30  |  18.1 KB  |  539 lines

  1. /* The Printer Configurator
  2.  * Jan Holesovsky <kendy@suse.cz>, 2000
  3.  *
  4.  * $Id: printconf.ycp,v 1.28.4.2 2000/03/23 16:22:10 gs Exp $
  5.  */
  6.  
  7. {
  8.   // Menuentry for the YaST2 menu
  9.   if (Args() == [ "get_menuentry" ]) 
  10.     return [ 
  11.       "printconf", $[
  12.     `menuentry    : UI(_("Hardware/Printer")),
  13.     `arguments    : [ ],
  14.     `widget       : `RichText(
  15.           UI(_("<P>Launch this module to configure your printer. Please, turn
  16. the printer on, YaST2 will try to autodetect it.</P>
  17. <P>You need to be logged in as <i>root</i> in order to
  18. do this.</P>"))),
  19.     `codefragment : nil ]
  20.     ];
  21.   
  22.  
  23.   UI(``{
  24.     // Debug dialog
  25.     define DebugDialog(string str) ``{
  26.       OpenDialog(//`opt(`decorated),
  27.         `VBox(`RichText(str),
  28.           `PushButton(_("&OK"))));
  29.       any r = UserInput();
  30.       CloseDialog();
  31.     };
  32.  
  33.     // The main dialog. Copied from installation.ycp.
  34.     OpenDialog(`opt(`defaultsize),
  35.            `VBox(`Image(`suseheader, "SuSE"),
  36.              `HBox(`HWeight(30, `RichText(`id(`help), "")),
  37.                `HWeight(70, `VBox(
  38.                   `Left(`Heading(`id(`title), _("YaST2 Printconf\n
  39. Initializing ...
  40. "))),
  41.                   `HVCenter(`ReplacePoint(`id(`contents), `Empty())),
  42.                 `HBox(
  43.                   // back pushbutton: the user input is ignored and the last dialog is called
  44.                   `PushButton(`id(`back), `opt(`disabled), _("&Back")),
  45.                   `HStretch(),
  46.                   // next pushbutton: the user input is checked and the next dialog is called
  47.                   `PushButton(`id(`next), `opt(`disabled), _("&Next"))))))));
  48.  
  49.     // Create content of the dialog. See installation.ycp.
  50.     define SetPrintconfContents(string title, term contents, string helptext,
  51.     boolean back_is_return, string next_label) ``{
  52.       /*if (back_is_return)
  53.           // "Return" is on the first screen of the installation.
  54.           // It means that the printconf will be left without changes.
  55.       ChangeWidget(`id(`back), `Label, _("&Return"));
  56.         else
  57.       ChangeWidget(`id(`back), `Label, _("&Back"));*/
  58.  
  59.       ChangeWidget(`id(`next), `Label, next_label);
  60.       ChangeWidget(`id(`back), `Enabled, true);
  61.       ChangeWidget(`id(`next), `Enabled, true);
  62.  
  63.       ChangeWidget(`id(`help), `Value, helptext);
  64.       ChangeWidget(`id(`title), `Value, title);
  65.       ReplaceWidget(`id(`contents), contents);
  66.     };
  67.  
  68.     /*
  69.      * Displays a message to the user in a small dialog with an OK
  70.      * button.
  71.      */
  72.  
  73.     define DisplayMessage(string message) ``{
  74.       // ok pushbutton: confirm the dialog
  75.       OpenDialog(`opt(`decorated), `VBox(`Label(message),
  76.                              `PushButton(_("&OK"))));
  77.       UserInput();
  78.       CloseDialog();
  79.     };
  80.  
  81.  
  82.     // Define dialog to let the user choose the connection type.
  83.     define SelectConnection(map dial_noncommon, map known, boolean is_first) ``{
  84.       list connection_val = [];
  85.       foreach(`type, `info, dial_noncommon, ``{
  86.         connection_val = add(connection_val, `item(`id(type), lookup(info, "name")));
  87.       });
  88.       term connection_sel = `SelectionBox(`id(`connectionsel),
  89.         // Do not do the translation longer than this text.
  90.     // It is a label of a selection box.
  91.         _("Select the printer type you want to add:"), connection_val);
  92.       
  93.       list alreadyconf_val = [];
  94.       foreach(`key, `pr, known, ``{
  95.     if (pr != nil) {
  96.       boolean|void to_add = lookup(pr, "add");
  97.       if ((to_add != nil) && to_add) {
  98.         list names = lookup(pr, "names");
  99.         string pr_con = lookup(pr, "connection");
  100.         string con_name = lookup(lookup(dial_noncommon, pr_con), "name");
  101.         string name = "";
  102.         
  103.             foreach(`n, names, ``{
  104.           if (size(name) > 0)
  105.             name = name+", ";
  106.           name = name+n;
  107.         });
  108.         alreadyconf_val = add(alreadyconf_val,
  109.           sformat(_("%1 (%2)"), name, con_name));
  110.       }
  111.     }
  112.       });
  113.  
  114. // Help, 1 of 3
  115.       string help_text = _("<P>In this dialog, you can manually add printers to your spooling system.
  116. Use this in case, when your printer was not found by YaST2.</P>
  117. ");
  118. // Help, 2 of 3
  119.       help_text = help_text + _("<P>The left column contains printers that will be added to
  120. your system after pressing the <B>Finish</B> button.</P>
  121. ");
  122. // Help, 3 of 3
  123.       help_text = help_text + _("<P>In the right column you can choose the type of the printer you have.
  124. When you push the <B>Add</B> button, the procedure to add a printer will start.</P>
  125. ");
  126.       
  127.       term contents = 
  128.         `HBox(`SelectionBox(`id(`alreadyconf), `opt(`disable),
  129.                         // Do not do the translation longer than this text.
  130.                             _("Configured printers:"), alreadyconf_val),
  131.           `VBox(connection_sel, `Right(`PushButton(`id(`new_one), _("&Add"))))
  132.     );
  133.       return SetPrintconfContents(_("Choose the printer you have"),
  134.         contents, help_text,
  135.     is_first, _("&Finish")); // TODO: help text.
  136.     
  137.     };
  138.     
  139.   });
  140.  
  141.   /* Chooses one message according to the language */
  142.   define Trans(map|void msgs, string lang) ``{
  143.     string|void message = "";
  144.     if (msgs != nil) {
  145.       message = lookup(msgs, lang);
  146.       if (message == nil)
  147.         message = lookup(msgs, substring(lang, 0, 2));
  148.       if (message == nil)
  149.         message = lookup(msgs, "default");
  150.       if (message == nil)
  151.         message = "";             // Everything has failed.
  152.     }
  153.     return message;
  154.   };
  155.   
  156.   /* Reads and localises the printer database */
  157.   define ReadLocalizedDatabase(string filename) ``{
  158.     list|void dbase = ReadY2(filename);
  159.     if (dbase == nil) {
  160.       UI(`DisplayMessage(_("FATAL: I am unable to find the printer database!")));
  161.       return nil;
  162.     }
  163.     string language = UI(`GetLanguage());
  164.     
  165.     return maplist(`manuf, dbase, ``{
  166.       list|void printers = lookup(manuf, "printers");
  167.       if (printers != nil) {
  168.         manuf = add(manuf, "printers", maplist(`pr, printers, ``{
  169.       map|void ps2printer = lookup(pr, "ps2printer");
  170.       if (ps2printer != nil) {
  171.             list|void options = lookup(ps2printer, "options");
  172.         if (options != nil) {
  173.           ps2printer = add(ps2printer, "options", maplist(`opt, options, ``{
  174.             map|void values = lookup(opt, "values");
  175.             if (values != nil) {
  176.               map val = $[];
  177.           foreach(`k, `v, values, ``{
  178.             val = add(val, k, Trans(v, language));
  179.           });
  180.           opt = add(opt, "values", val);                         // tr. values
  181.             }
  182.             return add(opt, "name", Trans(lookup(opt, "name"), language));// tr. opts
  183.           }));
  184.         }
  185.         pr = add(pr, "ps2printer", ps2printer);
  186.       }
  187.       return add(pr, "name", Trans(lookup(pr, "name"), language));   // tr. printers
  188.     }));
  189.       }
  190.       return add(manuf, "name", Trans(lookup(manuf, "name"), language)); // tr. manufact
  191.     });
  192.   };
  193.   
  194.   /* Returns manufacturer according to 1284 id */
  195.   define FindManufacturer1284(list database, string id) ``{
  196.     id = tolower(id);
  197.     list man = filter(`mnf, database, ``{
  198.       string|void mf = lookup(mnf, "1284id");
  199.       return (mf != nil && mf != "" && substring(id, 0, size(mf)) == tolower(mf));
  200.     });
  201.     if (size(man) == 0)
  202.       return nil;
  203.     else
  204.       return select(man, 0);
  205.   };
  206.   
  207.   /* Returns printer according to 1284 id */
  208.   define FindPrinter1284(map manufacturer, string id) ``{
  209.     id = tolower(id);
  210.     list prntrs = lookup(manufacturer, "printers");
  211.     list pr = filter(`prns, prntrs, ``{
  212.       string|void p = lookup(prns, "1284id");
  213.       return (p != nil && p != "" && substring(id, 0, size(p)) == tolower(p));
  214.     });
  215.     if (size(pr) == 0)
  216.       return nil;
  217.     else
  218.       return select(pr, 0);
  219.   };
  220.  
  221.   /* Move printer records from list "to_add" to indexed map "known" */
  222.   define AddPrinters(map known, list to_add) ``{
  223.     integer idx = size(known);
  224.     foreach(`prn, to_add, ``{
  225.         known = add(known, idx, prn);
  226.     idx = idx+1;
  227.       });
  228.     return known;
  229.   };
  230.  
  231.   /* Autoprobes parallel printers.
  232.      Returns a list of autoprobe records */
  233.   define AutoprobeDevice(list pr_database) ``{
  234.     Shell("/sbin/rmmod parport_probe");
  235.     Shell("/sbin/modprobe parport_probe"); // Must be restarted!
  236.     
  237.     list|void aprobe = SCR(`Read(.probe.byclass.printer));
  238.     if (aprobe == nil) {
  239.       UI(`DisplayMessage(_("I tried to autoprobe parallel and USB printers,\n
  240. but I haven't found any on your computer.
  241. ")));
  242.       return [];
  243.     }
  244.     
  245.     return maplist(`pr, aprobe, ``{
  246.       map record = $[];
  247.       string bus = lookup(pr, "bus");
  248.       string|void man1284 = nil;
  249.       string|void mod1284 = nil;
  250.       if (bus == "Parallel") {
  251.     record = $[
  252.       "autodetected" : true,       // This record was found by printconf
  253.       "connection" : "parallel",   // on parallel device
  254.       "parallel": $[ "device": lookup(pr, "dev_name") ] // device <dev>
  255.     ];
  256.     man1284 = lookup(pr, "vendor");
  257.     mod1284 = lookup(pr, "device");
  258.       }
  259.       if (bus == "USB") {
  260.     record = $[
  261.       "autodetected" : true,       // This record was found by printconf
  262.       "connection" : "usb",        // on usb device
  263.       "usb": $[ "device": lookup(pr, "dev_name") ] // device <dev>
  264.     ];
  265.     man1284 = lookup(pr, "sub_vendor");
  266.     mod1284 = lookup(pr, "sub_device");
  267.       }
  268.  
  269.       if (man1284 != nil) {
  270.         map|void manuf = FindManufacturer1284(pr_database, man1284);
  271.         if (manuf != nil) {
  272.           record = add(record, "manufacturer", lookup(manuf, "name"));
  273.           if (mod1284 != nil) {
  274.             map|void model = FindPrinter1284(manuf, mod1284);
  275.             if (model != nil) {
  276.               record = add(add(record, "model", lookup(model, "name")),
  277.                                          "ps2printer", lookup(model, "ps2printer"));
  278.             }
  279.           }
  280.         }
  281.       }
  282.       return record;
  283.     });
  284.   };
  285.  
  286.   /* Tries to find the highest lp number */
  287.   define GetHighestLpNumber(list printcap) ``{
  288.     integer high = 0;
  289.     foreach(`rec, printcap, ``{
  290.       list|void names = lookup(rec, "names");
  291.       if (names != nil)
  292.         foreach(`nam, names, ``{
  293.       if (substring(nam, 0, 2) == "lp") {
  294.         string num = substring(nam, 2, size(nam)-2);
  295.         if (num != "" && findfirstnotof(num, "0123456789") == nil) {
  296.           integer in = tointeger(num);
  297.           if (in > high)
  298.             high = in;
  299.         }
  300.       }
  301.     });
  302.     });
  303.     return high;
  304.   };
  305.  
  306.   /* Get a list of already used names. For a single list. */
  307.   define GetForbiddenNames(list printconf) ``{
  308.     list forb = maplist(`rec, printconf, ``lookup(rec, "names"));
  309.     forb = filter(`nam, forb, ``(nam != nil));
  310.     return flatten(forb);
  311.   };
  312.   
  313.   /* Get a list of already used names. For a single list. */
  314.   define GetForbiddenNames(integer current, map known_printers) ``{
  315.     list forb = maplist(`idx, `pr, known_printers, ``{
  316.       if (idx != current)
  317.         return lookup(pr, "names");
  318.       else
  319.         return nil;
  320.     });
  321.     forb = filter(`nam, forb, ``(nam != nil));
  322.     return flatten(forb);
  323.   };
  324.  
  325.   /* Show dialogs for some type of connection
  326.    * first: Am I the first dialog? */
  327.   define ShowDialogs(map printer, map dialogs, boolean first, boolean reverse) ``{
  328.     integer max = size(dialogs);
  329.     boolean|void add_it = lookup(printer, "add");
  330.     integer index = 0;
  331.     if (reverse && (add_it != false)) index = max-1;
  332.     
  333.     boolean reverse_call = reverse;
  334.     while ((index >= 0) && (index < max)) {
  335.       term dlg = lookup(dialogs, index);
  336.         
  337.       dlg = add(dlg, printer);                          // Add parameters.
  338.       dlg = add(dlg, (index == 0) && first);
  339.       dlg = add(dlg, reverse_call);
  340.       
  341.       map|void ret = CallFunction(dlg);
  342.       
  343.       if (ret != nil) {
  344.         printer = ret;
  345.         boolean|void add_it = lookup(printer, "add");
  346.         if (add_it == false) break;
  347.         index = index+1;
  348.     reverse_call = false;
  349.       } else {
  350.         index = index-1;
  351.     reverse_call = true;
  352.       }
  353.     }
  354.     
  355.     if (index < 0) return nil;
  356.     return printer;
  357.   };
  358.  
  359.   /* Initialization */
  360.   list|void printer_database = ReadLocalizedDatabase("printers.ycp");
  361.   if (printer_database == nil) {
  362.     UI(`CloseDialog());
  363.     return;
  364.   }
  365.  
  366.   Shell("/sbin/modprobe lp");
  367.   Shell("/sbin/lsmod | grep usbcore || /sbin/init.d/usb start");
  368.   Shell("/sbin/lsmod | grep printer || /sbin/modprobe printer");
  369.  
  370.   integer lpdaemon = Shell("/sbin/init.d/lpd restart");
  371.   if (lpdaemon != 0) {
  372.     UI(`DisplayMessage(_("FATAL: I am unable to restart the lpd daemon!\n
  373. Maybe, you haven't installed lpd (one of\n
  374. the lprold, plp or lprng packages) or\n
  375. you are not the user 'root'.
  376. ")));
  377.     UI(`CloseDialog());
  378.     return;
  379.   }
  380.   
  381.   if (Shell("which gs") != 0)
  382.     UI(`DisplayMessage(_("It seems that you don't have GhostScript\n
  383. installed on your computer. It is necessary \n
  384. in order to print.
  385. ")));
  386.  
  387.   boolean y2_save = false;
  388.   integer y2_save_call =
  389.     Shell("grep apsfilter /etc/printcap || ( mv /etc/printcap /etc/printcap.YaST2save && exit 1)");
  390.   if (y2_save_call == 1)
  391.     y2_save = true;
  392.  
  393.   list|void printcap = SCR(`Read(.etc.printcap));
  394.   /* apsfilter.setup generates lp? names. This is the highest one. */
  395.   integer highest_lp_no = 0;
  396.   list printcap_forb_names = [];
  397.   if (printcap != nil) {
  398.     highest_lp_no = GetHighestLpNumber(printcap);
  399.     printcap_forb_names = GetForbiddenNames(printcap);
  400.   }
  401.   
  402.   map dial_noncommon = $[
  403.     "parallel": $[ "name" :         _("Parallel printer"),
  404.                    "default" :      `printconf_ask_device("parallel"),
  405.            "autodetected" : `printconf_device_confirm() ],
  406.     "usb": $[      "name" :         _("USB printer"),
  407.                    "default" :      `printconf_ask_device("usb"),
  408.                "autodetected" : `printconf_device_confirm() ]
  409.   ];
  410.   
  411.   map known_printers = $[];
  412.     /* The records should be:
  413.          <num>:$[ "autodetected":true/false, -- added by user or by printconf?
  414.                   "add":true/false,          -- add this to the spooling system?
  415.                   "manufacturer":<man>, "model":<mod>,
  416.           "names": [ <name1>, <name2>, ...],
  417.                   "connection":<con>, <con>:$[<connection related>]]
  418.        The unknown information should not be filled in. The user will be asked.*/
  419.   
  420.   known_printers = AddPrinters(known_printers, AutoprobeDevice(printer_database));
  421.   /* TODO: more detection here (NCP, Samba, ...)*/
  422.  
  423.   integer index = 0;
  424.   boolean reverse = false;
  425.   /* Go through the known_printers map and ask for missing information. */
  426.   do {
  427.     any ret_value = nil;
  428.     map|void printer = lookup(known_printers, index);
  429.     
  430.     if (printer == nil) {                             // The user must be asked...
  431.       any dlg = UI(`SelectConnection(dial_noncommon, known_printers, index <= 0));
  432.       string|void new_conn = nil;                     // User wants to add this type.
  433.       do {
  434.         ret_value = UI(`UserInput());
  435.     new_conn = UI(`QueryWidget(`id(`connectionsel), `CurrentItem));
  436.     if ((ret_value == `new_one) && (new_conn == nil))
  437.       UI(`DisplayMessage(_("Please select the type of printer you want to add.")));
  438.       } while ((ret_value == `new_one) && (new_conn == nil));
  439.  
  440.       if (ret_value == `new_one)                      // The user wants one more printer!
  441.         known_printers = add(known_printers, index,   // Add empty one!
  442.         $[ "autodetected":false, "add":true, "connection":new_conn ]);
  443.       else 
  444.     if (ret_value == `back) index = index-1;
  445.       reverse = (ret_value == `back);
  446.     } else {                                          // printer != nil, configure it.
  447.       string type = lookup(printer, "connection");
  448.       boolean|void autodet = lookup(printer, "autodetected");
  449.       
  450.       map|void configured = nil;
  451.       term|void non_common = nil;
  452.       if (autodet == true)
  453.         non_common = lookup(lookup(dial_noncommon, type), "autodetected");
  454.       else
  455.         non_common = lookup(lookup(dial_noncommon, type), "default");
  456.       
  457.       list forbidden_names = union(printcap_forb_names,
  458.                                    GetForbiddenNames(index, known_printers));
  459.       
  460.       if (non_common != nil) {
  461.         map dialogs = $[           // Dialogs for configuring...
  462.           1: `printconf_manuf_model(printer_database),
  463.           2: `printconf_spool_info(forbidden_names),
  464.           3: `printconf_filter()
  465.         ];
  466.         dialogs = add(dialogs, 0, non_common);
  467.     
  468.     configured = 
  469.       ShowDialogs(printer, dialogs, (index == 0) && (autodet == true), reverse);
  470.       } else
  471.         UI(`DisplayMessage(
  472.           sformat("I am sorry, module for configuring %1 printers is not implemented yet.", type)));
  473.  
  474.       if (configured == nil) {
  475.         boolean|void auto = lookup(printer, "autodetected");
  476.         if (auto != true)                             // If the printer was added by user
  477.           known_printers = add(known_printers, index, nil); // remove it,
  478.         else
  479.           index = index-1;                            // else go back.
  480.       } else {
  481.         known_printers = add(known_printers, index, configured); // New configuration
  482.         index = index+1;
  483.       }
  484.       reverse = (configured == nil);
  485.     }
  486.   } while ((ret_value != `next) && (index >= 0));
  487.   
  488.   if (index < 0) {
  489.     UI(`DisplayMessage(_("There were no changes in \n
  490. the configuration of printers.
  491. ")));
  492.     if (y2_save == true)
  493.       Shell("mv /etc/printcap.YaST2save /etc/printcap");
  494.   } else {
  495.     integer i = 0;
  496.     boolean something_added = false;
  497.     while (i < size(known_printers)) {
  498.       map|void printer = lookup(known_printers, i);
  499.       if ((printer != nil) && (lookup(printer, "add") == true)) {
  500.         something_added = true;
  501.         if (lookup(printer, "connection") == "usb") {
  502.       Shell("cd /etc/rc.config.d/ ; \
  503.              . usb.rc.config ; \
  504.              echo $USB_DRIVERS | \
  505.            grep printer || \
  506.              ( sed 's/^USB_DRIVERS=/#USB_DRIVERS=/' < usb.rc.config \
  507.                                                     > usb.rc.config.new ; \
  508.                echo \"USB_DRIVERS=\\\"$USB_DRIVERS printer\\\"\" >> usb.rc.config.new ; \
  509.                mv usb.rc.config.new usb.rc.config )");
  510.       Shell("cat /etc/rc.config | \
  511.              sed 's/START_USB=\"[^\"]*\"/START_USB=\"yes\"/' > /etc/rc.config.new ; \
  512.          mv /etc/rc.config.new /etc/rc.config");
  513.       Shell("SuSEconfig -quick --nonewpackage");
  514.     }
  515.     
  516.     /* TODO: Do better dialogs! */
  517.         if (CallFunction(`printconf_write_printer(printer, "add")))
  518.       // %1 - name of the printer
  519.           UI(`DisplayMessage(sformat(UI(_("Printer '%1' was\n
  520. successfully configured.
  521. ")),
  522.         select(lookup(printer, "names"), 0))));
  523.     else
  524.       // %1 - name of the printer
  525.           UI(`DisplayMessage(sformat(UI(_("I was unable to configure\n
  526. printer '%1'.
  527.  
  528. ")),
  529.         select(lookup(printer, "names"), 0))));
  530.       }
  531.       i = i+1;
  532.     }
  533.     if (y2_save == true && !something_added)
  534.       Shell("mv /etc/printcap.YaST2save /etc/printcap");
  535.   }
  536.   UI(`CloseDialog());
  537.  
  538. }
  539.