#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"); }