scx/c/xlib/text.c

181 lines
4.9 KiB
C

#include "xlib.h"
extern XDrawText(), XDrawText16();
static s48_value Sym_1byte, Sym_2byte;
static Two_Byte (format) s48_value format; {
Check_Type (format, T_Symbol);
if (S48_EQ_P(format, Sym_1byte))
return 0;
else if (S48_EQ_P(format, Sym_2byte))
return 1;
Primitive_Error ("index format must be '1-byte or '2-byte");
/*NOTREACHED*/
}
static Get_1_Byte_Char (x) s48_value x; {
register c = (int)s48_extract_integer (x);
if (c < 0 || c > 255)
Range_Error (x);
return c;
}
static Get_2_Byte_Char (x) s48_value x; {
register c = (int)s48_extract_integer (x);
if (c < 0 || c > 65535)
Range_Error (x);
return c;
}
/* Calculation of text widths and extents should not be done using
* the Xlib functions. For instance, the values returned by
* XTextExtents() are only shorts and can therefore overflow for
* long strings.
*/
static s48_value Internal_Text_Metrics (font, t, f, width) s48_value font, t, f; {
char *s;
XChar2b *s2;
XFontStruct *info;
s48_value *data;
register i, n;
int dir, fasc, fdesc;
Alloca_Begin;
Check_Type (font, T_Font);
info = FONT(font)->info;
Check_Type (t, T_Vector);
n = S48_VECTOR_LENGTH(t);
data = VECTOR(t)->data;
if (Two_Byte (f)) {
Alloca (s2, XChar2b*, n * sizeof (XChar2b));
for (i = 0; i < n; i++) {
register c = Get_2_Byte_Char (data[i]);
s2[i].byte1 = (c >> 8) & 0xff;
s2[i].byte2 = c & 0xff;
}
if (width)
i = XTextWidth16 (info, s2, n);
else
XTextExtents16 (info, s2, n, &dir, &fasc, &fdesc, &CI);
} else {
Alloca (s, char*, n);
for (i = 0; i < n; i++)
s[i] = Get_1_Byte_Char (data[i]);
if (width)
i = XTextWidth (info, s, n);
else
XTextExtents (info, s, n, &dir, &fasc, &fdesc, &CI);
}
Alloca_End;
return width ? s48_enter_integer (i) : Record_To_Vector (Char_Info_Rec,
Char_Info_Size, Sym_Char_Info, FONT(font)->dpy, ~0L);
}
static s48_value P_Text_Width (font, t, f) s48_value font, t, f; {
return Internal_Text_Metrics (font, t, f, 1);
}
static s48_value P_Text_Extents (font, t, f) s48_value font, t, f; {
return Internal_Text_Metrics (font, t, f, 0);
}
static s48_value P_Draw_Image_Text (d, gc, x, y, t, f) s48_value d, gc, x, y, t, f; {
Display *dpy;
Drawable dr = Get_Drawable (d, &dpy);
s48_value *data;
register i, n;
char *s;
XChar2b *s2;
Alloca_Begin;
Check_Type (gc, T_Gc);
Check_Type (t, T_Vector);
n = S48_VECTOR_LENGTH(t);
data = VECTOR(t)->data;
if (Two_Byte (f)) {
Alloca (s2, XChar2b*, n * sizeof (XChar2b));
for (i = 0; i < n; i++) {
register c = Get_2_Byte_Char (data[i]);
s2[i].byte1 = (c >> 8) & 0xff;
s2[i].byte2 = c & 0xff;
}
XDrawImageString16 (dpy, dr, GCONTEXT(gc)->gc, (int)s48_extract_integer (x),
(int)s48_extract_integer (y), s2, n);
} else {
Alloca (s, char*, n);
for (i = 0; i < n; i++)
s[i] = Get_1_Byte_Char (data[i]);
XDrawImageString (dpy, dr, GCONTEXT(gc)->gc, (int)s48_extract_integer (x),
(int)s48_extract_integer (y), s, n);
}
Alloca_End;
return Void;
}
static s48_value P_Draw_Poly_Text (d, gc, x, y, t, f) s48_value d, gc, x, y, t, f; {
Display *dpy;
Drawable dr = Get_Drawable (d, &dpy);
s48_value *data;
register i, n, j, k;
int twobyte, nitems;
XTextItem *items;
int (*func)();
Alloca_Begin;
Check_Type (gc, T_Gc);
twobyte = Two_Byte (f);
func = twobyte ? (int(*)())XDrawText16 : (int(*)())XDrawText;
Check_Type (t, T_Vector);
if ((n = S48_VECTOR_LENGTH(t)) == 0)
return Void;
for (data = VECTOR(t)->data, i = 0, nitems = 1; i < n; i++)
if (TYPE(data[i]) == T_Font) nitems++;
Alloca (items, XTextItem*, nitems * sizeof (XTextItem));
items[0].delta = 0;
items[0].font = None;
for (j = k = i = 0; i <= n; i++) {
if (i == n || TYPE(data[i]) == T_Font) {
items[j].nchars = i-k;
if (twobyte) {
register XChar2b *p;
Alloca (p, XChar2b*, (i-k) * sizeof (XChar2b));
((XTextItem16 *)items)[j].chars = p;
for ( ; k < i; k++, p++) {
register c = Get_2_Byte_Char (data[k]);
p->byte1 = (c >> 8) & 0xff;
p->byte2 = c & 0xff;
}
} else {
register char *p;
Alloca (p, char*, i-k);
items[j].chars = p;
for ( ; k < i; k++)
*p++ = Get_1_Byte_Char (data[k]);
}
k++;
j++;
if (i < n) {
items[j].delta = 0;
Open_Font_Maybe (data[i]);
items[j].font = FONT(data[i])->id;
}
}
}
(*func)(dpy, dr, GCONTEXT(gc)->gc, (int)s48_extract_integer (x), (int)s48_extract_integer (y),
items, nitems);
Alloca_End;
return Void;
}
elk_init_xlib_text () {
Define_Primitive (P_Text_Width, "text-width", 3, 3, EVAL);
Define_Primitive (P_Text_Extents, "xlib-text-extents", 3, 3, EVAL);
Define_Primitive (P_Draw_Image_Text, "draw-image-text", 6, 6, EVAL);
Define_Primitive (P_Draw_Poly_Text, "draw-poly-text", 6, 6, EVAL);
Define_Symbol (&Sym_1byte, "1-byte");
Define_Symbol (&Sym_2byte, "2-byte");
}