Prevent region drags with the middle button in internal edit mode (#3869).
[ardour.git] / gtk2_ardour / utils.cc
index 5e5534222e174a71b700de94dab63b99d4d7a905..8cdf5e0b58650b3a04083b6d97308c2146e8da19 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
-    Copyright (C) 2003 Paul Davis 
+    Copyright (C) 2003 Paul Davis
 
     This program is free software; you an redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 
     This program is free software; you an redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 
 */
 
 
 */
 
+#ifdef WAF_BUILD
+#include "gtk2ardour-config.h"
+#endif
+
 #include <pango/pangoft2.h> // for fontmap resolution control for GnomeCanvas
 #include <pango/pangocairo.h> // for fontmap resolution control for GnomeCanvas
 
 #include <pango/pangoft2.h> // for fontmap resolution control for GnomeCanvas
 #include <pango/pangocairo.h> // for fontmap resolution control for GnomeCanvas
 
 
 #include <gtkmm2ext/utils.h>
 #include "ardour/configuration.h"
 
 #include <gtkmm2ext/utils.h>
 #include "ardour/configuration.h"
-#include "ardour/configuration.h"
+#include "ardour/rc_configuration.h"
 
 #include "ardour/filesystem_paths.h"
 
 #include "ardour_ui.h"
 
 #include "ardour/filesystem_paths.h"
 
 #include "ardour_ui.h"
+#include "debug.h"
 #include "public_editor.h"
 #include "keyboard.h"
 #include "utils.h"
 #include "i18n.h"
 #include "rgb_macros.h"
 #include "canvas_impl.h"
 #include "public_editor.h"
 #include "keyboard.h"
 #include "utils.h"
 #include "i18n.h"
 #include "rgb_macros.h"
 #include "canvas_impl.h"
+#include "gui_thread.h"
 
 using namespace std;
 using namespace Gtk;
 
 using namespace std;
 using namespace Gtk;
-using namespace sigc;
 using namespace Glib;
 using namespace PBD;
 using namespace Glib;
 using namespace PBD;
+using Gtkmm2ext::Keyboard;
 
 sigc::signal<void>  DPIReset;
 
 int
 
 sigc::signal<void>  DPIReset;
 
 int
-pixel_width (const ustring& str, Pango::FontDescription& font)
+pixel_width (const string& str, Pango::FontDescription& font)
 {
        Label foo;
        Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout ("");
 {
        Label foo;
        Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout ("");
@@ -70,20 +76,20 @@ pixel_width (const ustring& str, Pango::FontDescription& font)
        return width;
 }
 
        return width;
 }
 
-ustring
-fit_to_pixels (const ustring& str, int pixel_width, Pango::FontDescription& font, int& actual_width, bool with_ellipses)
+string
+fit_to_pixels (const string& str, int pixel_width, Pango::FontDescription& font, int& actual_width, bool with_ellipses)
 {
        Label foo;
        Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout ("");
 {
        Label foo;
        Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout ("");
-       ustring::size_type shorter_by = 0;
-       ustring txt;
+       string::size_type shorter_by = 0;
+       string txt;
 
        layout->set_font_description (font);
 
        actual_width = 0;
 
 
        layout->set_font_description (font);
 
        actual_width = 0;
 
-       ustring ustr = str;
-       ustring::iterator last = ustr.end();
+       string ustr = str;
+       string::iterator last = ustr.end();
        --last; /* now points at final entry */
 
        txt = ustr;
        --last; /* now points at final entry */
 
        txt = ustr;
@@ -99,7 +105,7 @@ fit_to_pixels (const ustring& str, int pixel_width, Pango::FontDescription& font
                        actual_width = width;
                        break;
                }
                        actual_width = width;
                        break;
                }
-               
+
                ustr.erase (last--);
                shorter_by++;
 
                ustr.erase (last--);
                shorter_by++;
 
@@ -128,7 +134,7 @@ fit_to_pixels (cairo_t* cr, std::string name, double avail)
 
        bool abbreviated = false;
        uint32_t width = 0;
 
        bool abbreviated = false;
        uint32_t width = 0;
-               
+
        while (1) {
                cairo_text_extents_t ext;
                cairo_text_extents (cr, name.c_str(), &ext);
        while (1) {
                cairo_text_extents_t ext;
                cairo_text_extents (cr, name.c_str(), &ext);
@@ -187,9 +193,9 @@ xpm2rgb (const char** xpm, uint32_t& w, uint32_t& h)
        uint32_t t, x, y, colors, cpp;
        unsigned char c;
        unsigned char *savergb, *rgb;
        uint32_t t, x, y, colors, cpp;
        unsigned char c;
        unsigned char *savergb, *rgb;
-       
+
        // PARSE HEADER
        // PARSE HEADER
-       
+
        if ( sscanf(xpm[0], "%u%u%u%u", &w, &h, &colors, &cpp) != 4 ) {
                error << string_compose (_("bad XPM header %1"), xpm[0])
                      << endmsg;
        if ( sscanf(xpm[0], "%u%u%u%u", &w, &h, &colors, &cpp) != 4 ) {
                error << string_compose (_("bad XPM header %1"), xpm[0])
                      << endmsg;
@@ -197,13 +203,13 @@ xpm2rgb (const char** xpm, uint32_t& w, uint32_t& h)
        }
 
        savergb = rgb = (unsigned char*) malloc (h * w * 3);
        }
 
        savergb = rgb = (unsigned char*) malloc (h * w * 3);
-       
+
        // LOAD XPM COLORMAP LONG ENOUGH TO DO CONVERSION
        for (t = 0; t < colors; ++t) {
                sscanf (xpm[t+1], "%c c #%lx", &c, &val);
                vals[c] = val;
        }
        // LOAD XPM COLORMAP LONG ENOUGH TO DO CONVERSION
        for (t = 0; t < colors; ++t) {
                sscanf (xpm[t+1], "%c c #%lx", &c, &val);
                vals[c] = val;
        }
-       
+
        // COLORMAP -> RGB CONVERSION
        //    Get low 3 bytes from vals[]
        //
        // COLORMAP -> RGB CONVERSION
        //    Get low 3 bytes from vals[]
        //
@@ -240,7 +246,7 @@ xpm2rgba (const char** xpm, uint32_t& w, uint32_t& h)
        }
 
        savergb = rgb = (unsigned char*) malloc (h * w * 4);
        }
 
        savergb = rgb = (unsigned char*) malloc (h * w * 4);
-       
+
        // LOAD XPM COLORMAP LONG ENOUGH TO DO CONVERSION
 
        if (strstr (xpm[1], "None")) {
        // LOAD XPM COLORMAP LONG ENOUGH TO DO CONVERSION
 
        if (strstr (xpm[1], "None")) {
@@ -255,7 +261,7 @@ xpm2rgba (const char** xpm, uint32_t& w, uint32_t& h)
                sscanf (xpm[t+1], "%c c #%lx", &c, &val);
                vals[c] = val;
        }
                sscanf (xpm[t+1], "%c c #%lx", &c, &val);
                vals[c] = val;
        }
-       
+
        // COLORMAP -> RGB CONVERSION
        //    Get low 3 bytes from vals[]
        //
        // COLORMAP -> RGB CONVERSION
        //    Get low 3 bytes from vals[]
        //
@@ -311,17 +317,17 @@ get_font_for_style (string widgetname)
        style = foobar.get_style ();
 
        Glib::RefPtr<const Pango::Layout> layout = foobar.get_layout();
        style = foobar.get_style ();
 
        Glib::RefPtr<const Pango::Layout> layout = foobar.get_layout();
-       
+
        PangoFontDescription *pfd = (PangoFontDescription *)pango_layout_get_font_description((PangoLayout *)layout->gobj());
        PangoFontDescription *pfd = (PangoFontDescription *)pango_layout_get_font_description((PangoLayout *)layout->gobj());
-       
+
        if (!pfd) {
        if (!pfd) {
-               
+
                /* layout inherited its font description from a PangoContext */
 
                PangoContext* ctxt = (PangoContext*) pango_layout_get_context ((PangoLayout*) layout->gobj());
                pfd =  pango_context_get_font_description (ctxt);
                return new Pango::FontDescription (pfd, true); /* make a copy */
                /* layout inherited its font description from a PangoContext */
 
                PangoContext* ctxt = (PangoContext*) pango_layout_get_context ((PangoLayout*) layout->gobj());
                pfd =  pango_context_get_font_description (ctxt);
                return new Pango::FontDescription (pfd, true); /* make a copy */
-       } 
+       }
 
        return new Pango::FontDescription (pfd, true); /* make a copy */
 }
 
        return new Pango::FontDescription (pfd, true); /* make a copy */
 }
