]> git.lyx.org Git - features.git/blobdiff - src/frontends/xforms/FormDocument.C
The 'Branches' mega-patch.
[features.git] / src / frontends / xforms / FormDocument.C
index d55286f6f805376617bc199b9845bc7843ef17e8..1f3d0a4fb3bc3b7f4051541aacf2f7a825095564 100644 (file)
@@ -5,48 +5,61 @@
  *
  * \author Jürgen Vigna
  * \author Rob Lahaye
+ * \author Martin Vermeer
+ * \author Juergen Spitzmueller
  *
  * Full author contact details are available in file CREDITS
  */
 
 #include <config.h>
 
-
 #include "ControlDocument.h"
 #include "FormDocument.h"
 #include "forms/form_document.h"
 #include "xformsBC.h"
 #include "ButtonController.h"
 
+#include "FormColorpicker.h"
+#include "LColor.h"
+#include "Lsstream.h"
 #include "bmtable.h"
 #include "checkedwidgets.h"
+#include "Tooltips.h"
 #include "input_validators.h" // fl_unsigned_float_filter
 #include "xforms_helpers.h"
 
+#include "bufferparams.h"
 #include "CutAndPaste.h"
 #include "debug.h"
 #include "language.h"
 #include "lyxrc.h"
 #include "lyxtextclasslist.h"
 #include "tex-strings.h"
+#include "ColorHandler.h"
 
 #include "controllers/frnt_lang.h"
 #include "controllers/helper_funcs.h"
 
+#include "support/tostr.h"
 #include "support/lstrings.h" // contains_functor, getStringFromVector
 #include "support/filetools.h" // LibFileSearch
-#include "support/BoostFormat.h"
 
-#include XPM_H_LOCATION
-#include FORMS_H_LOCATION
+#include "lyx_xpm.h"
+#include "lyx_forms.h"
 #include "combox.h"
 
 #include <boost/bind.hpp>
 
 #include <functional>
+#include <iomanip>
+
+using namespace lyx::support;
 
 using std::bind2nd;
 using std::vector;
+using std::endl;
+using std::setw;
+using std::setfill;
 
 
 namespace {
@@ -57,6 +70,7 @@ bool const scalableTabfolders = false;
 bool const scalableTabfolders = true;
 #endif
 
+
 } // namespace anon
 
 
@@ -139,19 +153,14 @@ void FormDocument::build()
                if (tit->isTeXClassAvailable()) {
                        fl_addto_combox(obj, tit->description().c_str());
                } else {
-                       string item =
-#if USE_BOOST_FORMAT
-                               boost::io::str(boost::format(_("Unavailable: %1$s")) % tit->description());
-#else
-                               _("Unavailable: ") + tit->description();
-#endif
+                       string item = bformat(_("Unavailable: %1$s"), tit->description());
                        fl_addto_combox(obj, item.c_str());
                }
        }
        fl_set_combox_browser_height(obj, 400);
 
        fl_addto_choice(class_->choice_spacing,
-                       _(" Single | OneHalf | Double | Custom "));
+                       _(" Single | OneHalf | Double | Custom ").c_str());
        fl_addto_choice(class_->choice_fontsize, "default|10|11|12");
        for (int n = 0; tex_fonts[n][0]; ++n) {
                fl_addto_choice(class_->choice_fonts,tex_fonts[n]);
@@ -171,7 +180,7 @@ void FormDocument::build()
        fl_addto_choice(class_->choice_pagestyle,
                        "default|empty|plain|headings|fancy");
        fl_addto_choice(class_->choice_skip,
-                       _(" SmallSkip | MedSkip | BigSkip | Length "));
+                       _(" SmallSkip | MedSkip | BigSkip | Length ").c_str());
        fl_addto_choice(class_->choice_skip_units,  units.c_str());
 
        // Set input filters on doc spacing to make it accept only
