+
+bool
+key_is_legal_for_numeric_entry (guint keyval)
+{
+ /* we assume that this does not change over the life of the process
+ */
+
+ static int comma_decimal = -1;
+
+ switch (keyval) {
+ case GDK_period:
+ case GDK_comma:
+ if (comma_decimal < 0) {
+ std::lconv* lc = std::localeconv();
+ if (strchr (lc->decimal_point, ',') != 0) {
+ comma_decimal = 1;
+ } else {
+ comma_decimal = 0;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ switch (keyval) {
+ case GDK_decimalpoint:
+ case GDK_KP_Separator:
+ return true;
+
+ case GDK_period:
+ if (comma_decimal) {
+ return false;
+ } else {
+ return true;
+ }
+ break;
+ case GDK_comma:
+ if (comma_decimal) {
+ return true;
+ } else {
+ return false;
+ }
+ break;
+ case GDK_minus:
+ case GDK_plus:
+ case GDK_0:
+ case GDK_1:
+ case GDK_2:
+ case GDK_3:
+ case GDK_4:
+ case GDK_5:
+ case GDK_6:
+ case GDK_7:
+ case GDK_8:
+ case GDK_9:
+ case GDK_KP_Add:
+ case GDK_KP_Subtract:
+ case GDK_KP_Decimal:
+ case GDK_KP_0:
+ case GDK_KP_1:
+ case GDK_KP_2:
+ case GDK_KP_3:
+ case GDK_KP_4:
+ case GDK_KP_5:
+ case GDK_KP_6:
+ case GDK_KP_7:
+ case GDK_KP_8:
+ case GDK_KP_9:
+ case GDK_Return:
+ case GDK_BackSpace:
+ case GDK_Delete:
+ case GDK_KP_Enter:
+ case GDK_Home:
+ case GDK_End:
+ case GDK_Left:
+ case GDK_Right:
+ return true;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+void
+set_pango_fontsize ()
+{
+ long val = ARDOUR::Config->get_font_scale();
+
+ /* FT2 rendering - used by GnomeCanvas, sigh */
+
+ pango_ft2_font_map_set_resolution ((PangoFT2FontMap*) pango_ft2_font_map_new(), 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);
+}
+
+void
+reset_dpi ()
+{
+ long val = ARDOUR::Config->get_font_scale();
+ set_pango_fontsize ();
+ /* Xft rendering */
+
+ gtk_settings_set_long_property (gtk_settings_get_default(),
+ "gtk-xft-dpi", val, "ardour");
+ DPIReset();//Emit Signal
+}
+
+void
+resize_window_to_proportion_of_monitor (Gtk::Window* window, int max_width, int max_height)
+{
+ Glib::RefPtr<Gdk::Screen> screen = window->get_screen ();
+ Gdk::Rectangle monitor_rect;
+ screen->get_monitor_geometry (0, monitor_rect);
+
+ 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);
+
+ window->resize (w, h);
+}
+
+
+/** Replace _ with __ in a string; for use with menu item text to make underscores displayed correctly */
+string
+escape_underscores (string const & s)
+{
+ 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;
+}
+
+/** Replace < and > with < and > respectively to make < > display correctly in markup strings */
+string
+escape_angled_brackets (string const & s)
+{
+ string o = s;
+ boost::replace_all (o, "<", "<");
+ boost::replace_all (o, ">", ">");
+ return o;
+}
+
+Gdk::Color
+unique_random_color (list<Gdk::Color>& used_colors)
+{
+ Gdk::Color newcolor;
+
+ while (1) {
+
+ /* avoid neon/glowing tones by limiting them to the
+ "inner section" (paler) of a color wheel/circle.
+ */
+
+ const int32_t max_saturation = 48000; // 65535 would open up the whole color wheel
+
+ newcolor.set_red (random() % max_saturation);
+ newcolor.set_blue (random() % max_saturation);
+ newcolor.set_green (random() % max_saturation);
+
+ if (used_colors.size() == 0) {
+ used_colors.push_back (newcolor);
+ return newcolor;
+ }
+
+ for (list<Gdk::Color>::iterator i = used_colors.begin(); i != used_colors.end(); ++i) {
+ Gdk::Color c = *i;
+ float rdelta, bdelta, gdelta;
+
+ rdelta = newcolor.get_red() - c.get_red();
+ bdelta = newcolor.get_blue() - c.get_blue();
+ gdelta = newcolor.get_green() - c.get_green();
+
+ if (sqrt (rdelta*rdelta + bdelta*bdelta + gdelta*gdelta) > 25.0) {
+ used_colors.push_back (newcolor);
+ return newcolor;
+ }
+ }
+
+ /* XXX need throttle here to make sure we don't spin for ever */
+ }
+}