@@ -340,44 +346,44 @@ rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a, s
        }
 
        Gtk::Label foo;
        }
 
        Gtk::Label foo;
-       
+
        window->add (foo);
 
        foo.set_name (style);
        foo.ensure_style ();
        window->add (foo);
 
        foo.set_name (style);
        foo.ensure_style ();
-       
-       GtkRcStyle* waverc = foo.get_style()->gobj()->rc_style;
 
 
-       if (waverc) {
+       GtkRcStyle* rc = foo.get_style()->gobj()->rc_style;
+
+       if (rc) {
                if (attr == "fg") {
                if (attr == "fg") {
-                       r = waverc->fg[state].red / 257;
-                       g = waverc->fg[state].green / 257;
-                       b = waverc->fg[state].blue / 257;
+                       r = rc->fg[state].red / 257;
+                       g = rc->fg[state].green / 257;
+                       b = rc->fg[state].blue / 257;
+
                        /* what a hack ... "a" is for "active" */
                        if (state == Gtk::STATE_NORMAL && rgba) {
                        /* what a hack ... "a" is for "active" */
                        if (state == Gtk::STATE_NORMAL && rgba) {
-                               a = waverc->fg[GTK_STATE_ACTIVE].red / 257;
+                               a = rc->fg[GTK_STATE_ACTIVE].red / 257;
                        }
                } else if (attr == "bg") {
                        r = g = b = 0;
                        }
                } else if (attr == "bg") {
                        r = g = b = 0;
-                       r = waverc->bg[state].red / 257;
-                       g = waverc->bg[state].green / 257;
-                       b = waverc->bg[state].blue / 257;
+                       r = rc->bg[state].red / 257;
+                       g = rc->bg[state].green / 257;
+                       b = rc->bg[state].blue / 257;
                } else if (attr == "base") {
                } else if (attr == "base") {
-                       r = waverc->base[state].red / 257;
-                       g = waverc->base[state].green / 257;
-                       b = waverc->base[state].blue / 257;
+                       r = rc->base[state].red / 257;
+                       g = rc->base[state].green / 257;
+                       b = rc->base[state].blue / 257;
                } else if (attr == "text") {
                } else if (attr == "text") {
-                       r = waverc->text[state].red / 257;
-                       g = waverc->text[state].green / 257;
-                       b = waverc->text[state].blue / 257;
+                       r = rc->text[state].red / 257;
+                       g = rc->text[state].green / 257;
+                       b = rc->text[state].blue / 257;
                }
        } else {
                warning << string_compose (_("missing RGBA style for \"%1\""), style) << endl;
        }
 
        window->remove ();
                }
        } else {
                warning << string_compose (_("missing RGBA style for \"%1\""), style) << endl;
        }
 
        window->remove ();
