Logo Search packages:      
Sourcecode: ardour version File versions  Download package

utils.cc

/*
    Copyright (C) 2003 Paul Davis 

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    $Id: utils.cc,v 1.24 2005/09/08 19:41:51 pauld Exp $
*/

#include <cstdlib>
#include <cctype>
#include <libart_lgpl/art_misc.h>
#include <gtk--/window.h>
#include <gtk--/combo.h>
#include <gtk--/label.h>
#include <gtk--/paned.h>
#include <gtk/gtkpaned.h>

#include <gtkmmext/utils.h>

#include "ardour_ui.h"
#include "utils.h"
#include "i18n.h"
#include "rgb_macros.h"

using namespace std;
using namespace Gtk;

string
short_version (string orig, string::size_type target_length)
{
      /* this tries to create a recognizable abbreviation
         of "orig" by removing characters until we meet
         a certain target length.

         note that we deliberately leave digits in the result
         without modification.
      */


      string::size_type pos;

      /* remove white-space and punctuation, starting at end */

      while (orig.length() > target_length) {
            if ((pos = orig.find_last_of (_("\"\n\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+="))) == string::npos) {
                  break;
            }
            orig.replace (pos, 1, "");
      }

      /* remove lower-case vowels, starting at end */

      while (orig.length() > target_length) {
            if ((pos = orig.find_last_of (_("aeiou"))) == string::npos) {
                  break;
            }
            orig.replace (pos, 1, "");
      }

      /* remove upper-case vowels, starting at end */

      while (orig.length() > target_length) {
            if ((pos = orig.find_last_of (_("AEIOU"))) == string::npos) {
                  break;
            }
            orig.replace (pos, 1, "");
      }

      /* remove lower-case consonants, starting at end */

      while (orig.length() > target_length) {
            if ((pos = orig.find_last_of (_("bcdfghjklmnpqrtvwxyz"))) == string::npos) {
                  break;
            }
            orig.replace (pos, 1, "");
      }

      /* remove upper-case consonants, starting at end */

      while (orig.length() > target_length) {
            if ((pos = orig.find_last_of (_("BCDFGHJKLMNPQRTVWXYZ"))) == string::npos) {
                  break;
            }
            orig.replace (pos, 1, "");
      }

      /* whatever the length is now, use it */
      
      return orig;
}

string
fit_to_pixels (string str, int32_t pixel_width, Gdk_Font& font)
{
      gint width;
      gint lbearing;
      gint rbearing;
      gint ascent;
      gint descent;

      int namelen = str.length();
      char cstr[namelen+1];
      strcpy (cstr, str.c_str());
      
      while (namelen) {
            
            gdk_string_extents (font,
                            cstr,
                            &lbearing,
                            &rbearing,
                            &width,
                            &ascent,
                            &descent);

            if (width < (pixel_width)) {
                  break;
            }

            --namelen;
            cstr[namelen] = '\0';

      }

      return cstr;
}

int
atoi (const string& s)
{
      return atoi (s.c_str());
}

double
atof (const string& s)
{
      return atof (s.c_str());
}

void
strip_whitespace_edges (string& str)
{
      string::size_type i;
      string::size_type len;
      string::size_type s;

      len = str.length();

      for (i = 0; i < len; ++i) {
            if (isgraph (str[i])) {
                  break;
            }
      }

      s = i;

      for (i = len - 1; i >= 0; --i) {
            if (isgraph (str[i])) {
                  break;
            }
      }

      str = str.substr (s, (i - s) + 1);
}

vector<string>
internationalize (const char **array)
{
      vector<string> v;

      for (uint32_t i = 0; array[i]; ++i) {
            v.push_back (_(array[i]));
      }

      return v;
}

gint
just_hide_it (GdkEventAny *ev, Gtk::Window *win)
{
      ARDOUR_UI::instance()->allow_focus (false);
      win->hide_all ();
      return TRUE;
}

void
allow_keyboard_focus (bool yn)
{
      ARDOUR_UI::instance()->allow_focus (yn);
}

/* xpm2rgb copied from nixieclock, which bore the legend:

    nixieclock - a nixie desktop timepiece
    Copyright (C) 2000 Greg Ercolano, erco@3dsite.com

    and was released under the GPL.
*/