@@ -236,12 +245,13 @@ void FormDocument::build()
 
        fl_addto_choice(paper_->choice_papersize,
                        _(" Default | Custom | US letter | US legal "
-                         "| US executive | A3 | A4 | A5 | B3 | B4 | B5 "));
+                         "| US executive | A3 | A4 | A5 "
+                         "| B3 | B4 | B5 ").c_str());
        fl_addto_choice(paper_->choice_paperpackage,
                        _(" None "
                          "| Small Margins "
                          "| Very small Margins "
-                         "| Very wide Margins "));
+                         "| Very wide Margins ").c_str());
 
        fl_addto_choice(paper_->choice_custom_width_units,  units.c_str());
        fl_addto_choice(paper_->choice_custom_height_units, units.c_str());
@@ -281,7 +291,7 @@ void FormDocument::build()
 
        fl_addto_choice(language_->choice_quotes_language,
                        _(" ``text'' | ''text'' | ,,text`` | ,,text'' |"
-                         " «text» | »text« "));
+                         " «text» | »text« ").c_str());
 
        // the document options form
        options_.reset(build_document_options(this));
@@ -301,14 +311,14 @@ void FormDocument::build()
        fl_set_input_return(options_->input_float_placement, FL_RETURN_CHANGED);
 
        fl_addto_choice(options_->choice_ams_math,
-                       _("Never | Automatically | Yes "));
+                       _("Never | Automatically | Yes ").c_str());
 
        for (int n = 0; tex_graphics[n][0]; ++n) {
                fl_addto_choice(options_->choice_postscript_driver,
                                tex_graphics[n]);
        }
        fl_addto_choice(options_->choice_citation_format,
-                       _(" Author-year | Numerical "));
+                       _(" Author-year | Numerical ").c_str());
 
        // the document bullets form
        bullets_.reset(build_document_bullet(this));
@@ -334,8 +344,9 @@ void FormDocument::build()
        fl_set_input_return(bullets_->input_latex, FL_RETURN_CHANGED);
 
        fl_addto_choice(bullets_->choice_size,
-                       _(" Default | Tiny | Smallest | Smaller | Small |"
-                         " Normal | Large | Larger | Largest | Huge | Huger "));
+                       _(" Default | Tiny | Smallest | Smaller "
+                         "| Small | Normal | Large | Larger | Largest "
+                         "| Huge | Huger ").c_str());
        fl_set_choice(bullets_->choice_size, 1);
 
        fl_set_input_maxchars(bullets_->input_latex, 80);
@@ -344,20 +355,60 @@ void FormDocument::build()
        fl_set_bmtable_pixmap_file(bullets_->bmtable_panel, 6, 6,
                                   bmtablefile.c_str());
 
+       picker_.reset(new FormColorpicker);
+       
+       // the document branches form
+       branch_.reset(build_document_branch(this));
+
+       fl_set_object_color(branch_->button_color,
+               GUI_COLOR_CHOICE, GUI_COLOR_CHOICE);
+       
+       bcview().addReadOnly(branch_->input_all_branches);
+       bcview().addReadOnly(branch_->button_add_branch);
+       bcview().addReadOnly(branch_->button_remove_branch);
+       bcview().addReadOnly(branch_->button_select);
+       bcview().addReadOnly(branch_->button_deselect);
+       bcview().addReadOnly(branch_->button_modify);
+       bcview().addReadOnly(branch_->browser_all_branches);
+
+       // set up the tooltips for branches form
+       string str = _("Enter the name of a new branch.");
+       tooltips().init(branch_->input_all_branches, str);
+       str = _("Add a new branch to the document.");
+       tooltips().init(branch_->button_add_branch, str);
+       str = _("Remove the selected branch from the document.");
+       tooltips().init(branch_->button_remove_branch, str);
+       str = _("Activate the selected branch for output.");
+       tooltips().init(branch_->button_select, str);
+       str = _("Deactivate the selected activated branch.");
+       tooltips().init(branch_->button_deselect, str);
+       str = _("Available branches for this document.");
+       tooltips().init(branch_->browser_all_branches, str);
+       str = _("Activated branches. Content will occur in the document\'s output");
+       tooltips().init(branch_->browser_selection, str);
+       str = _("Modify background color of branch inset");
+       tooltips().init(branch_->button_modify, str);
+       str = _("Background color of branch inset");
+       tooltips().init(branch_->button_color, str);
+
+       // Handle middle mouse paint:
+       setPrehandler(branch_->input_all_branches);
+       fl_set_input_return(branch_->input_all_branches, FL_RETURN_CHANGED);
+
        // Enable the tabfolder to be rescaled correctly.
        if (scalableTabfolders)
                fl_set_tabfolder_autofit(dialog_->tabfolder, FL_FIT);
 
        // Stack tabs