-       
+
        if (state == Gtk::STATE_NORMAL && rgba) {
                return (uint32_t) RGBA_TO_UINT(r,g,b,a);
        } else {
        if (state == Gtk::STATE_NORMAL && rgba) {
                return (uint32_t) RGBA_TO_UINT(r,g,b,a);
        } else {
@@ -491,7 +497,7 @@ gc_from_style (string widget_style_name, int state, string attr)
 }
 
 
 }
 
 
-bool 
+bool
 canvas_item_visible (ArdourCanvas::Item* item)
 {
        return (item->gobj()->object.flags & GNOME_CANVAS_ITEM_VISIBLE) ? true : false;
 canvas_item_visible (ArdourCanvas::Item* item)
 {
        return (item->gobj()->object.flags & GNOME_CANVAS_ITEM_VISIBLE) ? true : false;
@@ -503,12 +509,6 @@ set_color (Gdk::Color& c, int rgb)
        c.set_rgb((rgb >> 16)*256, ((rgb & 0xff00) >> 8)*256, (rgb & 0xff)*256);
 }
 
        c.set_rgb((rgb >> 16)*256, ((rgb & 0xff00) >> 8)*256, (rgb & 0xff)*256);
 }
 
-#ifdef GTKOSX
-extern "C" {
-       gboolean gdk_quartz_possibly_forward (GdkEvent*);
-}
-#endif
-
 bool
 relay_key_press (GdkEventKey* ev, Gtk::Window* win)
 {
 bool
 relay_key_press (GdkEventKey* ev, Gtk::Window* win)
 {
@@ -519,6 +519,79 @@ relay_key_press (GdkEventKey* ev, Gtk::Window* win)
        }
 }
 
        }
 }
 
