fluxbox/src/FbTk/XmbFontImp.cc

299 lines
7.6 KiB
C++
Raw Normal View History

2002-11-26 16:01:28 +00:00
// XmbFontImp.cc for FbTk fluxbox toolkit
2006-02-16 06:53:05 +00:00
// Copyright (c) 2002 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org)
//
2002-11-26 16:01:28 +00:00
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// $Id$
2002-11-26 16:01:28 +00:00
#include "XmbFontImp.hh"
#include "App.hh"
2003-04-26 18:58:30 +00:00
#include "StringUtil.hh"
#include "FbPixmap.hh"
#include "GContext.hh"
2003-02-17 23:36:43 +00:00
2002-11-26 16:01:28 +00:00
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif //HAVE_CONFIG_H
#ifdef HAVE_SETLOCALE
#include <locale.h>
#endif // HAVE_SETLOCALE
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif // _GNU_SOURCE
2004-08-31 15:26:40 +00:00
#ifdef HAVE_CSTDIO
#include <cstdio>
#else
#include <stdio.h>
#endif
#ifdef HAVE_CSTDARG
#include <cstdarg>
#else
#include <stdarg.h>
#endif
2002-11-26 16:01:28 +00:00
#include <iostream>
2004-08-31 15:26:40 +00:00
#ifdef HAVE_CSTRING
#include <cstring>
#else
#include <string.h>
#endif
2002-12-02 19:31:05 +00:00
#include <X11/Xlib.h>
2002-11-26 16:01:28 +00:00
using namespace std;
namespace {
const char *getFontSize(const char *pattern, int *size) {
2002-12-01 13:42:15 +00:00
const char *p;
const char *p2=0;
int n=0;
for (p=pattern; 1; p++) {
if (!*p) {
if (p2!=0 && n>1 && n<72) {
*size = n; return p2+1;
} else {
*size = 16; return 0;
}
} else if (*p=='-') {
if (n>1 && n<72 && p2!=0) {
*size = n;
return p2+1;
}
p2=p; n=0;
} else if (*p>='0' && *p<='9' && p2!=0) {
n *= 10;
n += *p-'0';
} else {
p2=0; n=0;
}
}
2002-11-26 16:01:28 +00:00
}
const char *getFontElement(const char *pattern, char *buf, int bufsiz, ...) {
2002-12-01 13:42:15 +00:00
const char *p, *v;
char *p2;
va_list va;
va_start(va, bufsiz);
buf[bufsiz-1] = 0;
buf[bufsiz-2] = '*';
while((v = va_arg(va, char *)) != 0) {
2003-04-26 18:58:30 +00:00
p = FbTk::StringUtil::strcasestr(pattern, v);
2002-12-01 13:42:15 +00:00
if (p) {
2004-02-10 19:03:42 +00:00
strncpy(buf, p+1, bufsiz-2);
2002-12-01 13:42:15 +00:00
p2 = strchr(buf, '-');
if (p2) *p2=0;
va_end(va);
return p;
}
}
va_end(va);
2004-02-10 19:03:42 +00:00
strncpy(buf, "*", bufsiz);
2002-12-01 13:42:15 +00:00
return 0;
2002-11-26 16:01:28 +00:00
}
XFontSet createFontSet(const char *fontname, bool& utf8mode) {
2002-12-01 13:42:15 +00:00
Display *display = FbTk::App::instance()->display();
XFontSet fs;
char **missing, *def = "-";
2005-12-22 23:39:31 +00:00
int nmissing;
std::string orig_locale = "";
2002-11-26 16:01:28 +00:00
2004-08-28 18:10:19 +00:00
#ifdef HAVE_SETLOCALE
if (utf8mode) {
orig_locale = setlocale(LC_CTYPE, NULL);
setlocale(LC_CTYPE, "UTF-8");
}
#endif // HAVE_SETLOCALE
2002-12-01 13:42:15 +00:00
fs = XCreateFontSet(display,
fontname, &missing, &nmissing, &def);
2004-08-28 18:10:19 +00:00
if (fs && (! nmissing)) {
#ifdef HAVE_SETLOCALE
if (utf8mode)
setlocale(LC_CTYPE, orig_locale.c_str());
2004-08-28 18:10:19 +00:00
#endif // HAVE_SETLOCALE
return fs;
}
2002-11-26 16:01:28 +00:00
#ifdef HAVE_SETLOCALE
2002-12-01 13:42:15 +00:00
if (! fs) {
if (nmissing)
XFreeStringList(missing);
2002-12-01 13:42:15 +00:00
setlocale(LC_CTYPE, "C");
fs = XCreateFontSet(display, fontname,
&missing, &nmissing, &def);
setlocale(LC_CTYPE, orig_locale.c_str());
2002-12-01 13:42:15 +00:00
}
2004-08-28 18:10:19 +00:00
if (utf8mode)
setlocale(LC_CTYPE, orig_locale.c_str());
2004-08-28 18:10:19 +00:00
#endif // HAVE_SETLOCALE
utf8mode = false;
2002-12-01 13:42:15 +00:00
return fs;
2002-11-26 16:01:28 +00:00
}
};
namespace FbTk {
XmbFontImp::XmbFontImp(const char *filename, bool utf8) : m_fontset(0), m_setextents(0), m_utf8mode(utf8) {
2002-12-01 13:42:15 +00:00
if (filename != 0)
load(filename);
2002-11-26 16:01:28 +00:00
}
XmbFontImp::~XmbFontImp() {
2002-12-01 13:42:15 +00:00
if (m_fontset != 0)
XFreeFontSet(App::instance()->display(), m_fontset);
2002-11-26 16:01:28 +00:00
}
bool XmbFontImp::load(const std::string &fontname) {
if (fontname.empty())
2002-12-01 13:42:15 +00:00
return false;
2004-08-28 18:10:19 +00:00
XFontSet set = createFontSet(fontname.c_str(), m_utf8mode);
2002-12-01 13:42:15 +00:00
if (set == 0)
return false;
2004-08-28 18:10:19 +00:00
2002-12-01 13:42:15 +00:00
if (m_fontset != 0)
XFreeFontSet(App::instance()->display(), m_fontset);
2004-08-28 18:10:19 +00:00
2002-12-01 13:42:15 +00:00
m_fontset = set;
m_setextents = XExtentsOfFontSet(m_fontset);
return true;
2002-11-26 16:01:28 +00:00
}
void XmbFontImp::drawText(const FbDrawable &d, int screen, GC main_gc, const char *text,
size_t len, int x, int y, FbTk::Orientation orient) const {
2002-11-26 16:01:28 +00:00
if (m_fontset == 0)
2002-12-01 13:42:15 +00:00
return;
if (orient == ROT0) {
#ifdef X_HAVE_UTF8_STRING
if (m_utf8mode) {
Xutf8DrawString(d.display(), d.drawable(), m_fontset,
main_gc, x, y,
text, len);
} else
#endif //X_HAVE_UTF8_STRING
{
XmbDrawString(d.display(), d.drawable(), m_fontset,
main_gc, x, y,
text, len);
}
return;
}
Display *dpy = App::instance()->display();
Window rootwin = DefaultRootWindow(dpy);
int xpos = x, ypos = y;
unsigned int w = d.width();
unsigned int h = d.height();
translateSize(orient, w, h);
untranslateCoords(orient, xpos, ypos, w, h);
// not straight forward, we actually draw it elsewhere, then rotate it
FbTk::FbPixmap canvas(rootwin, w, h, 1);
// create graphic context for our canvas
FbTk::GContext font_gc(canvas);
font_gc.setBackground(None);
font_gc.setForeground(None);
XFillRectangle(dpy, canvas.drawable(), font_gc.gc(), 0, 0, canvas.width(), canvas.height());
font_gc.setForeground(1);
2002-11-26 16:01:28 +00:00
#ifdef X_HAVE_UTF8_STRING
2002-12-01 13:42:15 +00:00
if (m_utf8mode) {
Xutf8DrawString(dpy, canvas.drawable(), m_fontset,
font_gc.gc(), xpos, ypos,
text, len);
} else
2002-11-26 16:01:28 +00:00
#endif //X_HAVE_UTF8_STRING
{
XmbDrawString(dpy, canvas.drawable(), m_fontset,
font_gc.gc(), xpos, ypos,
text, len);
}
canvas.rotate(orient);
GC my_gc = XCreateGC(dpy, d.drawable(), 0, 0);
XCopyGC(dpy, main_gc, GCForeground|GCBackground, my_gc);
// vertical or upside down
XSetFillStyle(dpy, my_gc, FillStippled);
// vertical or upside down
XSetFillStyle(dpy, my_gc, FillStippled);
XSetStipple(dpy, my_gc, canvas.drawable());
XSetTSOrigin(dpy, my_gc, 0, 0);
XFillRectangle(dpy, d.drawable(), my_gc, 0, 0,
canvas.width(),
canvas.height());
XFreeGC(dpy, my_gc);
2002-11-26 16:01:28 +00:00
}
unsigned int XmbFontImp::textWidth(const char * const text, unsigned int len) const {
2002-12-01 13:42:15 +00:00
if (m_fontset == 0)
return 0;
2002-12-01 13:42:15 +00:00
XRectangle ink, logical;
2002-11-26 16:01:28 +00:00
#ifdef X_HAVE_UTF8_STRING
2002-12-01 13:42:15 +00:00
if (m_utf8mode) {
Xutf8TextExtents(m_fontset, text, len,
&ink, &logical);
if (logical.width != 0)
return logical.width;
}
2002-11-26 16:01:28 +00:00
#endif // X_HAVE_UTF8_STRING
XmbTextExtents(m_fontset, text, len,
&ink, &logical);
2002-12-01 13:42:15 +00:00
return logical.width;
2002-11-26 16:01:28 +00:00
}
unsigned int XmbFontImp::height() const {
2002-12-01 13:42:15 +00:00
if (m_fontset == 0)
return 0;
return m_setextents->max_ink_extent.height;
2002-11-26 16:01:28 +00:00
}
}; // end namespace FbTk