libotk_a_SOURCES= color.cc display.cc font.cc gccache.cc image.cc property.cc \
imagecontrol.cc rect.cc screeninfo.cc texture.cc timer.cc \
- timerqueuemanager.cc
+ timerqueuemanager.cc style.cc configuration.cc util.cc
MAINTAINERCLEANFILES= Makefile.in
gccache.o: gccache.cc gccache.hh display.hh color.hh assassin.hh \
screeninfo.hh rect.hh
rect.o: rect.cc rect.hh
+configuration.o: configuration.cc configuration.hh
+style.o: style.cc style.hh
+util.o: util.cc util.hh
\ No newline at end of file
--- /dev/null
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif // HAVE_CONFIG_H
+
+extern "C" {
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif // HAVE_STDLIB_H
+}
+
+#include "configuration.hh"
+#include "util.hh"
+
+#include <algorithm>
+
+namespace otk {
+
+bool Configuration::_initialized = False;
+
+Configuration::Configuration(const std::string &file, bool autosave) {
+ setFile(file);
+ _modified = False;
+ _database = NULL;
+ _autosave = autosave;
+ if (! _initialized) {
+ XrmInitialize();
+ _initialized = True;
+ }
+}
+
+Configuration::Configuration(bool autosave) {
+ _modified = False;
+ _database = NULL;
+ _autosave = autosave;
+ if (! _initialized) {
+ XrmInitialize();
+ _initialized = True;
+ }
+}
+
+Configuration::~Configuration() {
+ if (_database != NULL)
+ XrmDestroyDatabase(_database);
+}
+
+void Configuration::setFile(const std::string &file) {
+ _file = file;
+}
+
+void Configuration::setAutoSave(bool autosave) {
+ _autosave = autosave;
+}
+
+void Configuration::save() {
+ assert(_database != NULL);
+ XrmPutFileDatabase(_database, _file.c_str());
+ _modified = False;
+}
+
+bool Configuration::load() {
+ if (_database != NULL)
+ XrmDestroyDatabase(_database);
+ _modified = False;
+ if (NULL == (_database = XrmGetFileDatabase(_file.c_str())))
+ return False;
+ return True;
+}
+
+bool Configuration::merge(const std::string &file, bool overwrite) {
+ if (XrmCombineFileDatabase(file.c_str(), &_database, overwrite) == 0)
+ return False;
+ _modified = True;
+ if (_autosave)
+ save();
+ return True;
+}
+
+void Configuration::create() {
+ if (_database != NULL)
+ XrmDestroyDatabase(_database);
+ _modified = False;
+ assert(NULL != (_database = XrmGetStringDatabase("")));
+}
+
+void Configuration::setValue(const std::string &rname, bool value) {
+ assert(_database != NULL);
+
+ const char *val = (value ? "True" : "False");
+ std::string rc_string = rname + ": " + val;
+ XrmPutLineResource(&_database, rc_string.c_str());
+
+ _modified = True;
+ if (_autosave)
+ save();
+}
+
+void Configuration::setValue(const std::string &rname, unsigned long value) {
+ assert(_database != NULL);
+
+ std::string rc_string = rname + ": " + itostring(value);
+ XrmPutLineResource(&_database, rc_string.c_str());
+
+ _modified = True;
+ if (_autosave)
+ save();
+}
+
+void Configuration::setValue(const std::string &rname, long value) {
+ assert(_database != NULL);
+
+ std::string rc_string = rname + ": " + itostring(value);
+ XrmPutLineResource(&_database, rc_string.c_str());
+
+ _modified = True;
+ if (_autosave)
+ save();
+}
+
+void Configuration::setValue(const std::string &rname, const char *value) {
+ assert(_database != NULL);
+ assert(value != NULL);
+
+ std::string rc_string = rname + ": " + value;
+ XrmPutLineResource(&_database, rc_string.c_str());
+
+ _modified = True;
+ if (_autosave)
+ save();
+}
+
+void Configuration::setValue(const std::string &rname,
+ const std::string &value) {
+ assert(_database != NULL);
+
+ std::string rc_string = rname + ": " + value;
+ XrmPutLineResource(&_database, rc_string.c_str());
+
+ _modified = True;
+ if (_autosave)
+ save();
+}
+
+bool Configuration::getValue(const std::string &rname, bool &value) const {
+ assert(_database != NULL);
+
+ std::string rclass = createClassName(rname);
+
+ char *rettype;
+ XrmValue retvalue;
+ if (0 == XrmGetResource(_database, rname.c_str(), rclass.c_str(),
+ &rettype, &retvalue) || retvalue.addr == NULL)
+ return False;
+ std::string val = retvalue.addr;
+ if (val == "True" || val == "True")
+ value = True;
+ else
+ value = False;
+ return True;
+}
+
+bool Configuration::getValue(const std::string &rname, long &value) const {
+ assert(_database != NULL);
+
+ std::string rclass = createClassName(rname);
+
+ char *rettype;
+ XrmValue retvalue;
+ if (0 == XrmGetResource(_database, rname.c_str(), rclass.c_str(),
+ &rettype, &retvalue) || retvalue.addr == NULL)
+ return False;
+ char *end;
+ value = strtol(retvalue.addr, &end, 10);
+ if (end == retvalue.addr)
+ return False;
+ return True;
+}
+
+bool Configuration::getValue(const std::string &rname, unsigned long &value) const {
+ assert(_database != NULL);
+
+ std::string rclass = createClassName(rname);
+
+ char *rettype;
+ XrmValue retvalue;
+ if (0 == XrmGetResource(_database, rname.c_str(), rclass.c_str(),
+ &rettype, &retvalue) || retvalue.addr == NULL)
+ return False;
+ char *end;
+ value = strtoul(retvalue.addr, &end, 10);
+ if (end == retvalue.addr)
+ return False;
+ return True;
+}
+
+bool Configuration::getValue(const std::string &rname,
+ std::string &value) const {
+ assert(_database != NULL);
+
+ std::string rclass = createClassName(rname);
+
+ char *rettype;
+ XrmValue retvalue;
+ if (0 == XrmGetResource(_database, rname.c_str(), rclass.c_str(),
+ &rettype, &retvalue) || retvalue.addr == NULL)
+ return False;
+ value = retvalue.addr;
+ return True;
+}
+
+
+std::string Configuration::createClassName(const std::string &rname) const {
+ std::string rclass(rname);
+
+ std::string::iterator it = rclass.begin(), end = rclass.end();
+ while (True) {
+ *it = toUpper(*it);
+ ++it;
+ if (it == end) break;
+ it = std::find(it, rclass.end(), '.');
+ if (it == end) break;
+ ++it;
+ if (it == end) break;
+ }
+ return rclass;
+}
+
+
+char Configuration::toUpper(char c) const {
+ if (c >= 'a' && c <= 'z')
+ return c - 'a' + 'A';
+ return c;
+}
+
+}
--- /dev/null
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+#ifndef __configuration_hh
+#define __configuration_hh
+
+/*! @file configuration.hh
+ @brief Loads, saves, and provides configuration options for the window
+ manager
+*/
+
+extern "C" {
+#include <X11/Xlib.h>
+#include <X11/Xresource.h>
+}
+
+#include <string>
+
+namespace otk {
+
+/*
+ * The Configuration class is a generic wrapper for configuration settings.
+ *
+ * This class is used for the global rc/config file, and for styles.
+ *
+ * This implementation of the Configuration class wraps an X resource database
+ * file.
+ */
+class Configuration {
+public:
+ explicit Configuration(const std::string &file, bool autosave = True);
+ Configuration(bool autosave = True);
+ virtual ~Configuration();
+
+ inline const std::string &file() const {
+ return static_cast<const std::string &>(_file);
+ }
+ void setFile(const std::string &file);
+
+ // defaults to true!
+ inline bool autoSave() const {
+ return _autosave;
+ }
+ void setAutoSave(bool);
+
+ inline bool isModified() const {
+ return _modified;
+ }
+
+ void save();
+ bool load();
+ bool merge(const std::string &file, bool overwrite = False);
+ void create();
+
+ void setValue(const std::string &rname, bool value);
+ inline void setValue(const std::string &rname, int value) {
+ setValue(rname, (long) value);
+ }
+ inline void setValue(const std::string &rname, unsigned int value) {
+ setValue(rname, (unsigned long) value);
+ }
+ void setValue(const std::string &rname, long value);
+ void setValue(const std::string &rname, unsigned long value);
+ void setValue(const std::string &rname, const std::string &value);
+ void setValue(const std::string &rname, const char *value);
+
+ bool getValue(const std::string &rname, bool &value) const;
+ inline bool getValue(const std::string &rname, int &value) const {
+ return getValue(rname, (long) value);
+ }
+ inline bool getValue(const std::string &rname, unsigned int &value) const {
+ return getValue(rname, (unsigned long) value);
+ }
+ bool getValue(const std::string &rname, long &value) const;
+ bool getValue(const std::string &rname, unsigned long &value) const;
+ bool getValue(const std::string &rname, std::string &value) const;
+
+private:
+ std::string createClassName(const std::string &rname) const;
+ char toUpper(char) const;
+
+ static bool _initialized;
+ std::string _file;
+ bool _modified;
+ bool _autosave;
+ XrmDatabase _database;
+};
+
+}
+
+#endif // __configuration_hh
#include "screeninfo.hh"
#include "display.hh"
-#include "src/util.hh"
+#include "util.hh"
using std::string;
default_string.resize(pos);
display_string = string("DISPLAY=") + default_string + '.' +
- ob::itostring(static_cast<unsigned long>(screen_number));
+ otk::itostring(static_cast<unsigned long>(screen_number));
#ifdef XINERAMA
xinerama_active = False;
--- /dev/null
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif // HAVE_CONFIG_H
+
+#include <assert.h>
+#include "display.hh"
+
+#include "util.hh"
+#include "style.hh"
+
+namespace otk {
+
+Style::Style()
+{
+ fprintf(stderr, "new font class used");
+}
+
+Style::Style(unsigned int screen) : screen_number(screen)
+{
+}
+
+Style::Style(unsigned int screen, otk::BImageControl *ctrl)
+ : image_control(ctrl), screen_number(screen)
+{
+}
+
+Style::~Style() {
+ if (font)
+ delete font;
+
+ if (close_button.mask != None)
+ XFreePixmap(otk::OBDisplay::display, close_button.mask);
+ if (max_button.mask != None)
+ XFreePixmap(otk::OBDisplay::display, max_button.mask);
+ if (icon_button.mask != None)
+ XFreePixmap(otk::OBDisplay::display, icon_button.mask);
+ if (stick_button.mask != None)
+ XFreePixmap(otk::OBDisplay::display, stick_button.mask);
+
+ max_button.mask = None;
+ close_button.mask = None;
+ icon_button.mask = None;
+ stick_button.mask = None;
+}
+
+void Style::load(otk::Configuration &style) {
+ std::string s;
+
+ // load fonts/fontsets
+ if (font)
+ delete font;
+
+ font = readDatabaseFont("window.", style);
+
+ // load window config
+ t_focus = readDatabaseTexture("window.title.focus", "white", style);
+ t_unfocus = readDatabaseTexture("window.title.unfocus", "black", style);
+
+ l_focus = readDatabaseTexture("window.label.focus", "white", style);
+ l_unfocus = readDatabaseTexture("window.label.unfocus", "black", style);
+
+ h_focus = readDatabaseTexture("window.handle.focus", "white", style);
+ h_unfocus = readDatabaseTexture("window.handle.unfocus", "black", style);
+
+ g_focus = readDatabaseTexture("window.grip.focus", "white", style);
+ g_unfocus = readDatabaseTexture("window.grip.unfocus", "black", style);
+
+ b_focus = readDatabaseTexture("window.button.focus", "white", style);
+ b_unfocus = readDatabaseTexture("window.button.unfocus", "black", style);
+ b_pressed = readDatabaseTexture("window.button.pressed", "black", style);
+
+ //if neither of these can be found, we will use the previous resource
+ b_pressed_focus = readDatabaseTexture("window.button.pressed.focus",
+ "black", style, true);
+ b_pressed_unfocus = readDatabaseTexture("window.button.pressed.unfocus",
+ "black", style, true);
+
+ if (close_button.mask != None)
+ XFreePixmap(otk::OBDisplay::display, close_button.mask);
+ if (max_button.mask != None)
+ XFreePixmap(otk::OBDisplay::display, max_button.mask);
+ if (icon_button.mask != None)
+ XFreePixmap(otk::OBDisplay::display, icon_button.mask);
+ if (stick_button.mask != None)
+ XFreePixmap(otk::OBDisplay::display, stick_button.mask);
+
+ close_button.mask = max_button.mask = icon_button.mask
+ = icon_button.mask = None;
+
+ readDatabaseMask("window.button.close.mask", close_button, style);
+ readDatabaseMask("window.button.max.mask", max_button, style);
+ readDatabaseMask("window.button.icon.mask", icon_button, style);
+ readDatabaseMask("window.button.stick.mask", stick_button, style);
+
+ // we create the window.frame texture by hand because it exists only to
+ // make the code cleaner and is not actually used for display
+ otk::BColor color = readDatabaseColor("window.frame.focusColor", "white",
+ style);
+ f_focus = otk::BTexture("solid flat", screen_number, image_control);
+ f_focus.setColor(color);
+
+ color = readDatabaseColor("window.frame.unfocusColor", "white", style);
+ f_unfocus = otk::BTexture("solid flat", screen_number, image_control);
+ f_unfocus.setColor(color);
+
+ l_text_focus = readDatabaseColor("window.label.focus.textColor",
+ "black", style);
+ l_text_unfocus = readDatabaseColor("window.label.unfocus.textColor",
+ "white", style);
+
+ b_pic_focus = readDatabaseColor("window.button.focus.picColor",
+ "black", style);
+ b_pic_unfocus = readDatabaseColor("window.button.unfocus.picColor",
+ "white", style);
+
+ justify = LeftJustify;
+
+ if (style.getValue("window.justify", s)) {
+ if (s == "right" || s == "Right")
+ justify = RightJustify;
+ else if (s == "center" || s == "Center")
+ justify = CenterJustify;
+ }
+
+ // sanity checks
+ if (t_focus.texture() == otk::BTexture::Parent_Relative)
+ t_focus = f_focus;
+ if (t_unfocus.texture() == otk::BTexture::Parent_Relative)
+ t_unfocus = f_unfocus;
+ if (h_focus.texture() == otk::BTexture::Parent_Relative)
+ h_focus = f_focus;
+ if (h_unfocus.texture() == otk::BTexture::Parent_Relative)
+ h_unfocus = f_unfocus;
+
+ border_color = readDatabaseColor("borderColor", "black", style);
+
+ // load bevel, border and handle widths
+
+ const otk::ScreenInfo *s_info = otk::OBDisplay::screenInfo(screen_number);
+ unsigned int width = s_info->getRect().width();
+
+ if (! style.getValue("handleWidth", handle_width) ||
+ handle_width > width/2 || handle_width == 0)
+ handle_width = 6;
+
+ if (! style.getValue("borderWidth", border_width))
+ border_width = 1;
+
+ if (! style.getValue("bevelWidth", bevel_width)
+ || bevel_width > width/2 || bevel_width == 0)
+ bevel_width = 3;
+
+ if (! style.getValue("frameWidth", frame_width)
+ || frame_width > width/2)
+ frame_width = bevel_width;
+
+ if (style.getValue("rootCommand", s))
+ bexec(s, s_info->displayString());
+}
+
+
+void Style::doJustify(const std::string &text, int &start_pos,
+ unsigned int max_length,
+ unsigned int modifier) const {
+ size_t text_len = text.size();
+ unsigned int length;
+
+ do {
+ length = font->measureString(std::string(text, 0, text_len)) + modifier;
+ } while (length > max_length && text_len-- > 0);
+
+ switch (justify) {
+ case RightJustify:
+ start_pos += max_length - length;
+ break;
+
+ case CenterJustify:
+ start_pos += (max_length - length) / 2;
+ break;
+
+ case LeftJustify:
+ default:
+ break;
+ }
+}
+
+
+void Style::readDatabaseMask(const std::string &rname, PixmapMask &pixmapMask,
+ const otk::Configuration &style) {
+ Window root_window = otk::OBDisplay::screenInfo(screen_number)->getRootWindow();
+ std::string s;
+ int hx, hy; //ignored
+ int ret = BitmapOpenFailed; //default to failure.
+
+ if (style.getValue(rname, s))
+ {
+ if (s[0] != '/' && s[0] != '~')
+ {
+ std::string xbmFile = std::string("~/.openbox/buttons/") + s;
+ ret = XReadBitmapFile(otk::OBDisplay::display, root_window,
+ expandTilde(xbmFile).c_str(), &pixmapMask.w,
+ &pixmapMask.h, &pixmapMask.mask, &hx, &hy);
+ } else
+ ret = XReadBitmapFile(otk::OBDisplay::display, root_window,
+ expandTilde(s).c_str(), &pixmapMask.w,
+ &pixmapMask.h, &pixmapMask.mask, &hx, &hy);
+
+ if (ret == BitmapSuccess)
+ return;
+ }
+
+ pixmapMask.mask = None;
+ pixmapMask.w = pixmapMask.h = 0;
+}
+
+
+otk::BTexture Style::readDatabaseTexture(const std::string &rname,
+ const std::string &default_color,
+ const otk::Configuration &style,
+ bool allowNoTexture)
+{
+ otk::BTexture texture;
+ std::string s;
+
+ if (style.getValue(rname, s))
+ texture = otk::BTexture(s);
+ else if (allowNoTexture) //no default
+ texture.setTexture(otk::BTexture::NoTexture);
+ else
+ texture.setTexture(otk::BTexture::Solid | otk::BTexture::Flat);
+
+ // associate this texture with this screen
+ texture.setScreen(screen_number);
+ texture.setImageControl(image_control);
+
+ if (texture.texture() != otk::BTexture::NoTexture) {
+ texture.setColor(readDatabaseColor(rname + ".color", default_color,
+ style));
+ texture.setColorTo(readDatabaseColor(rname + ".colorTo", default_color,
+ style));
+ texture.setBorderColor(readDatabaseColor(rname + ".borderColor",
+ default_color, style));
+ }
+
+ return texture;
+}
+
+
+otk::BColor Style::readDatabaseColor(const std::string &rname,
+ const std::string &default_color,
+ const otk::Configuration &style) {
+ otk::BColor color;
+ std::string s;
+ if (style.getValue(rname, s))
+ color = otk::BColor(s, screen_number);
+ else
+ color = otk::BColor(default_color, screen_number);
+ return color;
+}
+
+
+otk::BFont *Style::readDatabaseFont(const std::string &rbasename,
+ const otk::Configuration &style) {
+ std::string fontname;
+
+ std::string s;
+
+ int i;
+ if (style.getValue(rbasename + "xft.font", s) &&
+ style.getValue(rbasename + "xft.size", i)) {
+ std::string family = s;
+ bool bold = False;
+ bool italic = False;
+ bool dropShadow = False;
+
+ if (style.getValue(rbasename + "xft.flags", s)) {
+ if (s.find("bold") != std::string::npos)
+ bold = True;
+ if (s.find("italic") != std::string::npos)
+ italic = True;
+ if (s.find("shadow") != std::string::npos)
+ dropShadow = True;
+ }
+
+ unsigned char offset = 1;
+ if (style.getValue(rbasename + "xft.shadow.offset", s)) {
+ offset = atoi(s.c_str()); //doesn't detect errors
+ if (offset > CHAR_MAX)
+ offset = 1;
+ }
+
+ unsigned char tint = 0x40;
+ if (style.getValue(rbasename + "xft.shadow.tint", s)) {
+ tint = atoi(s.c_str());
+ }
+
+
+ otk::BFont *b = new otk::BFont(screen_number, family, i, bold, italic,
+ dropShadow && shadow_fonts,
+ offset, tint, aa_fonts);
+ if (b->valid())
+ return b;
+ delete b;
+ }
+
+ exit(2); // can't continue without a font
+}
+
+}
--- /dev/null
+#ifndef __style_hh
+#define __style_hh
+
+#include <string>
+
+#include "color.hh"
+#include "font.hh"
+#include "texture.hh"
+#include "image.hh"
+#include "configuration.hh"
+
+// XXX: document
+
+namespace otk {
+
+class Style {
+public:
+
+ enum TextJustify { LeftJustify = 1, RightJustify, CenterJustify };
+ enum BulletType { RoundBullet = 1, TriangleBullet, SquareBullet, NoBullet };
+
+ struct PixmapMask {
+ Pixmap mask;
+ unsigned int w, h;
+ };
+
+// private:
+
+ otk::BImageControl *image_control;
+
+ otk::BColor
+ l_text_focus, l_text_unfocus,
+ b_pic_focus, b_pic_unfocus;
+
+ otk::BColor border_color;
+
+ otk::BFont *font;
+
+ otk::BTexture
+ f_focus, f_unfocus,
+ t_focus, t_unfocus,
+ l_focus, l_unfocus,
+ h_focus, h_unfocus,
+ b_focus, b_unfocus,
+ b_pressed, b_pressed_focus, b_pressed_unfocus,
+ g_focus, g_unfocus;
+
+ PixmapMask close_button, max_button, icon_button, stick_button;
+ TextJustify justify;
+
+ unsigned int handle_width, bevel_width, frame_width, border_width;
+
+ unsigned int screen_number;
+
+ bool shadow_fonts, aa_fonts;
+
+public:
+
+ Style();
+ Style(unsigned int);
+ Style(unsigned int, otk::BImageControl *);
+ ~Style();
+
+ void doJustify(const std::string &text, int &start_pos,
+ unsigned int max_length, unsigned int modifier) const;
+
+ void readDatabaseMask(const std::string &rname,
+ PixmapMask &pixmapMask,
+ const otk::Configuration &style);
+
+ otk::BTexture readDatabaseTexture(const std::string &rname,
+ const std::string &default_color,
+ const otk::Configuration &style,
+ bool allowNoTexture = false);
+
+ otk::BColor readDatabaseColor(const std::string &rname,
+ const std::string &default_color,
+ const otk::Configuration &style);
+
+ otk::BFont *readDatabaseFont(const std::string &rbasename,
+ const otk::Configuration &style);
+
+ void load(otk::Configuration &);
+
+ inline unsigned int getHandleWidth(void) const { return handle_width; }
+ inline unsigned int getBevelWidth(void) const { return bevel_width; }
+ inline unsigned int getFrameWidth(void) const { return frame_width; }
+ inline unsigned int getBorderWidth(void) const { return border_width; }
+
+ inline void setImageControl(otk::BImageControl *c) { image_control = c; }
+ inline void setScreenNumber(unsigned int scr) { screen_number = scr; }
+
+ // XXX add inline accessors for the rest of the bummy
+};
+
+}
+
+#endif // __style_hh
--- /dev/null
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+
+#ifdef HAVE_CONFIG_H
+# include "../config.h"
+#endif // HAVE_CONFIG_H
+
+extern "C" {
+#include <X11/Xatom.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif // HAVE_UNISTD_H
+
+#if defined(HAVE_PROCESS_H) && defined(__EMX__)
+# include <process.h>
+#endif // HAVE_PROCESS_H __EMX__
+
+#include <assert.h>
+}
+
+#include <algorithm>
+
+#include "util.hh"
+
+using std::string;
+
+namespace otk {
+
+string expandTilde(const string& s) {
+ if (s[0] != '~') return s;
+
+ const char* const home = getenv("HOME");
+ if (home == NULL) return s;
+
+ return string(home + s.substr(s.find('/')));
+}
+
+
+void bexec(const string& command, const string& displaystring) {
+#ifndef __EMX__
+ if (! fork()) {
+ setsid();
+ int ret = putenv(const_cast<char *>(displaystring.c_str()));
+ assert(ret != -1);
+ ret = execl("/bin/sh", "/bin/sh", "-c", command.c_str(), NULL);
+ exit(ret);
+ }
+#else // __EMX__
+ spawnlp(P_NOWAIT, "cmd.exe", "cmd.exe", "/c", command.c_str(), NULL);
+#endif // !__EMX__
+}
+
+
+string textPropertyToString(Display *display, XTextProperty& text_prop) {
+ string ret;
+
+ if (text_prop.value && text_prop.nitems > 0) {
+ if (text_prop.encoding == XA_STRING) {
+ ret = (char *) text_prop.value;
+ } else {
+ text_prop.nitems = strlen((char *) text_prop.value);
+
+ char **list;
+ int num;
+ if (XmbTextPropertyToTextList(display, &text_prop,
+ &list, &num) == Success &&
+ num > 0 && *list) {
+ ret = *list;
+ XFreeStringList(list);
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+string itostring(unsigned long i) {
+ if (i == 0)
+ return string("0");
+
+ string tmp;
+ for (; i > 0; i /= 10)
+ tmp.insert(tmp.begin(), "0123456789"[i%10]);
+ return tmp;
+}
+
+
+string itostring(long i) {
+ std::string tmp = itostring( (unsigned long) std::abs(i));
+ if (i < 0)
+ tmp.insert(tmp.begin(), '-');
+ return tmp;
+}
+
+}
+
+#ifndef HAVE_BASENAME
+string basename (const string& path) {
+ string::size_type slash = path.rfind('/');
+ if (slash == string::npos)
+ return path;
+ return path.substr(slash+1);
+}
+#endif // HAVE_BASENAME
+
--- /dev/null
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+#ifndef _BLACKBOX_UTIL_HH
+#define _BLACKBOX_UTIL_HH
+
+extern "C" {
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else // !TIME_WITH_SYS_TIME
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else // !HAVE_SYS_TIME_H
+# include <time.h>
+# endif // HAVE_SYS_TIME_H
+#endif // TIME_WITH_SYS_TIME
+}
+
+
+#include <string>
+#include <vector>
+
+namespace otk {
+
+/* XXX: this needs autoconf help */
+const unsigned int BSENTINEL = 65535;
+
+std::string expandTilde(const std::string& s);
+
+void bexec(const std::string& command, const std::string& displaystring);
+
+std::string textPropertyToString(Display *display, XTextProperty& text_prop);
+
+std::string itostring(unsigned long i);
+std::string itostring(long i);
+inline std::string itostring(unsigned int i)
+ { return itostring((unsigned long) i); }
+inline std::string itostring(int i)
+ { return itostring((long) i); }
+
+}
+
+#ifndef HAVE_BASENAME
+std::string basename(const std::string& path);
+#endif
+
+#endif