+bool
+forward_key_press (GdkEventKey* ev)
+{
+        return PublicEditor::instance().on_key_press_event(ev);
+}
+
+#ifdef GTKOSX
+static guint
+osx_keyval_without_alt (guint accent_keyval)
+{
+       switch (accent_keyval) {
+       case GDK_oe:
+               return GDK_q;
+       case GDK_registered:
+               return GDK_r;
+       case GDK_dagger:
+               return GDK_t;
+       case GDK_yen:
+               return GDK_y;
+       case GDK_diaeresis:
+               return GDK_u;
+       case GDK_oslash:
+               return GDK_o;
+       case GDK_Greek_pi:
+               return GDK_p;
+       case GDK_leftdoublequotemark:
+               return GDK_bracketleft;
+       case GDK_leftsinglequotemark:
+               return GDK_bracketright;
+       case GDK_guillemotleft:
+               return GDK_backslash;
+       case GDK_aring:
+               return GDK_a;
+       case GDK_ssharp:
+               return GDK_s;
+       case GDK_partialderivative:
+               return GDK_d;
+       case GDK_function:
+               return GDK_f;
+       case GDK_copyright:
+               return GDK_g;
+       case GDK_abovedot:
+               return GDK_h;
+       case GDK_notsign:
+               return GDK_l;
+       case GDK_ellipsis:
+               return GDK_semicolon;
+       case GDK_ae:
+               return GDK_apostrophe;
+       case GDK_Greek_OMEGA:
+               return GDK_z;
+       case GDK_ccedilla:
+               return GDK_c;
+       case GDK_radical:
+               return GDK_v;
+       case GDK_integral:
+               return GDK_b;
+       case GDK_mu:
+               return GDK_m;
+       case GDK_lessthanequal:
+               return GDK_comma;
+       case GDK_greaterthanequal:
+               return GDK_period;
+       case GDK_division:
+               return GDK_slash;
+       default:
+               break;
+       }
+
+       return GDK_VoidSymbol;
+}
+#endif
+
 bool
 key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
 {
 bool
 key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
 {
@@ -527,16 +600,11 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
        bool special_handling_of_unmodified_accelerators = false;
        bool allow_activating = true;
 
        bool special_handling_of_unmodified_accelerators = false;
        bool allow_activating = true;
 
-#undef DEBUG_ACCELERATOR_HANDLING
-#ifdef  DEBUG_ACCELERATOR_HANDLING
-       //bool debug = (getenv ("ARDOUR_DEBUG_ACCELERATOR_HANDLING") != 0);
-       bool debug=true;
-#endif
        if (focus) {
                if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
                        special_handling_of_unmodified_accelerators = true;
        if (focus) {
                if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
                        special_handling_of_unmodified_accelerators = true;
-               } 
-       } 
+               }
+       }
 
 #ifdef GTKOSX
        /* should this be universally true? */
 
 #ifdef GTKOSX
        /* should this be universally true? */
@@ -545,18 +613,15 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
        }
 #endif
 
        }
 #endif
 