unsigned char*
xpm2rgb (const char** xpm, uint32_t& w, uint32_t& h)
{
      static long vals[256], val;
      uint32_t t, x, y, colors, cpp;
      unsigned char c;
      unsigned char *savergb, *rgb;
      
      // PARSE HEADER
      
      if ( sscanf(xpm[0], "%u%u%u%u", &w, &h, &colors, &cpp) != 4 ) {
            error << compose (_("bad XPM header %1"), xpm[0])
                  << endmsg;
            return 0;
      }

      savergb = rgb = (unsigned char*)art_alloc (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;
      }
      
      // COLORMAP -> RGB CONVERSION
      //    Get low 3 bytes from vals[]
      //

      const char *p;
      for (y = h-1; y > 0; --y) {

            for (p = xpm[1+colors+(h-y-1)], x = 0; x < w; x++, rgb += 3) {
                  val = vals[(int)*p++];
                  *(rgb+2) = val & 0xff; val >>= 8;  // 2:B
                  *(rgb+1) = val & 0xff; val >>= 8;  // 1:G
                  *(rgb+0) = val & 0xff;             // 0:R
            }
      }

      return (savergb);
}

unsigned char*
xpm2rgba (const char** xpm, uint32_t& w, uint32_t& h)
{
      static long vals[256], val;
      uint32_t t, x, y, colors, cpp;
      unsigned char c;
      unsigned char *savergb, *rgb;
      char transparent;

      // PARSE HEADER

      if ( sscanf(xpm[0], "%u%u%u%u", &w, &h, &colors, &cpp) != 4 ) {
            error << compose (_("bad XPM header %1"), xpm[0])
                  << endmsg;
            return 0;
      }

      savergb = rgb = (unsigned char*)art_alloc (h * w * 4);
      
      // LOAD XPM COLORMAP LONG ENOUGH TO DO CONVERSION

      if (strstr (xpm[1], "None")) {
            sscanf (xpm[1], "%c", &transparent);
            t = 1;
      } else {
            transparent = 0;
            t = 0;
      }

      for (; t < colors; ++t) {
            sscanf (xpm[t+1], "%c c #%lx", &c, &val);
            vals[c] = val;
      }
      
      // COLORMAP -> RGB CONVERSION
      //    Get low 3 bytes from vals[]
      //

      const char *p;
      for (y = h-1; y > 0; --y) {

            char alpha;

            for (p = xpm[1+colors+(h-y-1)], x = 0; x < w; x++, rgb += 4) {

                  if (transparent && (*p++ == transparent)) {
                        alpha = 0;
                        val = 0;
                  } else {
                        alpha = 255;
                        val = vals[(int)*p];
                  }

                  *(rgb+3) = alpha;                  // 3: alpha
                  *(rgb+2) = val & 0xff; val >>= 8;  // 2:B
                  *(rgb+1) = val & 0xff; val >>= 8;  // 1:G
                  *(rgb+0) = val & 0xff;             // 0:R
            }
      }

      return (savergb);
}

GtkCanvasPoints*
get_canvas_points (string who, uint32_t npoints)
{
      // cerr << who << ": wants " << npoints << " canvas points" << endl;
#ifdef TRAP_EXCESSIVE_POINT_REQUESTS
      if (npoints > (uint32_t) gdk_screen_width() + 4) {
            abort ();
      }
#endif
      return gtk_canvas_points_new (npoints);
}

int
channel_combo_get_channel_count (Gtk::Combo& combo)
{
      string str = combo.get_entry()->get_text();
      int chns;

      if (str == _("mono")) {
            return 1;
      } else if (str == _("stereo")) {
            return 2;
      } else if ((chns = atoi (str)) != 0) {
            return chns;
      } else {
            return 0;
      }
}

