704 lines
16 KiB
C
704 lines
16 KiB
C
/*
|
|
* Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
|
|
* Copyright (C) 2004-2022 Kim Woelders
|
|
*
|
|
* 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 of the Software, its documentation and marketing & publicity
|
|
* materials, and acknowledgment shall be given in the documentation, materials
|
|
* and software packages that this Software was used.
|
|
*
|
|
* 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 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.
|
|
*/
|
|
#include "config.h"
|
|
|
|
#include "E.h"
|
|
#include "eimage.h"
|
|
#include "tclass.h"
|
|
#include "xwin.h"
|
|
|
|
static void
|
|
TextDrawRotTo(Win win, EX_Drawable src, EX_Drawable dst, int x, int y,
|
|
int w, int h, TextState * ts)
|
|
{
|
|
EImage *im;
|
|
int win_w;
|
|
|
|
switch (ts->style.orientation)
|
|
{
|
|
case FONT_TO_UP:
|
|
im = EImageGrabDrawable(src, 0, y, x, h, w, 0);
|
|
EImageOrientate(im, 1);
|
|
EImageRenderOnDrawable(im, win, dst, 0, 0, 0, w, h);
|
|
EImageFree(im);
|
|
break;
|
|
case FONT_TO_DOWN:
|
|
EXGetSize(src, &win_w, NULL);
|
|
im = EImageGrabDrawable(src, NoXID, win_w - y - h, x, h, w, 0);
|
|
EImageOrientate(im, 3);
|
|
EImageRenderOnDrawable(im, win, dst, 0, 0, 0, w, h);
|
|
EImageFree(im);
|
|
break;
|
|
case FONT_TO_LEFT: /* Holy carumba! That's for yoga addicts, maybe .... */
|
|
im = EImageGrabDrawable(src, NoXID, x, y, w, h, 0);
|
|
EImageOrientate(im, 2);
|
|
EImageRenderOnDrawable(im, win, dst, 0, 0, 0, w, h);
|
|
EImageFree(im);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
TextDrawRotBack(Win win, EX_Drawable dst, EX_Drawable src, int x, int y,
|
|
int w, int h, TextState * ts)
|
|
{
|
|
EImage *im;
|
|
int win_w;
|
|
|
|
switch (ts->style.orientation)
|
|
{
|
|
case FONT_TO_UP:
|
|
im = EImageGrabDrawable(src, NoXID, 0, 0, w, h, 0);
|
|
EImageOrientate(im, 3);
|
|
EImageRenderOnDrawable(im, win, dst, 0, y, x, h, w);
|
|
EImageFree(im);
|
|
break;
|
|
case FONT_TO_DOWN:
|
|
EXGetSize(dst, &win_w, NULL);
|
|
im = EImageGrabDrawable(src, NoXID, 0, 0, w, h, 0);
|
|
EImageOrientate(im, 1);
|
|
EImageRenderOnDrawable(im, win, dst, 0, win_w - y - h, x, h, w);
|
|
EImageFree(im);
|
|
break;
|
|
case FONT_TO_LEFT: /* Holy carumba! That's for yoga addicts, maybe .... */
|
|
im = EImageGrabDrawable(src, NoXID, 0, 0, w, h, 0);
|
|
EImageOrientate(im, 2);
|
|
EImageRenderOnDrawable(im, win, dst, 0, x, y, w, h);
|
|
EImageFree(im);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if FONT_TYPE_IFT
|
|
static EImage *
|
|
TextImageGet(Win win __UNUSED__, EX_Drawable src, int x, int y, int w, int h,
|
|
TextState * ts)
|
|
{
|
|
EImage *im;
|
|
int win_w;
|
|
|
|
switch (ts->style.orientation)
|
|
{
|
|
default:
|
|
case FONT_TO_RIGHT:
|
|
im = EImageGrabDrawable(src, NoXID, x, y, w, h, 0);
|
|
break;
|
|
case FONT_TO_LEFT:
|
|
im = EImageGrabDrawable(src, NoXID, x, y, w, h, 0);
|
|
EImageOrientate(im, 2);
|
|
break;
|
|
case FONT_TO_UP:
|
|
im = EImageGrabDrawable(src, 0, y, x, h, w, 0);
|
|
EImageOrientate(im, 1);
|
|
break;
|
|
case FONT_TO_DOWN:
|
|
EXGetSize(src, &win_w, NULL);
|
|
im = EImageGrabDrawable(src, NoXID, win_w - y - h, x, h, w, 0);
|
|
EImageOrientate(im, 3);
|
|
break;
|
|
}
|
|
|
|
return im;
|
|
}
|
|
|
|
static void
|
|
TextImagePut(EImage * im, Win win, EX_Drawable dst, int x, int y,
|
|
int w, int h, TextState * ts)
|
|
{
|
|
int win_w;
|
|
|
|
switch (ts->style.orientation)
|
|
{
|
|
default:
|
|
case FONT_TO_RIGHT:
|
|
EImageRenderOnDrawable(im, win, dst, 0, x, y, w, h);
|
|
break;
|
|
case FONT_TO_LEFT:
|
|
EImageOrientate(im, 2);
|
|
EImageRenderOnDrawable(im, win, dst, 0, x, y, w, h);
|
|
break;
|
|
case FONT_TO_UP:
|
|
EImageOrientate(im, 3);
|
|
EImageRenderOnDrawable(im, win, dst, 0, y, x, h, w);
|
|
break;
|
|
case FONT_TO_DOWN:
|
|
EXGetSize(dst, &win_w, NULL);
|
|
EImageOrientate(im, 1);
|
|
EImageRenderOnDrawable(im, win, dst, 0, win_w - y - h, x, h, w);
|
|
break;
|
|
}
|
|
EImageFree(im);
|
|
}
|
|
#endif /* FONT_TYPE_IFT */
|
|
|
|
TextState *
|
|
TextclassGetTextState(TextClass * tclass, int state, int active, int sticky)
|
|
{
|
|
if (!tclass)
|
|
return NULL;
|
|
|
|
if (active)
|
|
{
|
|
if (!sticky)
|
|
{
|
|
switch (state)
|
|
{
|
|
case STATE_NORMAL:
|
|
return tclass->active.normal;
|
|
case STATE_HILITED:
|
|
return tclass->active.hilited;
|
|
case STATE_CLICKED:
|
|
return tclass->active.clicked;
|
|
case STATE_DISABLED:
|
|
return tclass->active.disabled;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (state)
|
|
{
|
|
case STATE_NORMAL:
|
|
return tclass->sticky_active.normal;
|
|
case STATE_HILITED:
|
|
return tclass->sticky_active.hilited;
|
|
case STATE_CLICKED:
|
|
return tclass->sticky_active.clicked;
|
|
case STATE_DISABLED:
|
|
return tclass->sticky_active.disabled;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
else if (sticky)
|
|
{
|
|
switch (state)
|
|
{
|
|
case STATE_NORMAL:
|
|
return tclass->sticky.normal;
|
|
case STATE_HILITED:
|
|
return tclass->sticky.hilited;
|
|
case STATE_CLICKED:
|
|
return tclass->sticky.clicked;
|
|
case STATE_DISABLED:
|
|
return tclass->sticky.disabled;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (state)
|
|
{
|
|
case STATE_NORMAL:
|
|
return tclass->norm.normal;
|
|
case STATE_HILITED:
|
|
return tclass->norm.hilited;
|
|
case STATE_CLICKED:
|
|
return tclass->norm.clicked;
|
|
case STATE_DISABLED:
|
|
return tclass->norm.disabled;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
TextstateTextFit1(TextState * ts, char **ptext, int *pw, int textwidth_limit)
|
|
{
|
|
char *text = *ptext;
|
|
int hh, ascent;
|
|
char *new_line;
|
|
int nuke_count = 0, nc2;
|
|
int len;
|
|
|
|
len = strlen(text);
|
|
if (len <= 1)
|
|
return;
|
|
new_line = EMALLOC(char, len + 10);
|
|
if (!new_line)
|
|
return;
|
|
|
|
while (*pw > textwidth_limit)
|
|
{
|
|
nuke_count++;
|
|
|
|
if (nuke_count >= len - 1)
|
|
{
|
|
new_line[0] = text[0];
|
|
memcpy(new_line + 1, "...", 4);
|
|
break;
|
|
}
|
|
|
|
nc2 = (len - nuke_count) / 2;
|
|
memcpy(new_line, text, nc2);
|
|
memcpy(new_line + nc2, "...", 3);
|
|
strcpy(new_line + nc2 + 3, text + nc2 + nuke_count);
|
|
|
|
ts->ops->TextSize(ts, new_line, 0, pw, &hh, &ascent);
|
|
}
|
|
|
|
Efree(text);
|
|
*ptext = new_line;
|
|
}
|
|
|
|
static void
|
|
TextstateTextFitMB(TextState * ts, char **ptext, int *pw, int textwidth_limit)
|
|
{
|
|
char *text = *ptext;
|
|
int hh, ascent;
|
|
char *new_line;
|
|
int nuke_count = 0, nc2;
|
|
int len;
|
|
wchar_t *wc_line = NULL;
|
|
int wc_len;
|
|
|
|
if (EwcOpen(ts->need_utf8 || Mode.locale.utf8_int))
|
|
return;
|
|
|
|
len = strlen(text);
|
|
wc_len = EwcStrToWcs(text, len, NULL, 0);
|
|
if (wc_len <= 1)
|
|
goto done;
|
|
|
|
wc_line = EMALLOC(wchar_t, wc_len + 1);
|
|
if (!wc_line)
|
|
goto done;
|
|
|
|
if (EwcStrToWcs(text, len, wc_line, wc_len) <= 0)
|
|
goto done;
|
|
|
|
new_line = EMALLOC(char, len + 10);
|
|
|
|
if (!new_line)
|
|
goto done;
|
|
|
|
while (*pw > textwidth_limit)
|
|
{
|
|
int len_mb;
|
|
|
|
nuke_count++;
|
|
if (nuke_count >= wc_len - 1)
|
|
{
|
|
int mlen;
|
|
|
|
mlen = EwcWcsToStr(wc_line, 1, new_line, MB_CUR_MAX);
|
|
if (mlen < 0)
|
|
mlen = 1;
|
|
|
|
strcpy(new_line + mlen, "...");
|
|
break;
|
|
}
|
|
|
|
nc2 = (wc_len - nuke_count) / 2;
|
|
len_mb = EwcWcsToStr(wc_line, nc2, new_line, len + 10);
|
|
memcpy(new_line + len_mb, "...", 3);
|
|
len_mb += 3;
|
|
len_mb += EwcWcsToStr(wc_line + nc2 + nuke_count,
|
|
wc_len - nc2 - nuke_count,
|
|
new_line + len_mb, len + 10 - len_mb);
|
|
new_line[len_mb] = '\0';
|
|
|
|
ts->ops->TextSize(ts, new_line, 0, pw, &hh, &ascent);
|
|
}
|
|
Efree(text);
|
|
*ptext = new_line;
|
|
done:
|
|
Efree(wc_line);
|
|
EwcClose();
|
|
}
|
|
|
|
static void
|
|
TsTextDraw(TextState * ts, int x, int y, const char *text, int len)
|
|
{
|
|
if (ts->style.effect == 1)
|
|
{
|
|
ts->ops->FdcSetColor(ts, ts->bg_col);
|
|
ts->ops->TextDraw(ts, x + 1, y + 1, text, len);
|
|
}
|
|
else if (ts->style.effect == 2)
|
|
{
|
|
ts->ops->FdcSetColor(ts, ts->bg_col);
|
|
ts->ops->TextDraw(ts, x - 1, y, text, len);
|
|
ts->ops->TextDraw(ts, x + 1, y, text, len);
|
|
ts->ops->TextDraw(ts, x, y - 1, text, len);
|
|
ts->ops->TextDraw(ts, x, y + 1, text, len);
|
|
}
|
|
ts->ops->FdcSetColor(ts, ts->fg_col);
|
|
ts->ops->TextDraw(ts, x, y, text, len);
|
|
}
|
|
|
|
typedef struct {
|
|
const char *type;
|
|
const FontOps *ops;
|
|
#if USE_MODULES
|
|
char checked;
|
|
#endif
|
|
} FontHandler;
|
|
|
|
#if FONT_TYPE_XFS
|
|
extern const FontOps FontOps_xfs;
|
|
#endif
|
|
|
|
#if USE_MODULES
|
|
|
|
#define FONT(type, ops, opsm) { type, opsm, 0 }
|
|
|
|
#else
|
|
|
|
#define FONT(type, ops, opsm) { type, ops }
|
|
|
|
#if FONT_TYPE_IFT
|
|
extern const FontOps FontOps_ift;
|
|
#endif
|
|
#if FONT_TYPE_XFT
|
|
extern const FontOps FontOps_xft;
|
|
#endif
|
|
#if FONT_TYPE_PANGO_XFT
|
|
extern const FontOps FontOps_pango;
|
|
#endif
|
|
|
|
#endif /* USE_MODULES */
|
|
|
|
static FontHandler fhs[] = {
|
|
#if FONT_TYPE_XFS
|
|
FONT("xfs", &FontOps_xfs, &FontOps_xfs), /* XFontSet - XCreateFontSet */
|
|
#endif
|
|
#if FONT_TYPE_IFT
|
|
FONT("ift", &FontOps_ift, NULL), /* Imlib2/FreeType */
|
|
#endif
|
|
#if FONT_TYPE_XFT
|
|
FONT("xft", &FontOps_xft, NULL), /* Xft */
|
|
#endif
|
|
#if FONT_TYPE_PANGO_XFT
|
|
FONT("pango", &FontOps_pango, NULL), /* Pango-Xft */
|
|
#endif
|
|
FONT(NULL, NULL, NULL)
|
|
};
|
|
|
|
static void
|
|
TextStateLoadFont(TextState * ts)
|
|
{
|
|
const char *s, *type, *name;
|
|
char buf[1024];
|
|
FontHandler *fhp = fhs;
|
|
|
|
if (!ts->fontname)
|
|
return;
|
|
|
|
/* Quit if already done */
|
|
if (ts->type)
|
|
return;
|
|
|
|
ts->need_utf8 = Mode.locale.utf8_int;
|
|
|
|
type = NULL;
|
|
name = ts->fontname;
|
|
#if FONT_TYPE_IFT
|
|
if (strchr(ts->fontname, '/'))
|
|
{
|
|
type = "ift";
|
|
goto check;
|
|
}
|
|
#endif
|
|
#if FONT_TYPE_XFS
|
|
if (ts->fontname[0] == '-')
|
|
{
|
|
type = "xfs";
|
|
goto check;
|
|
}
|
|
#endif
|
|
s = strchr(ts->fontname, ':');
|
|
if (!s || s == ts->fontname)
|
|
goto fallback;
|
|
if (s - ts->fontname > 16)
|
|
goto fallback;
|
|
memcpy(buf, ts->fontname, s - ts->fontname);
|
|
buf[s - ts->fontname] = '\0';
|
|
type = buf;
|
|
name = s + 1;
|
|
|
|
check:
|
|
for (fhp = fhs; fhp->type; fhp++)
|
|
{
|
|
if (strcmp(fhp->type, type))
|
|
continue;
|
|
#if USE_MODULES
|
|
if (!fhp->ops)
|
|
{
|
|
if (fhp->checked)
|
|
goto fallback;
|
|
fhp->checked = 1;
|
|
fhp->ops = ModLoadSym("font", "FontOps", type);
|
|
if (!fhp->ops)
|
|
goto fallback;
|
|
}
|
|
#endif
|
|
if (fhp->ops->Load(ts, name) == 0)
|
|
goto done;
|
|
}
|
|
fallback:
|
|
#if FONT_TYPE_XFS
|
|
if (!FontOps_xfs.Load(ts, "fixed")) /* XFontSet - XCreateFontSet */
|
|
goto done;
|
|
#endif
|
|
|
|
done:
|
|
if (!ts->ops)
|
|
Eprintf("*** Unable to load font \"%s\"\n", ts->fontname);
|
|
else if (EDebug(EDBUG_TYPE_FONTS))
|
|
Eprintf("%s: %s: type=%d\n", __func__, ts->fontname, ts->type);
|
|
return;
|
|
}
|
|
|
|
void
|
|
TextSize(TextClass * tclass, int active, int sticky, int state,
|
|
const char *text, int *width, int *height, int fsize __UNUSED__)
|
|
{
|
|
const char *str;
|
|
char **lines;
|
|
int i, num_lines, ww, hh, asc;
|
|
TextState *ts;
|
|
|
|
*width = 0;
|
|
*height = 0;
|
|
|
|
if (!text)
|
|
return;
|
|
|
|
ts = TextclassGetTextState(tclass, state, active, sticky);
|
|
if (!ts)
|
|
return;
|
|
|
|
TextStateLoadFont(ts);
|
|
if (!ts->ops)
|
|
return;
|
|
|
|
/* Do encoding conversion, if necessary */
|
|
str = EstrInt2Enc(text, ts->need_utf8);
|
|
lines = StrlistFromString(str, '\n', &num_lines);
|
|
EstrInt2EncFree(str, ts->need_utf8);
|
|
if (!lines)
|
|
return;
|
|
|
|
for (i = 0; i < num_lines; i++)
|
|
{
|
|
ts->ops->TextSize(ts, lines[i], strlen(lines[i]), &ww, &hh, &asc);
|
|
*height += hh;
|
|
if (ww > *width)
|
|
*width = ww;
|
|
}
|
|
|
|
StrlistFree(lines, num_lines);
|
|
}
|
|
|
|
__EXPORT__ void
|
|
TextstateTextFit(TextState * ts, char **ptext, int *pw, int textwidth_limit)
|
|
{
|
|
if (ts->need_utf8 || MB_CUR_MAX > 1)
|
|
TextstateTextFitMB(ts, ptext, pw, textwidth_limit);
|
|
else
|
|
TextstateTextFit1(ts, ptext, pw, textwidth_limit);
|
|
}
|
|
|
|
void
|
|
TextstateTextDraw(TextState * ts, Win win, EX_Drawable draw,
|
|
const char *text, int x, int y, int w, int h,
|
|
const EImageBorder * pad, int fsize __UNUSED__, int justh,
|
|
int justv)
|
|
{
|
|
const char *str;
|
|
char **lines;
|
|
int i, num_lines;
|
|
int textwidth_limit, textheight_limit, offset_x, offset_y;
|
|
int xx, yy, ww, hh, ascent;
|
|
EX_Pixmap drawable;
|
|
|
|
if (w <= 0 || h <= 0)
|
|
return;
|
|
|
|
TextStateLoadFont(ts);
|
|
if (!ts->ops)
|
|
return;
|
|
|
|
/* Do encoding conversion, if necessary */
|
|
str = EstrInt2Enc(text, ts->need_utf8);
|
|
lines = StrlistFromString(str, '\n', &num_lines);
|
|
EstrInt2EncFree(str, ts->need_utf8);
|
|
if (!lines)
|
|
return;
|
|
|
|
if (draw == NoXID)
|
|
draw = WinGetXwin(win);
|
|
|
|
if (ts->style.orientation == FONT_TO_RIGHT ||
|
|
ts->style.orientation == FONT_TO_LEFT)
|
|
{
|
|
if (pad)
|
|
{
|
|
x += pad->left;
|
|
w -= pad->left + pad->right;
|
|
y += pad->top;
|
|
h -= pad->top + pad->bottom;
|
|
}
|
|
textwidth_limit = w;
|
|
textheight_limit = h;
|
|
}
|
|
else
|
|
{
|
|
if (pad)
|
|
{
|
|
x += pad->left;
|
|
h -= pad->left + pad->right;
|
|
y += pad->top;
|
|
w -= pad->top + pad->bottom;
|
|
}
|
|
textwidth_limit = h;
|
|
textheight_limit = w;
|
|
}
|
|
|
|
#if 0
|
|
Eprintf("%s: %d,%d %dx%d(%dx%d): %s\n", __func__, x, y, w, h,
|
|
textwidth_limit, textheight_limit, text);
|
|
#endif
|
|
|
|
yy = y;
|
|
|
|
if (ts->ops->FdcInit(ts, win, draw))
|
|
return;
|
|
|
|
#if FONT_TYPE_IFT
|
|
if (ts->type == FONT_TYPE_IFT)
|
|
{
|
|
for (i = 0; i < num_lines; i++)
|
|
{
|
|
EImage *im;
|
|
|
|
ts->ops->TextSize(ts, lines[i], 0, &ww, &hh, &ascent);
|
|
if (ww > textwidth_limit)
|
|
ts->ops->TextFit(ts, &lines[i], &ww, textwidth_limit);
|
|
|
|
if (justv && num_lines == 1 && textheight_limit > 0)
|
|
yy += (textheight_limit - hh) / 2;
|
|
if (i == 0)
|
|
yy += ascent;
|
|
xx = x + (((textwidth_limit - ww) * justh) >> 10);
|
|
|
|
im = TextImageGet(win, draw, xx - 1, yy - 1 - ascent,
|
|
ww + 2, hh + 2, ts);
|
|
if (!im)
|
|
break;
|
|
|
|
offset_x = 1;
|
|
offset_y = ascent + 1;
|
|
|
|
ts->ops->FdcSetDrawable(ts, (unsigned long)im);
|
|
|
|
TsTextDraw(ts, offset_x, offset_y, lines[i], strlen(lines[i]));
|
|
|
|
TextImagePut(im, win, draw, xx - 1, yy - 1 - ascent,
|
|
ww + 2, hh + 2, ts);
|
|
|
|
yy += hh;
|
|
}
|
|
}
|
|
else
|
|
#endif /* FONT_TYPE_IFT */
|
|
{
|
|
for (i = 0; i < num_lines; i++)
|
|
{
|
|
ts->ops->TextSize(ts, lines[i], 0, &ww, &hh, &ascent);
|
|
if (ww > textwidth_limit)
|
|
ts->ops->TextFit(ts, &lines[i], &ww, textwidth_limit);
|
|
|
|
if (justv && num_lines == 1 && textheight_limit > 0)
|
|
yy += (textheight_limit - hh) / 2;
|
|
if (i == 0)
|
|
yy += ascent;
|
|
xx = x + (((textwidth_limit - ww) * justh) >> 10);
|
|
|
|
if (ts->style.orientation != FONT_TO_RIGHT)
|
|
drawable = ECreatePixmap(win, ww + 2, hh + 2, 0);
|
|
else
|
|
drawable = draw;
|
|
TextDrawRotTo(win, draw, drawable, xx - 1, yy - 1 - ascent,
|
|
ww + 2, hh + 2, ts);
|
|
|
|
if (ts->style.orientation == FONT_TO_RIGHT)
|
|
{
|
|
offset_x = xx;
|
|
offset_y = yy;
|
|
}
|
|
else
|
|
{
|
|
offset_x = 1;
|
|
offset_y = ascent + 1;
|
|
}
|
|
|
|
if (drawable != draw)
|
|
ts->ops->FdcSetDrawable(ts, drawable);
|
|
|
|
TsTextDraw(ts, offset_x, offset_y, lines[i], strlen(lines[i]));
|
|
|
|
TextDrawRotBack(win, draw, drawable, xx - 1, yy - 1 - ascent,
|
|
ww + 2, hh + 2, ts);
|
|
if (drawable != draw)
|
|
EFreePixmap(drawable);
|
|
|
|
yy += hh;
|
|
}
|
|
}
|
|
|
|
if (ts->ops->FdcFini)
|
|
ts->ops->FdcFini(ts);
|
|
|
|
StrlistFree(lines, num_lines);
|
|
}
|
|
|
|
void
|
|
TextDraw(TextClass * tclass, Win win, EX_Drawable draw, int active,
|
|
int sticky, int state, const char *text, int x, int y, int w, int h,
|
|
int fsize, int justh)
|
|
{
|
|
TextState *ts;
|
|
|
|
if (!tclass || !text)
|
|
return;
|
|
|
|
ts = TextclassGetTextState(tclass, state, active, sticky);
|
|
if (!ts)
|
|
return;
|
|
|
|
TextstateTextDraw(ts, win, draw, text, x, y, w, h, NULL, fsize, justh, 0);
|
|
}
|