-#ifdef DEBUG_ACCELERATOR_HANDLING
-       if (debug) {
-               cerr << "Win = " << win << " Key event: code = " << ev->keyval << " state = " << hex << ev->state << dec << " special handling ? " 
-                    << special_handling_of_unmodified_accelerators
-                    << " magic widget focus ? "
-                    << Keyboard::some_magic_widget_has_focus()
-                    << " allow_activation ? "
-                    << allow_activating
-                    << endl;
-       }
-#endif
-
+        
+        DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 Key event: code = %2  state = %3 special handling ? %4 magic widget focus ? %5 allow_activation ? %6\n",
+                                                          win,
+                                                          ev->keyval,
+                                                          ev->state,
+                                                          special_handling_of_unmodified_accelerators,
+                                                          Keyboard::some_magic_widget_has_focus(),
+                                                          allow_activating));
+        
        /* This exists to allow us to override the way GTK handles
           key events. The normal sequence is:
 
        /* This exists to allow us to override the way GTK handles
           key events. The normal sequence is:
 
@@ -566,18 +631,18 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
               the focus widget and/or focus chain
 
           The problem with this is that if the accelerators include
               the focus widget and/or focus chain
 
           The problem with this is that if the accelerators include
-          keys without modifiers, such as the space bar or the 
+          keys without modifiers, such as the space bar or the
           letter "e", then pressing the key while typing into
           a text entry widget results in the accelerator being
           activated, instead of the desired letter appearing
           in the text entry.
 
           There is no good way of fixing this, but this
           letter "e", then pressing the key while typing into
           a text entry widget results in the accelerator being
           activated, instead of the desired letter appearing
           in the text entry.
 
           There is no good way of fixing this, but this
-          represents a compromise. The idea is that 
+          represents a compromise. The idea is that
           key events involving modifiers (not Shift)
           get routed into the activation pathway first, then
           get propagated to the focus widget if necessary.
           key events involving modifiers (not Shift)
           get routed into the activation pathway first, then
           get propagated to the focus widget if necessary.
-          
+
           If the key event doesn't involve modifiers,
           we deliver to the focus widget first, thus allowing
           it to get "normal text" without interference
           If the key event doesn't involve modifiers,
           we deliver to the focus widget first, thus allowing
           it to get "normal text" without interference
@@ -588,6 +653,22 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
           all "normal text" accelerators.
        */
 
           all "normal text" accelerators.
        */
 
+#ifdef GTKOSX
+       if (!special_handling_of_unmodified_accelerators) {
+               if (ev->state & GDK_MOD1_MASK) {
+                       /* we're not in a text entry or "magic focus" widget so we don't want OS X "special-character" 
+                          text-style handling of alt-<key>. change the keyval back to what it would be without
+                          the alt key. this way, we see <alt>-v rather than <alt>-radical and so on.
+                       */
+                       guint keyval_without_alt = osx_keyval_without_alt (ev->keyval);
+
+                       if (keyval_without_alt != GDK_VoidSymbol) {
+                                DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Remapped %1 to %2\n", gdk_keyval_name (ev->keyval), gdk_keyval_name (keyval_without_alt)));
+                               ev->keyval = keyval_without_alt;
+                       }
+               }
+       }
+#endif
 
        if (!special_handling_of_unmodified_accelerators) {
 
 
        if (!special_handling_of_unmodified_accelerators) {
 
@@ -598,21 +679,10 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
 
                uint32_t fakekey = ev->keyval;
 
 
                uint32_t fakekey = ev->keyval;
 
-               if (possibly_translate_keyval_to_make_legal_accelerator (fakekey)) {
+               if (Gtkmm2ext::possibly_translate_keyval_to_make_legal_accelerator (fakekey)) {
                        if (allow_activating && gtk_accel_groups_activate(G_OBJECT(win), fakekey, GdkModifierType(ev->state))) {
                                return true;
                        }
                        if (allow_activating && gtk_accel_groups_activate(G_OBJECT(win), fakekey, GdkModifierType(ev->state))) {
                                return true;
                        }
-
-#ifdef GTKOSX
-                       if (allow_activating) {
-                               int oldval = ev->keyval;
-                               ev->keyval = fakekey;
-                               if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
-                                       return true;
-                               }
-                               ev->keyval = oldval;
-                       }
-#endif
                }
        }
 
                }
        }
 
@@ -624,88 +694,54 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
 
                /* no special handling or there are modifiers in effect: accelerate first */
 
 
                /* no special handling or there are modifiers in effect: accelerate first */
 
-#ifdef DEBUG_ACCELERATOR_HANDLING
-               if (debug) {
-                       cerr << "\tactivate, then propagate\n";
-               }
-#endif
+                DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
 
                if (allow_activating) {
 
                if (allow_activating) {
-#ifdef GTKOSX
-                       if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
-                               return true;
-                       }
-#endif
                        if (gtk_window_activate_key (win, ev)) {
                                return true;
                        }
                }
 
                        if (gtk_window_activate_key (win, ev)) {
                                return true;
                        }
                }
 
-#ifdef DEBUG_ACCELERATOR_HANDLING
-               if (debug) {
-                       cerr << "\tnot accelerated, now propagate\n";
-               }
-#endif
+                DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
+
                return gtk_window_propagate_key_event (win, ev);
        }
                return gtk_window_propagate_key_event (win, ev);
        }
