Include a stripped-down version of FLTK in tree and add a USE_INCLUDED_FLTK option to build against it.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4603 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/common/fltk/src/xutf8/utf8Wrap.c b/common/fltk/src/xutf8/utf8Wrap.c
new file mode 100644
index 0000000..1d7f523
--- /dev/null
+++ b/common/fltk/src/xutf8/utf8Wrap.c
@@ -0,0 +1,1049 @@
+/* "$Id: utf8Wrap.c 8401 2011-02-08 10:06:19Z ianmacarthur $"
+ *
+ * Author: Jean-Marc Lienher ( http://oksid.ch )
+ * Copyright 2000-2003 by O'ksi'D.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA.
+ *
+ * Please report all bugs and problems on the following page:
+ *
+ * http://www.fltk.org/str.php
+ */
+
+/*
+ * X11 UTF-8 text drawing functions.
+ */
+#if !defined(WIN32) && !defined(__APPLE__)
+
+#include "../../FL/Xutf8.h"
+#include <X11/Xlib.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+/* External auto generated functions : */
+#include "ucs2fontmap.c"
+/*
+ * extern int ucs2fontmap(char *s, unsigned int ucs, int enc);
+ * extern int encoding_number(const char *enc);
+ * extern const char *encoding_name(int num);
+ */
+
+/* The ARM header files have a bug by not taking into account that ARM cpu
+ * likes pacing to 4 bytes. This little trick defines our own version of
+ * XChar2b which does not have this problem
+ */
+
+#if defined(__GNUC__) && defined(__arm__) && !defined(__ARM_EABI__)
+typedef struct {
+ unsigned char byte1;
+ unsigned char byte2;
+}
+__attribute__ ((packed))
+Fl_XChar2b;
+#else
+#define Fl_XChar2b XChar2b
+#endif
+
+
+/*********************************************************************/
+/** extract a list of font from the base font name list **/
+/*********************************************************************/
+static int
+get_font_list(
+ const char *base_font_name_list,
+ char ***flist) {
+ const char *ptr;
+ const char *p;
+ int nb;
+ int nb_name;
+
+ ptr = base_font_name_list;
+ p = NULL;
+ nb = 0;
+ nb_name = 1;
+
+ while (*ptr) {
+ if (*ptr == ',') nb_name++;
+ ptr++;
+ }
+
+ *flist = (char **) malloc(sizeof(char*) * nb_name);
+ ptr = base_font_name_list;
+
+ while (*ptr) {
+ int l = 0, i = 0;
+
+ while(isspace(*ptr)) ptr++;
+ p = ptr;
+ while (*ptr && *ptr != ',') { ptr++; l++; }
+ if (l > 2) {
+ (*flist)[nb] = (char*) malloc((unsigned)l + 2);
+ while (p != ptr) { ((*flist)[nb])[i] = *p; i++; p++; }
+ (*flist)[nb][i] = '\0';
+ nb++;
+ }
+ if (*ptr) ptr++;
+ }
+ if (nb < 1) {
+ free(*flist);
+ *flist = (char**)NULL;
+ }
+ return nb;
+}
+
+/*********************************************************************/
+/** get the font name used as encoding for "fontspecific" encoding **/
+/** (mainly used for adobe-symbol and adobe-zapfdingbats) **/
+/*********************************************************************/
+static int
+font_spec_enc(char *font) {
+ int ret;
+ char *enc;
+ char *end;
+
+ enc = font;
+ while (*enc != '-') enc++;
+ enc++;
+ while (*enc != '-') enc++;
+ enc++;
+ end = enc;
+ while (*end != '-') end++;
+ *end = '\0';
+
+ ret = encoding_number(enc);
+ *end = '-';
+
+ return ret;
+}
+
+
+/*********************************************************************/
+/** get the sub range of a iso10646-1 font **/
+/*********************************************************************/
+static void
+get_range(const char *enc,
+ int *min,
+ int *max) {
+
+ const char *ptr = enc;
+ const char *ptr1;
+
+ if (!enc) return;
+
+ while (*ptr && *ptr != '-') ptr++;
+ if (!*ptr) return;
+ while (*ptr && *ptr != '[') ptr++;
+ if (!*ptr) return;
+ *min = 0xFFFF;
+ *max = 0;
+ while (*ptr && *ptr != ']') {
+ int val;
+ ptr++;
+ ptr1 = ptr;
+ while (*ptr && *ptr != ']' && *ptr != ' ' && *ptr != '_') ptr++;
+ val = strtol(ptr1, NULL, 0);
+ if (val < *min) *min = val;
+ if (val > *max) *max = val;
+ }
+}
+
+/*********************************************************************/
+/** get the internal encoding number of each fonts **/
+/*********************************************************************/
+static int *
+get_encodings(char **font_name_list,
+ int *ranges,
+ int nb_font) {
+
+ int *font_encoding_list;
+ int i;
+ i = 0;
+
+ font_encoding_list = (int *) malloc(sizeof(int) * nb_font);
+ while (i < nb_font) {
+ char *ptr;
+ int ec;
+ ptr = font_name_list[i];
+ ec = 0;
+ font_encoding_list[i] = -1;
+ ranges[i * 2] = 0;
+ ranges[i * 2 + 1] = 0xFFFF;
+
+ if (ptr && strstr(ptr, "fontspecific")) {
+ font_encoding_list[i] = font_spec_enc(ptr);
+ ptr = NULL;
+ }
+ while (ptr && *ptr) {
+ if (*ptr == '-') {
+ ec++;
+ if (ec == 13) {
+ font_encoding_list[i] = encoding_number(ptr + 1);
+ if (font_encoding_list[i] == 0) {
+ get_range(ptr + 1,
+ ranges + i * 2,
+ ranges + i * 2 + 1);
+ }
+ break;
+ }
+ }
+ ptr++;
+ }
+ if (font_encoding_list[i] < 0) font_encoding_list[i] = 1;
+ i++;
+ }
+ return font_encoding_list;
+}
+
+/*********************************************************************/
+/** find the first font which matches the name and load it. **/
+/*********************************************************************/
+XFontStruct *
+find_best_font(Display *dpy,
+ char **name) {
+
+ char **list;
+ int cnt;
+ XFontStruct *s;
+
+ list = XListFonts(dpy, *name, 1, &cnt);
+ if (cnt && list) {
+ free(*name);
+ *name = strdup(list[0]);
+ s = XLoadQueryFont(dpy, *name);
+ XFreeFontNames(list);
+ return s;
+ }
+ return NULL;
+}
+
+/*********************************************************************/
+/** load all fonts **/
+/*********************************************************************/
+static void
+load_fonts(Display *dpy,
+ XUtf8FontStruct *font_set) {
+
+ int i;
+ char **list;
+
+ i = 0;
+ list = NULL;
+
+ font_set->fonts = (XFontStruct**) malloc(sizeof(XFontStruct*) *
+ font_set->nb_font);
+
+ font_set->ranges = (int*) malloc(sizeof(int) *
+ font_set->nb_font * 2);
+
+ font_set->descent = 0;
+ font_set->ascent = 0;
+ font_set->fid = 0;
+
+ while (i < font_set->nb_font) {
+ XFontStruct *fnt;
+
+ fnt = font_set->fonts[i] =
+ find_best_font(dpy, &(font_set->font_name_list[i]));
+ if (fnt) {
+ font_set->fid = fnt->fid;
+ if (fnt->ascent > font_set->ascent) {
+ font_set->ascent = fnt->ascent;
+ }
+ if (fnt->descent > font_set->descent) {
+ font_set->descent = fnt->descent;
+ }
+ } else {
+ free(font_set->font_name_list[i]);
+ font_set->font_name_list[i] = NULL;
+ }
+ i++;
+ }
+
+ font_set->encodings =
+ get_encodings(font_set->font_name_list,
+ font_set->ranges, font_set->nb_font);
+
+ /* unload fonts with same encoding */
+ for (i = 0; i < font_set->nb_font; i++) {
+ if (font_set->font_name_list[i]) {
+ int j;
+ for (j = 0; j < i; j++) {
+ if (font_set->font_name_list[j] &&
+ font_set->encodings[j] ==
+ font_set->encodings[i] &&
+ font_set->ranges[2*j] ==
+ font_set->ranges[2*i] &&
+ font_set->ranges[(2*j)+1] &&
+ font_set->ranges[(2*i)+1]) {
+ XFreeFont(dpy, font_set->fonts[i]);
+ free(font_set->font_name_list[i]);
+ font_set->font_name_list[i] = NULL;
+ font_set->fonts[i] = 0;
+ }
+ }
+ }
+ }
+}
+
+/*********************************************************************/
+/** Creates an array of XFontStruct acording to the comma separated **/
+/** list of fonts. XLoad all fonts. **/
+/*********************************************************************/
+XUtf8FontStruct *
+XCreateUtf8FontStruct(Display *dpy,
+ const char *base_font_name_list) {
+
+ XUtf8FontStruct *font_set;
+
+ font_set = (XUtf8FontStruct*)malloc(sizeof(XUtf8FontStruct));
+
+ if (!font_set) {
+ return NULL;
+ }
+
+ font_set->nb_font = get_font_list(base_font_name_list,
+ &font_set->font_name_list);
+
+ if (font_set->nb_font < 1) {
+ free(font_set);
+ return NULL;
+ }
+
+ load_fonts(dpy, font_set);
+
+ return font_set;
+}
+
+
+/*****************************************************************************/
+/** draw a Right To Left UTF-8 string using multiple fonts as needed. **/
+/*****************************************************************************/
+void
+XUtf8DrawRtlString(Display *display,
+ Drawable d,
+ XUtf8FontStruct *font_set,
+ GC gc,
+ int x,
+ int y,
+ const char *string,
+ int num_bytes) {
+
+ int *encodings; /* encodings array */
+ XFontStruct **fonts; /* fonts array */
+ Fl_XChar2b buf[128]; /* drawing buffer */
+ Fl_XChar2b *ptr; /* pointer to the drawing buffer */
+ int fnum; /* index of the current font in the fonts array*/
+ int i; /* current byte in the XChar2b buffer */
+ int first; /* first valid font index */
+ int last_fnum; /* font index of the previous char */
+ int nb_font; /* quantity of fonts in the font array */
+ char glyph[2]; /* byte1 and byte2 value of the UTF-8 char */
+ int *ranges; /* sub range of iso10646 */
+
+ nb_font = font_set->nb_font;
+
+ if (nb_font < 1) {
+ /* there is no font in the font_set :-( */
+ return;
+ }
+
+ ranges = font_set->ranges;
+ fonts = font_set->fonts;
+ encodings = font_set->encodings;
+ i = 0;
+ fnum = 0;
+ ptr = buf + 128;
+
+ while(fnum < nb_font && !fonts[fnum]) fnum++;
+ if (fnum >= nb_font) {
+ /* there is no valid font for the X server */
+ return;
+ }
+
+ first = fnum;
+ last_fnum = fnum;
+
+ while (num_bytes > 0) {
+ int ulen; /* byte length of the UTF-8 char */
+ unsigned int ucs; /* Unicode value of the UTF-8 char */
+ unsigned int no_spc; /* Spacing char equivalent of a non-spacing char */
+
+ if (i > 120) {
+ /*** draw the buffer **/
+ XSetFont(display, gc, fonts[fnum]->fid);
+ x -= XTextWidth16(fonts[fnum], ptr, i);
+ XDrawString16(display, d, gc, x, y, ptr, i);
+ i = 0;
+ ptr = buf + 128;
+ }
+
+ ulen = XFastConvertUtf8ToUcs((unsigned char*)string, num_bytes, &ucs);
+
+ if (ulen < 1) ulen = 1;
+
+ no_spc = XUtf8IsNonSpacing(ucs);
+ if (no_spc) ucs = no_spc;
+
+ /*
+ * find the first encoding which can be used to
+ * draw the glyph
+ */
+ fnum = first;
+ while (fnum < nb_font) {
+ if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) {
+ if (encodings[fnum] != 0 ||
+ (ucs >= ranges[fnum * 2] && ucs <= ranges[fnum * 2 + 1])) {
+ break;
+ }
+ }
+ fnum++;
+ }
+ if (fnum == nb_font) {
+ /* the char is not valid in all encodings ->
+ * draw it using the first font :-(
+ */
+ fnum = first;
+ ucs2fontmap(glyph, '?', encodings[fnum]);
+ }
+
+ if (last_fnum != fnum || no_spc) {
+ XSetFont(display, gc, fonts[last_fnum]->fid);
+ x -= XTextWidth16(fonts[last_fnum], ptr, i);
+ XDrawString16(display, d, gc, x, y, ptr, i);
+ i = 0;
+ ptr = buf + 127;
+ (*ptr).byte1 = glyph[0];
+ (*ptr).byte2 = glyph[1];
+ if (no_spc) {
+ x += XTextWidth16(fonts[fnum], ptr, 1);
+ }
+ } else {
+ ptr--;
+ (*ptr).byte1 = glyph[0];
+ (*ptr).byte2 = glyph[1];
+ }
+ last_fnum = fnum;
+ i++;
+ string += ulen;
+ num_bytes -= ulen;
+ }
+
+ if (i < 1) return;
+
+ XSetFont(display, gc, fonts[fnum]->fid);
+ x -= XTextWidth16(fonts[last_fnum], ptr, i);
+ XDrawString16(display, d, gc, x, y, ptr, i);
+}
+
+
+/*****************************************************************************/
+/** draw an UTF-8 string using multiple fonts as needed. **/
+/*****************************************************************************/
+void
+XUtf8DrawString(Display *display,
+ Drawable d,
+ XUtf8FontStruct *font_set,
+ GC gc,
+ int x,
+ int y,
+ const char *string,
+ int num_bytes) {
+
+ int *encodings; /* encodings array */
+ XFontStruct **fonts; /* fonts array */
+ Fl_XChar2b buf[128]; /* drawing buffer */
+ int fnum; /* index of the current font in the fonts array*/
+ int i; /* current byte in the XChar2b buffer */
+ int first; /* first valid font index */
+ int last_fnum; /* font index of the previous char */
+ int nb_font; /* quantity of fonts in the font array */
+ char glyph[2]; /* byte1 and byte2 value of the UTF-8 char */
+ int *ranges; /* sub range of iso10646 */
+
+ nb_font = font_set->nb_font;
+
+ if (nb_font < 1) {
+ /* there is no font in the font_set :-( */
+ return;
+ }
+ ranges = font_set->ranges;
+ fonts = font_set->fonts;
+ encodings = font_set->encodings;
+ i = 0;
+ fnum = 0;
+
+ while(fnum < nb_font && !fonts[fnum]) fnum++;
+ if (fnum >= nb_font) {
+ /* there is no valid font for the X server */
+ return;
+ }
+
+ first = fnum;
+ last_fnum = fnum;
+
+ while (num_bytes > 0) {
+ int ulen; /* byte length of the UTF-8 char */
+ unsigned int ucs; /* Unicode value of the UTF-8 char */
+ unsigned int no_spc; /* Spacing char equivalent of a non-spacing char */
+
+ if (i > 120) {
+ /*** draw the buffer **/
+ XSetFont(display, gc, fonts[fnum]->fid);
+ XDrawString16(display, d, gc, x, y, buf, i);
+ x += XTextWidth16(fonts[fnum], buf, i);
+ i = 0;
+ }
+
+ ulen = XFastConvertUtf8ToUcs((unsigned char*)string, num_bytes, &ucs);
+
+ if (ulen < 1) ulen = 1;
+
+ no_spc = XUtf8IsNonSpacing(ucs);
+ if (no_spc) ucs = no_spc;
+
+ /*
+ * find the first encoding which can be used to
+ * draw the glyph
+ */
+ fnum = first;
+ while (fnum < nb_font) {
+ if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) {
+ if (encodings[fnum] != 0 ||
+ (ucs >= ranges[fnum * 2] &&
+ ucs <= ranges[fnum * 2 + 1])) {
+ break;
+ }
+ }
+ fnum++;
+ }
+ if (fnum == nb_font) {
+ /* the char is not valid in all encodings ->
+ * draw it using the first font :-(
+ */
+ fnum = first;
+ ucs2fontmap(glyph, '?', encodings[fnum]);
+ }
+
+ if (last_fnum != fnum || no_spc) {
+ XSetFont(display, gc, fonts[last_fnum]->fid);
+ XDrawString16(display, d, gc, x, y, buf, i);
+ x += XTextWidth16(fonts[last_fnum], buf, i);
+ i = 0;
+ (*buf).byte1 = glyph[0];
+ (*buf).byte2 = glyph[1];
+ if (no_spc) {
+ x -= XTextWidth16(fonts[fnum], buf, 1);
+ }
+ } else {
+ (*(buf + i)).byte1 = glyph[0];
+ (*(buf + i)).byte2 = glyph[1];
+ }
+ last_fnum = fnum;
+ i++;
+ string += ulen;
+ num_bytes -= ulen;
+ }
+
+ XSetFont(display, gc, fonts[fnum]->fid);
+ XDrawString16(display, d, gc, x, y, buf, i);
+}
+
+
+/*****************************************************************************/
+/** Measure the inked extents of a UTF-8 string using multiple fonts as **/
+/** needed. Tries to mirror the behaviour of the draw function **/
+/** XUtf8DrawString() as closely as possible to get consistent sizes. **/
+/*****************************************************************************/
+void
+XUtf8_measure_extents(
+ Display *display,
+ Drawable d,
+ XUtf8FontStruct *font_set,
+ GC gc,
+ int *xx, /* x-offset from origin */
+ int *yy, /* y-offset from origin */
+ int *ww, /* overall inked width */
+ int *hh, /* maximum inked height */
+ const char *string, /* text to measure */
+ int num_bytes) {
+ int *encodings; /* encodings array */
+ XFontStruct **fonts; /* fonts array */
+ Fl_XChar2b buf[128]; /* drawing buffer */
+ int fnum; /* index of the current font in the fonts array*/
+ int i; /* current byte in the XChar2b buffer */
+ int first; /* first valid font index */
+ int last_fnum; /* font index of the previous char */
+ int nb_font; /* quantity of fonts in the font array */
+ char glyph[2]; /* byte1 and byte2 value of the UTF-8 char */
+ int *ranges; /* sub range of iso10646 */
+
+ int wd = 0; /* accumulates the width of the text */
+ int ht = 0; /* used to find max height in text */
+ int hs; /* "height sum" of current text segment */
+ int yt = 0x7FFFFFFF; /* used to find bounding rectangle delta-y */
+ int res; /* result from calling XTextExtents16() - we should test this is OK! */
+
+ XCharStruct sizes;
+ int dir_ret = 0;
+ int fnt_asc = 0;
+ int fnt_dsc = 0;
+
+ nb_font = font_set->nb_font;
+
+ if (nb_font < 1) {
+ /* there is no font in the font_set :-( */
+ return;
+ }
+ ranges = font_set->ranges;
+ fonts = font_set->fonts;
+ encodings = font_set->encodings;
+ i = 0;
+ fnum = 0;
+
+ while(fnum < nb_font && !fonts[fnum]) fnum++;
+ if (fnum >= nb_font) {
+ /* there is no valid font for the X server */
+ return;
+ }
+
+ first = fnum;
+ last_fnum = fnum;
+
+ while (num_bytes > 0) {
+ int ulen; /* byte length of the UTF-8 char */
+ unsigned int ucs; /* Unicode value of the UTF-8 char */
+ unsigned int no_spc; /* Spacing char equivalent of a non-spacing char */
+
+ if (i > 120) {
+ /*** draw the buffer **/
+ XSetFont(display, gc, fonts[fnum]->fid);
+ res = XTextExtents16(fonts[fnum], buf, i, &dir_ret, &fnt_asc, &fnt_dsc, &sizes);
+ /* recover the dimensions - should verify that res == 0 first! */
+ wd += sizes.width; /* accumulate the width */
+ hs = sizes.ascent + sizes.descent; /* total height */
+ if(hs > ht) ht = hs; /* new height exceeds previous height */
+ if(yt > (-sizes.ascent)) yt = -sizes.ascent; /* delta y offset */
+ i = 0;
+ }
+
+ ulen = XFastConvertUtf8ToUcs((unsigned char*)string, num_bytes, &ucs);
+
+ if (ulen < 1) ulen = 1;
+
+ no_spc = XUtf8IsNonSpacing(ucs);
+ if (no_spc) ucs = no_spc;
+
+ /*
+ * find the first encoding which can be used to
+ * draw the glyph
+ */
+ fnum = first;
+ while (fnum < nb_font) {
+ if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) {
+ if (encodings[fnum] != 0 ||
+ (ucs >= ranges[fnum * 2] &&
+ ucs <= ranges[fnum * 2 + 1])) {
+ break;
+ }
+ }
+ fnum++;
+ }
+ if (fnum == nb_font) {
+ /* the char is not valid in all encodings ->
+ * draw it using the first font :-(
+ */
+ fnum = first;
+ ucs2fontmap(glyph, '?', encodings[fnum]);
+ }
+
+ if (last_fnum != fnum || no_spc) {
+ XSetFont(display, gc, fonts[last_fnum]->fid);
+ res = XTextExtents16(fonts[last_fnum], buf, i, &dir_ret, &fnt_asc, &fnt_dsc, &sizes);
+ /* recover the dimensions - should verify that res == 0 first! */
+ wd += sizes.width; /* accumulate the width */
+ hs = sizes.ascent + sizes.descent; /* total height */
+ if(hs > ht) ht = hs; /* new height exceeds previous height */
+ if(yt > (-sizes.ascent)) yt = -sizes.ascent; /* delta y offset */
+ i = 0;
+ (*buf).byte1 = glyph[0];
+ (*buf).byte2 = glyph[1];
+ if (no_spc) {
+ wd -= XTextWidth16(fonts[fnum], buf, 1);
+ }
+ } else {
+ (*(buf + i)).byte1 = glyph[0];
+ (*(buf + i)).byte2 = glyph[1];
+ }
+ last_fnum = fnum;
+ i++;
+ string += ulen;
+ num_bytes -= ulen;
+ }
+
+ XSetFont(display, gc, fonts[fnum]->fid);
+ res = XTextExtents16(fonts[fnum], buf, i, &dir_ret, &fnt_asc, &fnt_dsc, &sizes);
+ /* recover the dimensions - should verify that res == 0 first! */
+ wd += sizes.width; /* accumulate the width */
+ hs = sizes.ascent + sizes.descent; /* total height */
+ if(hs > ht) ht = hs; /* new height exceeds previous height */
+ if(yt > (-sizes.ascent)) yt = -sizes.ascent; /* delta y offset */
+ /* return values */
+ *ww = wd; /* width of inked area rectangle */
+ *hh = ht; /* max height of inked area rectangle */
+ *xx = 0; /* x-offset from origin to start of inked area - this is wrong! */
+ *yy = yt; /* y-offset from origin to start of inked rectangle */
+}
+
+
+/*****************************************************************************/
+/** returns the pixel width of a UTF-8 string **/
+/*****************************************************************************/
+int
+XUtf8TextWidth(XUtf8FontStruct *font_set,
+ const char *string,
+ int num_bytes) {
+
+ int x;
+ int *encodings; /* encodings array */
+ XFontStruct **fonts; /* fonts array */
+ Fl_XChar2b buf[128]; /* drawing buffer */
+ int fnum; /* index of the current font in the fonts array*/
+ int i; /* current byte in the XChar2b buffer */
+ int first; /* first valid font index */
+ int last_fnum; /* font index of the previous char */
+ int nb_font; /* quantity of fonts in the font array */
+ char glyph[2]; /* byte1 and byte2 value of the UTF-8 char */
+ int *ranges; /* sub range of iso10646 */
+
+ nb_font = font_set->nb_font;
+ x = 0;
+
+ if (nb_font < 1) {
+ /* there is no font in the font_set :-( */
+ return x;
+ }
+
+ ranges = font_set->ranges;
+ fonts = font_set->fonts;
+ encodings = font_set->encodings;
+ i = 0;
+ fnum = 0;
+
+ while(fnum < nb_font && !fonts[fnum]) fnum++;
+ if (fnum >= nb_font) {
+ /* there is no valid font for the X server */
+ return x;
+ }
+
+ first = fnum;
+ last_fnum = fnum;
+
+ while (num_bytes > 0) {
+ int ulen; /* byte length of the UTF-8 char */
+ unsigned int ucs; /* Unicode value of the UTF-8 char */
+ unsigned int no_spc; /* Spacing char equivalent of a non-spacing char */
+
+ if (i > 120) {
+ /*** measure the buffer **/
+ x += XTextWidth16(fonts[fnum], buf, i);
+ i = 0;
+ }
+
+ ulen = XFastConvertUtf8ToUcs((unsigned char*)string, num_bytes, &ucs);
+
+ if (ulen < 1) ulen = 1;
+
+ no_spc = XUtf8IsNonSpacing(ucs);
+ if (no_spc) {
+ ucs = no_spc;
+ }
+
+ /*
+ * find the first encoding which can be used to
+ * draw the glyph
+ */
+ fnum = first;
+ while (fnum < nb_font) {
+ if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) {
+ if (encodings[fnum] != 0 ||
+ (ucs >= ranges[fnum * 2] &&
+ ucs <= ranges[fnum * 2 + 1])) {
+ break;
+ }
+ }
+ fnum++;
+ }
+ if (fnum == nb_font) {
+ /* the char is not valid in all encodings ->
+ * draw it using the first font :-(
+ */
+ fnum = first;
+ ucs2fontmap(glyph, '?', encodings[fnum]);
+ }
+
+ if (last_fnum != fnum || no_spc) {
+ x += XTextWidth16(fonts[last_fnum], buf, i);
+ i = 0;
+ (*buf).byte1 = glyph[0];
+ (*buf).byte2 = glyph[1];
+ if (no_spc) {
+ /* go back to draw the non-spacing char over the previous char */
+ x -= XTextWidth16(fonts[fnum], buf, 1);
+ }
+ } else {
+ (*(buf + i)).byte1 = glyph[0];
+ (*(buf + i)).byte2 = glyph[1];
+ }
+ last_fnum = fnum;
+ i++;
+ string += ulen;
+ num_bytes -= ulen;
+ }
+
+ x += XTextWidth16(fonts[last_fnum], buf, i);
+
+ return x;
+}
+
+/*****************************************************************************/
+/** get the X font and glyph ID of a UCS char **/
+/*****************************************************************************/
+int
+XGetUtf8FontAndGlyph(XUtf8FontStruct *font_set,
+ unsigned int ucs,
+ XFontStruct **fnt,
+ unsigned short *id) {
+
+ int x;
+ int *encodings; /* encodings array */
+ XFontStruct **fonts; /* fonts array */
+ int fnum; /* index of the current font in the fonts array*/
+ int i; /* current byte in the XChar2b buffer */
+ int first; /* first valid font index */
+ int last_fnum; /* font index of the previous char */
+ int nb_font; /* quantity of fonts in the font array */
+ char glyph[2]; /* byte1 and byte2 value of the UTF-8 char */
+ int *ranges; /* sub range of iso10646 */
+
+ nb_font = font_set->nb_font;
+ x = 0;
+
+ if (nb_font < 1) {
+ /* there is no font in the font_set :-( */
+ return -1;
+ }
+
+ ranges = font_set->ranges;
+ fonts = font_set->fonts;
+ encodings = font_set->encodings;
+ i = 0;
+ fnum = 0;
+
+ while(fnum < nb_font && !fonts[fnum]) fnum++;
+ if (fnum >= nb_font) {
+ /* there is no valid font for the X server */
+ return -1;
+ }
+
+ first = fnum;
+ last_fnum = fnum;
+
+ /*
+ * find the first encoding which can be used to
+ * draw the glyph
+ */
+ fnum = first;
+ while (fnum < nb_font) {
+ if (fonts[fnum] && ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) {
+ if (encodings[fnum] != 0 ||
+ (ucs >= ranges[fnum * 2] &&
+ ucs <= ranges[fnum * 2 + 1])) {
+ break;
+ }
+ }
+ fnum++;
+ }
+ if (fnum == nb_font) {
+ /* the char is not valid in all encodings ->
+ * draw it using the first font :-(
+ */
+ fnum = first;
+ ucs2fontmap(glyph, '?', encodings[fnum]);
+ }
+
+ *id = ((unsigned char)glyph[0] << 8) | (unsigned char)glyph[1] ;
+ *fnt = fonts[fnum];
+ return 0;
+}
+
+/*****************************************************************************/
+/** returns the pixel width of a UCS char **/
+/*****************************************************************************/
+int
+XUtf8UcsWidth(XUtf8FontStruct *font_set,
+ unsigned int ucs) {
+
+ int x;
+ int *encodings; /* encodings array */
+ XFontStruct **fonts; /* fonts array */
+ Fl_XChar2b buf[8]; /* drawing buffer */
+ int fnum; /* index of the current font in the fonts array*/
+ int i; /* current byte in the XChar2b buffer */
+ int first; /* first valid font index */
+ int last_fnum; /* font index of the previous char */
+ int nb_font; /* quantity of fonts in the font array */
+ char glyph[2]; /* byte1 and byte2 value of the UTF-8 char */
+ int *ranges; /* sub range of iso10646 */
+
+ nb_font = font_set->nb_font;
+ x = 0;
+
+ if (nb_font < 1) {
+ /* there is no font in the font_set :-( */
+ return x;
+ }
+
+ ranges = font_set->ranges;
+ fonts = font_set->fonts;
+ encodings = font_set->encodings;
+ i = 0;
+ fnum = 0;
+
+ while(fnum < nb_font && !fonts[fnum]) fnum++;
+ if (fnum >= nb_font) {
+ /* there is no valid font for the X server */
+ return x;
+ }
+
+ first = fnum;
+ last_fnum = fnum;
+
+ ucs = XUtf8IsNonSpacing(ucs);
+
+ /*
+ * find the first encoding which can be used to
+ * draw the glyph
+ */
+ fnum = first;
+ while (fnum < nb_font) {
+ if (fonts[fnum] &&
+ ucs2fontmap(glyph, ucs, encodings[fnum]) >= 0) {
+ if (encodings[fnum] != 0 || (ucs >= ranges[fnum * 2] &&
+ ucs <= ranges[fnum * 2 + 1])) {
+ break;
+ }
+ }
+ fnum++;
+ }
+ if (fnum == nb_font) {
+ /* the char is not valid in all encodings ->
+ * draw it using the first font :-(
+ */
+ fnum = first;
+ ucs2fontmap(glyph, '?', encodings[fnum]);
+ }
+
+ (*buf).byte1 = glyph[0];
+ (*buf).byte2 = glyph[1];
+
+ x += XTextWidth16(fonts[fnum], buf, 1);
+
+ return x;
+}
+
+/*****************************************************************************/
+/** draw an UTF-8 string and clear the background. **/
+/*****************************************************************************/
+void
+XUtf8DrawImageString(Display *display,
+ Drawable d,
+ XUtf8FontStruct *font_set,
+ GC gc,
+ int x,
+ int y,
+ const char *string,
+ int num_bytes) {
+
+ /* FIXME: must be improved ! */
+ int w;
+ int fill_style;
+ unsigned long foreground;
+ unsigned long background;
+ int function;
+ XGCValues xgcv;
+
+ w = XUtf8TextWidth(font_set, string, num_bytes);
+
+ XGetGCValues(display, gc,
+ GCFunction|GCForeground|GCBackground|GCFillStyle, &xgcv);
+
+ function = xgcv.function;
+ fill_style = xgcv.fill_style;
+ foreground = xgcv.foreground;
+ background = xgcv.background;
+
+ xgcv.function = GXcopy;
+ xgcv.foreground = background;
+ xgcv.background = foreground;
+ xgcv.fill_style = FillSolid;
+
+ XChangeGC(display, gc,
+ GCFunction|GCForeground|GCBackground|GCFillStyle, &xgcv);
+
+ XFillRectangle(display, d, gc, x, y - font_set->ascent,
+ (unsigned)w, (unsigned)(font_set->ascent + font_set->descent));
+
+ xgcv.function = function;
+ xgcv.foreground = foreground;
+ xgcv.background = background;
+ xgcv.fill_style = fill_style;
+
+ XChangeGC(display, gc,
+ GCFunction|GCForeground|GCBackground|GCFillStyle, &xgcv);
+
+ XUtf8DrawString(display, d, font_set, gc, x, y, string, num_bytes);
+}
+
+/*****************************************************************************/
+/** free the XFontSet and others things created by XCreateUtf8FontSet **/
+/*****************************************************************************/
+void
+XFreeUtf8FontStruct(Display *dpy,
+ XUtf8FontStruct *font_set) {
+
+ int i;
+ i = 0;
+ while (i < font_set->nb_font) {
+ if (font_set->fonts[i]) {
+ XFreeFont(dpy, font_set->fonts[i]);
+ free(font_set->font_name_list[i]);
+ }
+ i++;
+ }
+ free(font_set->ranges);
+ free(font_set->font_name_list);
+ free(font_set->fonts);
+ free(font_set->encodings);
+ free(font_set);
+}
+
+#endif /* X11 only */
+
+/*
+ * End of "$Id: utf8Wrap.c 8401 2011-02-08 10:06:19Z ianmacarthur $".
+ */