static int32_t 
int_from_hex (char hic, char loc) 
{
      int hi;           /* hi byte */
      int lo;           /* low byte */

      hi = (int) hic;

      if( ('0'<=hi) && (hi<='9') ) {
            hi -= '0';
      } else if( ('a'<= hi) && (hi<= 'f') ) {
            hi -= ('a'-10);
      } else if( ('A'<=hi) && (hi<='F') ) {
            hi -= ('A'-10);
      }
      
      lo = (int) loc;
      
      if( ('0'<=lo) && (lo<='9') ) {
            lo -= '0';
      } else if( ('a'<=lo) && (lo<='f') ) {
            lo -= ('a'-10);
      } else if( ('A'<=lo) && (lo<='F') ) {
            lo -= ('A'-10);
      }

      return lo + (16 * hi);
}

void
url_decode (string& url)
{
      string::iterator last;
      string::iterator next;

      for (string::iterator i = url.begin(); i != url.end(); ++i) {
            if ((*i) == '+') {
                  *i = ' ';
            }
      }

      if (url.length() <= 3) {
            return;
      }

      last = url.end();

      --last; /* points at last char */
      --last; /* points at last char - 1 */

      for (string::iterator i = url.begin(); i != last; ) {

            if (*i == '%') {

                  next = i;

                  url.erase (i);
                  
                  i = next;
                  ++next;
                  
                  if (isxdigit (*i) && isxdigit (*next)) {
                        /* replace first digit with char */
                        *i = int_from_hex (*i,*next);
                        ++i; /* points at 2nd of 2 digits */
                        url.erase (i);
                  }
            } else {
                  ++i;
            }
      }
}

string
get_font_for_style (string widgetname)
{
      Gtk::Label foobar;

      foobar.set_name (widgetname);
      foobar.ensure_style();

      if (foobar.get_style() == 0 || foobar.get_style()->gtkobj()->rc_style == 0 || foobar.get_style()->gtkobj()->rc_style->font_name == 0) {
            return "fixed";
      }

      string str = foobar.get_style()->gtkobj()->rc_style->font_name;

      if (str.empty()) {
            return "fixed"; // standard X Window fallback font
      } else {
            return str;
      }
}
gint
pane_handler (GdkEventButton* ev, Gtk::Paned* pane)
{
      if (ev->window != Gtkmmext::get_paned_handle (*pane)) {
            return FALSE;
      }

      if (Keyboard::is_delete_event (ev)) {

            gint pos;
            gint cmp;

            pos = Gtkmmext::gtk_paned_get_position (pane->gtkobj());

            if (dynamic_cast<VPaned*>(pane)) {
                  cmp = pane->height();
            } else {
                  cmp = pane->width();
            }

            /* we have to use approximations here because we can't predict the
               exact position or sizes of the pane (themes, etc)
            */

            if (pos < 10 || abs (pos - cmp) < 10) {

                  /* already collapsed: restore it (note that this is cast from a pointer value to int, which is tricky on 64bit */
                  
                  pane->set_position ((gint64) pane->get_data ("rpos"));

            } else {    

                  int collapse_direction;

                  /* store the current position */

                  pane->set_data ("rpos", (gpointer) pos);

                  /* collapse to show the relevant child in full */
                  
                  collapse_direction = (gint64) pane->get_data ("collapse-direction");

                  if (collapse_direction) {
                        pane->set_position (1);
                  } else {
                        if (dynamic_cast<VPaned*>(pane)) {
                              pane->set_position (pane->height());
                        } else {
                              pane->set_position (pane->width());
                        }
                  }
            }

            return TRUE;
      } 

      return FALSE;
}
uint32_t
rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a)
{
      Gtk::Label foo;
      
      foo.set_name (style);
      foo.ensure_style ();
      
      GtkRcStyle* waverc = foo.get_style()->gtkobj()->rc_style;

      if (waverc) {
            r = waverc->fg[GTK_STATE_NORMAL].red / 257;
            g = waverc->fg[GTK_STATE_NORMAL].green / 257;
            b = waverc->fg[GTK_STATE_NORMAL].blue / 257;

            /* what a hack ... "a" is for "active" */

            a = waverc->fg[GTK_STATE_ACTIVE].red / 257; 

      } else {
            warning << compose (_("missing RGBA style for \"%1\""), style) << endl;
      }
      
      return (uint32_t) RGBA_TO_UINT(r,g,b,a);
}

Generated by  Doxygen 1.6.0   Back to index