-       
+
        /* no modifiers, propagate first */
        /* no modifiers, propagate first */
-       
-#ifdef DEBUG_ACCELERATOR_HANDLING
-       if (debug) {
-               cerr << "\tpropagate, then activate\n";
-       }
-#endif
-       if (!gtk_window_propagate_key_event (win, ev)) {
-#ifdef DEBUG_ACCELERATOR_HANDLING
-               if (debug) {
-                       cerr << "\tpropagation didn't handle, so activate\n";
-               }
-#endif
 
 
+        DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
+
+       if (!gtk_window_propagate_key_event (win, ev)) {
+                DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
                if (allow_activating) {
                if (allow_activating) {
-                       
-#ifdef GTKOSX
-                       if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
-                               return true;
-                       }
-#endif
                        return gtk_window_activate_key (win, ev);
                        return gtk_window_activate_key (win, ev);
-               } 
-                       
-       } else {
-#ifdef DEBUG_ACCELERATOR_HANDLING
-               if (debug) {
-                       cerr << "\thandled by propagate\n";
                }
                }
-#endif
+
+       } else {
+                DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
                return true;
        }
 
                return true;
        }
 
-#ifdef DEBUG_ACCELERATOR_HANDLING
-       if (debug) {
-               cerr << "\tnot handled\n";
-       }
-#endif
+        DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
        return true;
 }
 
        return true;
 }
 
-Glib::RefPtr<Gdk::Pixbuf>      
+Glib::RefPtr<Gdk::Pixbuf>
 get_xpm (std::string name)
 {
        if (!xpm_map[name]) {
 
                SearchPath spath(ARDOUR::ardour_search_path());
                spath += ARDOUR::system_data_search_path();
 get_xpm (std::string name)
 {
        if (!xpm_map[name]) {
 
                SearchPath spath(ARDOUR::ardour_search_path());
                spath += ARDOUR::system_data_search_path();
-               
+
                spath.add_subdirectory_to_paths("pixmaps");
                spath.add_subdirectory_to_paths("pixmaps");
-               
+
                sys::path data_file_path;
                sys::path data_file_path;
-               
+
                if(!find_file_in_search_path (spath, name, data_file_path)) {
                        fatal << string_compose (_("cannot find XPM file for %1"), name) << endmsg;
                }
                if(!find_file_in_search_path (spath, name, data_file_path)) {
                        fatal << string_compose (_("cannot find XPM file for %1"), name) << endmsg;
                }
-               
+
                try {
                        xpm_map[name] =  Gdk::Pixbuf::create_from_file (data_file_path.to_string());
                } catch(const Glib::Error& e)   {
                try {
                        xpm_map[name] =  Gdk::Pixbuf::create_from_file (data_file_path.to_string());
                } catch(const Glib::Error& e)   {
@@ -716,7 +752,7 @@ get_xpm (std::string name)
        return xpm_map[name];
 }
 
        return xpm_map[name];
 }
 
-Glib::ustring
+std::string
 get_icon_path (const char* cname)
 {
        string name = cname;
 get_icon_path (const char* cname)
 {
        string name = cname;
@@ -736,7 +772,7 @@ get_icon_path (const char* cname)
        return data_file_path.to_string();
 }
 
        return data_file_path.to_string();
 }
 
-Glib::RefPtr<Gdk::Pixbuf>      
+Glib::RefPtr<Gdk::Pixbuf>
 get_icon (const char* cname)
 {
        Glib::RefPtr<Gdk::Pixbuf> img;
 get_icon (const char* cname)
 {
        Glib::RefPtr<Gdk::Pixbuf> img;
@@ -760,22 +796,22 @@ longest (vector<string>& strings)
 
        vector<string>::iterator longest = strings.begin();
        string::size_type longest_length = (*longest).length();
 
        vector<string>::iterator longest = strings.begin();
        string::size_type longest_length = (*longest).length();
-       
+
        vector<string>::iterator i = longest;
        ++i;
 
        while (i != strings.end()) {
        vector<string>::iterator i = longest;
        ++i;
 
        while (i != strings.end()) {
-               
+
                string::size_type len = (*i).length();
                string::size_type len = (*i).length();
-               
+
                if (len > longest_length) {
                        longest = i;
                        longest_length = len;
                if (len > longest_length) {
                        longest = i;
                        longest_length = len;
-               } 
-               
+               }
+
                ++i;
        }
                ++i;
        }
-       
+
        return *longest;
 }
 
        return *longest;
 }
 
@@ -819,7 +855,7 @@ key_is_legal_for_numeric_entry (guint keyval)
        case GDK_Left:
        case GDK_Right:
                return true;
        case GDK_Left:
        case GDK_Right:
                return true;
-               
+
        default:
                break;
        }
        default:
                break;
        }
@@ -836,7 +872,7 @@ set_pango_fontsize ()
        pango_ft2_font_map_set_resolution ((PangoFT2FontMap*) pango_ft2_font_map_for_display(), val/1024, val/1024);
 
        /* Cairo rendering, in case there is any */
        pango_ft2_font_map_set_resolution ((PangoFT2FontMap*) pango_ft2_font_map_for_display(), val/1024, val/1024);
 
        /* Cairo rendering, in case there is any */
-       
+
        pango_cairo_font_map_set_resolution ((PangoCairoFontMap*) pango_cairo_font_map_get_default(), val/1024);
 }
 
        pango_cairo_font_map_set_resolution ((PangoCairoFontMap*) pango_cairo_font_map_get_default(), val/1024);
 }
 