-       fl_addto_tabfolder(dialog_->tabfolder,_("Document"),
+       fl_addto_tabfolder(dialog_->tabfolder,_("Document").c_str(),
                           class_->form);
-       fl_addto_tabfolder(dialog_->tabfolder,_("Paper"),
+       fl_addto_tabfolder(dialog_->tabfolder,_("Paper").c_str(),
                           paper_->form);
-       fl_addto_tabfolder(dialog_->tabfolder,_("Language"),
+       fl_addto_tabfolder(dialog_->tabfolder,_("Language").c_str(),
                           language_->form);
-       fl_addto_tabfolder(dialog_->tabfolder,_("Extra"),
+       fl_addto_tabfolder(dialog_->tabfolder,_("Extra").c_str(),
                           options_->form);
-       fbullet = fl_addto_tabfolder(dialog_->tabfolder,_("Bullets"),
+       fbullet = fl_addto_tabfolder(dialog_->tabfolder,_("Bullets").c_str(),
                                     bullets_->form);
 
        if ((XpmVersion < 4) || (XpmVersion == 4 && XpmRevision < 7)) {
@@ -367,6 +418,9 @@ void FormDocument::build()
                fl_deactivate_object(fbullet);
                fl_set_object_lcol(fbullet, FL_INACTIVE);
        }
+
+       fl_addto_tabfolder(dialog_->tabfolder,_("Branches").c_str(),
+                                    branch_->form);
 }
 
 
@@ -379,6 +433,7 @@ void FormDocument::apply()
        language_apply(params);
        options_apply(params);
        bullets_apply(params);
+       branch_apply(params);
 }
 
 
@@ -396,6 +451,7 @@ void FormDocument::update()
        language_update(params);
        options_update(params);
        bullets_update(params);
+       branch_update(params);
 }
 
 
@@ -446,7 +502,7 @@ ButtonPolicy::SMInput FormDocument::input(FL_OBJECT * ob, long)
                // Default unit choice is cm if metric, inches if US paper.
                // If papersize is default, check the lyxrc-settings
                int const paperchoice = fl_get_choice(paper_->choice_papersize);
-               bool const metric = (paperchoice == 1 && lyxrc.default_papersize > BufferParams::PAPER_EXECUTIVEPAPER)
+               bool const metric = (paperchoice == 1 && lyxrc.default_papersize > PAPER_EXECUTIVEPAPER)
                        || paperchoice == 2 || paperchoice > 5;
                string const default_unit = metric ? "cm" : "in";
                if (getString(class_->input_skip).empty())
@@ -457,6 +513,15 @@ ButtonPolicy::SMInput FormDocument::input(FL_OBJECT * ob, long)
                setEnabled(options_->choice_citation_format,
                           fl_get_button(options_->check_use_natbib));
 
+       } else if (ob == branch_->browser_all_branches ||
+                       ob == branch_->browser_selection ||
+                       ob == branch_->button_add_branch ||
+                       ob == branch_->button_remove_branch ||
+                       ob == branch_->button_modify ||
+                       ob == branch_->button_select ||
+                       ob == branch_->button_deselect ||
+                       ob == branch_->button_deselect) {
+               branch_input(ob);
        } else if (ob == dialog_->button_save_defaults) {
                apply();
                controller().saveAsDefault();
@@ -469,7 +534,7 @@ ButtonPolicy::SMInput FormDocument::input(FL_OBJECT * ob, long)
 
        } else if (ob == paper_->radio_landscape) {
                fl_set_choice(paper_->choice_paperpackage,
-                             BufferParams::PACKAGE_NONE + 1);
+                             PACKAGE_NONE + 1);
 
        } else if (ob == paper_->choice_papersize) {
                int const paperchoice = fl_get_choice(paper_->choice_papersize);
@@ -512,7 +577,7 @@ ButtonPolicy::SMInput FormDocument::input(FL_OBJECT * ob, long)
 
                // Default unit choice is cm if metric, inches if US paper.
                // If papersize is default, use the lyxrc-settings
-               bool const metric = (defsize && lyxrc.default_papersize > BufferParams::PAPER_EXECUTIVEPAPER)
+               bool const metric = (defsize && lyxrc.default_papersize > PAPER_EXECUTIVEPAPER)
                        || paperchoice == 2 || paperchoice > 5;
                string const default_unit = metric ? "cm" : "in";
                if (getString(paper_->input_custom_width).empty())
@@ -570,7 +635,7 @@ ButtonPolicy::SMInput FormDocument::input(FL_OBJECT * ob, long)
                        fl_set_button(paper_->check_use_geometry, 1);
 
                fl_set_choice(paper_->choice_paperpackage,
-                             BufferParams::PACKAGE_NONE + 1);
+                             PACKAGE_NONE + 1);
 
                bool const use_geom = fl_get_button(paper_->check_use_geometry);
                setEnabled(paper_->input_top_margin,    use_geom);