@@ -852,74 +888,36 @@ reset_dpi ()
        DPIReset();//Emit Signal
 }
 
        DPIReset();//Emit Signal
 }
 
-bool
-possibly_translate_keyval_to_make_legal_accelerator (uint32_t& keyval)
+void
+resize_window_to_proportion_of_monitor (Gtk::Window* window, int max_width, int max_height)
 {
 {
-       int fakekey = GDK_VoidSymbol;
+       Glib::RefPtr<Gdk::Screen> screen = window->get_screen ();
+       Gdk::Rectangle monitor_rect;
+       screen->get_monitor_geometry (0, monitor_rect);
 
 
-       switch (keyval) {
-       case GDK_Tab:
-       case GDK_ISO_Left_Tab:
-               fakekey = GDK_nabla;
-               break;
-               
-       case GDK_Up:
-               fakekey = GDK_uparrow;
-               break;
-               
-       case GDK_Down:
-               fakekey = GDK_downarrow;
-               break;
-               
-       case GDK_Right:
-               fakekey = GDK_rightarrow;
-               break;
-               
-       case GDK_Left:
-               fakekey = GDK_leftarrow;
-               break;
-               
-       default:
-               break;
-       }
-       
-       if (fakekey != GDK_VoidSymbol) {
-               keyval = fakekey;
-               return true;
-       } 
+       int const w = std::min (int (monitor_rect.get_width() * 0.8), max_width);
+       int const h = std::min (int (monitor_rect.get_height() * 0.8), max_height);
 
 
-       return false;
+       window->resize (w, h);
 }
 }
-               
 
 
-inline guint8
-convert_color_channel (guint8 src,
-                      guint8 alpha)
-{
-       return alpha ? ((guint (src) << 8) - src) / alpha : 0;
-}
 
 
-void
-convert_bgra_to_rgba (guint8 const* src,
-                     guint8*       dst,
-                     int           width,
-                     int           height)
+/** Replace _ with __ in a string; for use with menu item text to make underscores displayed correctly */
+string
+escape_underscores (string const & s)
 {
 {
-       guint8 const* src_pixel = src;
-       guint8*       dst_pixel = dst;
-       
-       for (int y = 0; y < height; y++)
-               for (int x = 0; x < width; x++)
-               {
-                       dst_pixel[0] = convert_color_channel (src_pixel[2],
-                                                             src_pixel[3]);
-                       dst_pixel[1] = convert_color_channel (src_pixel[1],
-                                                             src_pixel[3]);
-                       dst_pixel[2] = convert_color_channel (src_pixel[0],
-                                                             src_pixel[3]);
-                       dst_pixel[3] = src_pixel[3];
-                       
-                       dst_pixel += 4;
-                       src_pixel += 4;
+       string o;
+       string::size_type const N = s.length ();
+
+       for (string::size_type i = 0; i < N; ++i) {
+               if (s[i] == '_') {
+                       o += "__";
+               } else {
+                       o += s[i];
                }
                }
+       }
+
+       return o;
 }
 }
+
+