@@ -594,11 +659,11 @@ ButtonPolicy::SMInput FormDocument::input(FL_OBJECT * ob, long)
                // either default papersize (preferences) or document
                // papersize has to be A4
                bool const enable = ( fl_get_choice(paper_->choice_papersize) == 1
-                                     && lyxrc.default_papersize == BufferParams::PAPER_A4PAPER )
+                                     && lyxrc.default_papersize == PAPER_A4PAPER )
                        || fl_get_choice(paper_->choice_papersize) == 7;
                if (!enable)
                        fl_set_choice(paper_->choice_paperpackage,
-                                     BufferParams::PACKAGE_NONE + 1);
+                                     PACKAGE_NONE + 1);
                setEnabled(paper_->choice_paperpackage,
                           enable && fl_get_button(paper_->radio_portrait));
        }
@@ -607,6 +672,139 @@ ButtonPolicy::SMInput FormDocument::input(FL_OBJECT * ob, long)
 }
 
 
+void FormDocument::branch_input(FL_OBJECT * ob)
+{
+       BufferParams & params = controller().params();
+       std::vector<string> vec;
+
+       if (ob == branch_->button_add_branch) {
+               string new_branch = fl_get_input(branch_->input_all_branches);
+               if (!new_branch.empty()) {
+                       params.branchlist.add(new_branch);
+                       fl_set_input(branch_->input_all_branches, "");
+                       // Update branch list
+                       string const all_branches = params.branchlist.allBranches();
+                       fl_clear_browser(branch_->browser_all_branches);
+                       vec = getVectorFromString(all_branches, "|");
+                       for (unsigned i = 0; i < vec.size(); ++i) {
+                               fl_addto_browser(branch_->browser_all_branches,
+                                                               vec[i].c_str());
+                       }
+                       LColor::color c = static_cast<LColor::color>(lcolor.size());
+                       lcolor.fill(c, new_branch, lcolor.getX11Name(LColor::background));
+               }
+
+       } else if (ob == branch_->button_remove_branch) {
+               unsigned i = fl_get_browser(branch_->browser_all_branches);
+               string const current_branch =
+                       fl_get_browser_line(branch_->browser_all_branches, i);
+               if (!current_branch.empty()) {
+                       params.branchlist.remove(current_branch);
+                       // Update branch list
+                       string const all_branches = params.branchlist.allBranches();
+                       fl_clear_browser(branch_->browser_all_branches);
+                       vec = getVectorFromString(all_branches, "|");
+                       for (unsigned i = 0; i < vec.size(); ++i) {
+                               fl_addto_browser(branch_->browser_all_branches,
+                                                               vec[i].c_str());
+                       }
+                       // Update selected-list...
+                       string const all_selected = params.branchlist.allSelected();
+                       fl_clear_browser(branch_->browser_selection);
+                       vec = getVectorFromString(all_selected, "|");
+                       for (unsigned i = 0; i < vec.size(); ++i) {
+                               fl_addto_browser(branch_->browser_selection, vec[i].c_str());
+                       }
+               }
+       } else if (ob == branch_->button_select) {
+               unsigned i = fl_get_browser(branch_->browser_all_branches);
+               string const current_branch =
+                       fl_get_browser_line(branch_->browser_all_branches, i);
+               if (!current_branch.empty()) {
+                       fl_clear_browser(branch_->browser_selection);
+                       params.branchlist.setSelected(current_branch, true);
+                       string const all_selected = params.branchlist.allSelected();
+                       vec = getVectorFromString(all_selected, "|");
+                       for (unsigned i = 0; i < vec.size(); ++i) {
+                               fl_addto_browser(branch_->browser_selection,
+                                                       vec[i].c_str());
+                       }
+               }
+       } else if (ob == branch_->button_deselect) {
+               unsigned i = fl_get_browser(branch_->browser_selection);
+               string const current_sel =
+                       fl_get_browser_line(branch_->browser_selection, i);
+               if (!current_sel.empty()) {
+                       fl_clear_browser(branch_->browser_selection);
+                       params.branchlist.setSelected(current_sel, false);
+                       string const all_selected = params.branchlist.allSelected();
+                       vec = getVectorFromString(all_selected, "|");
+                       for (unsigned i = 0; i < vec.size(); ++i) {
+                               fl_addto_browser(branch_->browser_selection,
+                                                       vec[i].c_str());
+                       }
+               }
+       } else if (ob == branch_->button_modify) {
+               unsigned i = fl_get_browser(branch_->browser_all_branches);
+               string const current_branch =
+                       fl_get_browser_line(branch_->browser_all_branches, i);
+               
+               RGBColor before;
+               string x11hexname = params.branchlist.getColor(current_branch);
+               if (x11hexname[0] == '#') {
+                       before = RGBColor(x11hexname);
+               } else{
+                       fl_getmcolor(FL_COL1, &before.r, &before.g, &before.b);
+               }
+
+               RGBColor col = picker_->requestColor(before);
+               if (before != col) {
+                       fl_mapcolor(GUI_COLOR_CHOICE, col.r, col.g, col.b);
+                       fl_redraw_object(branch_->button_color);
+                       // Figure out here how to stash the new colour into the
+                       // LyX colour database.
+
+                       x11hexname = X11hexname(col);
+
+                       // current_branch already in database
+                       LColor::color c = lcolor.getFromLyXName(current_branch);
+                       lcolor.setColor(current_branch, x11hexname);
+                       // Make sure that new colour is also displayed ;-)
+                       lyxColorHandler->getGCForeground(c);
+                       lyxColorHandler->updateColor(c);
+                       // what about system_lcolor?
+                       // Here set colour in BranchList:
+                       params.branchlist.setColor(current_branch, x11hexname);
+               }
+       } else if (ob == branch_->browser_all_branches) {
+               unsigned i = fl_get_browser(branch_->browser_all_branches);
+               string const current_branch =
+                       fl_get_browser_line(branch_->browser_all_branches, i);
+               // make button_color track selected branch:
+
+               RGBColor rgb;
+               string x11hexname = params.branchlist.getColor(current_branch);
+               if (x11hexname[0] == '#') {
+                       rgb = RGBColor(x11hexname);
+               } else {
+                       fl_getmcolor(FL_COL1, &rgb.r, &rgb.g, &rgb.b);
+               }
+               fl_mapcolor(GUI_COLOR_CHOICE, rgb.r, rgb.g, rgb.b);
+               fl_redraw_object(branch_->button_color);
+       }
+       setEnabled(branch_->button_select,
+               (fl_get_browser(branch_->browser_all_branches) > 0));
+       setEnabled(branch_->button_deselect,
+               (fl_get_browser(branch_->browser_selection) > 0));
+       setEnabled(branch_->button_remove_branch,
+               (fl_get_browser(branch_->browser_all_branches) > 0));
+       setEnabled(branch_->button_modify,
+               (fl_get_browser(branch_->browser_all_branches) > 0));
+
+       branchlist_ = params.branchlist;
+}
+
+
 bool FormDocument::class_apply(BufferParams &params)
 {
        bool redo = false;
@@ -671,19 +869,19 @@ bool FormDocument::class_apply(BufferParams &params)
        Spacing tmpSpacing = params.spacing;
        switch (fl_get_choice(class_->choice_spacing)) {
        case 1:
-               lyxerr[Debug::INFO] << "Spacing: SINGLE\n";
+               lyxerr[Debug::INFO] << "Spacing: SINGLE" << endl;
                params.spacing.set(Spacing::Single);
                break;
        case 2:
-               lyxerr[Debug::INFO] << "Spacing: ONEHALF\n";
+               lyxerr[Debug::INFO] << "Spacing: ONEHALF" << endl;
                params.spacing.set(Spacing::Onehalf);
                break;
        case 3:
-               lyxerr[Debug::INFO] << "Spacing: DOUBLE\n";
+               lyxerr[Debug::INFO] << "Spacing: DOUBLE" << endl;
                params.spacing.set(Spacing::Double);
                break;
        case 4:
-               lyxerr[Debug::INFO] << "Spacing: OTHER\n";
+               lyxerr[Debug::INFO] << "Spacing: OTHER" << endl;
                params.spacing.set(Spacing::Other,
                                   getString(class_->input_spacing));
                break;
@@ -699,10 +897,10 @@ bool FormDocument::class_apply(BufferParams &params)
 
 void FormDocument::paper_apply(BufferParams & params)
 {
-       params.papersize2 = char(fl_get_choice(paper_->choice_papersize) - 1);
+       params.papersize2 = VMARGIN_PAPER_TYPE(fl_get_choice(paper_->choice_papersize) - 1);
 
        params.paperpackage =
-               char(fl_get_choice(paper_->choice_paperpackage) - 1);
+               PAPER_PACKAGES(fl_get_choice(paper_->choice_paperpackage) - 1);
 
        // set params.papersize from params.papersize2 and params.paperpackage
        params.setPaperStuff();
@@ -710,9 +908,9 @@ void FormDocument::paper_apply(BufferParams & params)
        params.use_geometry = fl_get_button(paper_->check_use_geometry);
 
        if (fl_get_button(paper_->radio_landscape))
-               params.orientation = BufferParams::ORIENTATION_LANDSCAPE;
+               params.orientation = ORIENTATION_LANDSCAPE;
        else
-               params.orientation = BufferParams::ORIENTATION_PORTRAIT;
+               params.orientation = ORIENTATION_PORTRAIT;
 
        params.paperwidth =
                getLengthFromWidgets(paper_->input_custom_width,
@@ -831,6 +1029,16 @@ void FormDocument::bullets_apply(BufferParams & params)
 }
 
 
+void FormDocument::branch_apply(BufferParams & params)
+{
+       BufferParams & prms = controller().params();
+       if (branchlist_.empty())
+               branchlist_ = prms.branchlist;
+       params.branchlist = branchlist_;
+       branchlist_.clear();
+}
+
+               
 void FormDocument::UpdateClassParams(BufferParams const & params)
 {
        // These are the params that have to be updated on any class change
@@ -892,7 +1100,7 @@ void FormDocument::class_update(BufferParams const & params)
        bool const length_input = pos == 4;
        if (length_input) {
                int const paperchoice = fl_get_choice(paper_->choice_papersize);
-               bool const metric = (paperchoice == 1 && lyxrc.default_papersize > BufferParams::PAPER_EXECUTIVEPAPER)
+               bool const metric = (paperchoice == 1 && lyxrc.default_papersize > PAPER_EXECUTIVEPAPER)
                        || paperchoice == 2 || paperchoice > 5;
                string const default_unit = metric ? "cm" : "in";
                string const length = params.getDefSkip().asLyXCommand();
@@ -1001,7 +1209,7 @@ void FormDocument::paper_update(BufferParams const & params)
        fl_set_button(paper_->radio_landscape, 0);
        setEnabled(paper_->radio_landscape, !useCustom);
 
-       if (params.orientation == BufferParams::ORIENTATION_LANDSCAPE)
+       if (params.orientation == ORIENTATION_LANDSCAPE)
                fl_set_button(paper_->radio_landscape, 1);
        else
                fl_set_button(paper_->radio_portrait, 1);
@@ -1009,11 +1217,11 @@ void FormDocument::paper_update(BufferParams const & params)
                   //either default papersize (preferences)
                   //or document papersize has to be A4
                   (paperchoice == 7
-                   || paperchoice == 1 && lyxrc.default_papersize == BufferParams::PAPER_A4PAPER)
+                   || paperchoice == 1 && lyxrc.default_papersize == PAPER_A4PAPER)
                   && fl_get_button(paper_->radio_portrait));
 
        // Default unit choice is cm if metric, inches if US paper.
-       bool const metric = (paperchoice == 1 && lyxrc.default_papersize > BufferParams::PAPER_EXECUTIVEPAPER)
+       bool const metric = (paperchoice == 1 && lyxrc.default_papersize > PAPER_EXECUTIVEPAPER)
                || paperchoice == 2 || paperchoice > 5;
        string const default_unit = metric ? "cm" : "in";
        updateWidgetsFromLengthString(paper_->input_custom_width,
@@ -1095,6 +1303,56 @@ void FormDocument::bullets_update(BufferParams const & params)
 }
 
 
+void FormDocument::branch_update(BufferParams const & params)
+{
+       if (!branch_.get())
+               return;
+       
+       string const all_branches = params.branchlist.allBranches();
+       fl_clear_browser(branch_->browser_all_branches);
+       string current_branch("none");
+       
+       if (!all_branches.empty()) {
+               std::vector<string> vec = getVectorFromString(all_branches, "|");
+               for (unsigned i = 0; i < vec.size(); ++i) {
+                       fl_addto_browser(branch_->browser_all_branches, vec[i].c_str());
+               }
+               fl_select_browser_line(branch_->browser_all_branches, 1);
+               current_branch =
+                       fl_get_browser_line(branch_->browser_all_branches, 1);
+       }
+
+       // display proper selection...
+       string const all_selected = params.branchlist.allSelected();
+       fl_clear_browser(branch_->browser_selection);
+       if (!all_selected.empty()) {
+               std::vector<string> vec = getVectorFromString(all_selected, "|");
+               for (unsigned i = 0; i < vec.size(); ++i) {
+                       fl_addto_browser(branch_->browser_selection, vec[i].c_str());
+                       }
+       }
+       // display proper colour...
+       RGBColor rgb;
+       string x11hexname = params.branchlist.getColor(current_branch);
+       if (x11hexname[0] == '#') {
+               rgb = RGBColor(x11hexname);
+       } else {
+               fl_getmcolor(FL_COL1, &rgb.r, &rgb.g, &rgb.b);
+       }
+       fl_mapcolor(GUI_COLOR_CHOICE, rgb.r, rgb.g, rgb.b);
+       fl_redraw_object(branch_->button_color);
+
+       setEnabled(branch_->button_select,
+               (fl_get_browser(branch_->browser_all_branches) > 0));
+       setEnabled(branch_->button_deselect,
+               (fl_get_browser(branch_->browser_selection) > 0));
+       setEnabled(branch_->button_remove_branch,
+               (fl_get_browser(branch_->browser_all_branches) > 0));
+       setEnabled(branch_->button_modify,
+               (fl_get_browser(branch_->browser_all_branches) > 0));
+}
+
+
 void FormDocument::checkReadOnly()
 {
        if (bc().readOnly(controller().bufferIsReadonly())) {