/* text.c * * $Id$ * * Copyright 1990, 1991, 1992, 1993, 1994, 1995, Oliver Laumann, Berlin * Copyright 2002, 2003 Sam Hocevar , Paris * * This software was derived from Elk 1.2, which was Copyright 1987, 1988, * 1989, Nixdorf Computer AG and TELES GmbH, Berlin (Elk 1.2 has been written * by Oliver Laumann for TELES Telematic Services, Berlin, in a joint project * between TELES and Nixdorf Microprocessor Engineering, Berlin). * * Oliver Laumann, TELES GmbH, Nixdorf Computer AG and Sam Hocevar, as co- * owners or individual owners of copyright in this software, grant to any * person or company a worldwide, royalty free, license to * * i) copy this software, * ii) prepare derivative works based on this software, * iii) distribute copies of this software or derivative works, * iv) perform this software, or * v) display this software, * * provided that this notice is not removed and that neither Oliver Laumann * nor Teles nor Nixdorf are deemed to have made any representations as to * the suitability of this software for any purpose nor are held responsible * for any defects of this software. * * THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ #include "xlib.h" extern int XDrawText(), XDrawText16(); static Object Sym_1byte, Sym_2byte; static int Two_Byte (Object format) { Check_Type (format, T_Symbol); if (EQ(format, Sym_1byte)) return 0; else if (EQ(format, Sym_2byte)) return 1; Primitive_Error ("index format must be '1-byte or '2-byte"); /*NOTREACHED*/ return 0; } static int Get_1_Byte_Char (Object x) { register int c = Get_Integer (x); if (c < 0 || c > 255) Range_Error (x); return c; } static int Get_2_Byte_Char (Object x) { register int c = Get_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 Object Internal_Text_Metrics (Object font, Object t, Object f, int width) { char *s; XChar2b *s2; XFontStruct *info; Object *data; register int i, n; int dir, fasc, fdesc; Alloca_Begin; Check_Type (font, T_Font); info = FONT(font)->info; Check_Type (t, T_Vector); n = VECTOR(t)->size; data = VECTOR(t)->data; if (Two_Byte (f)) { Alloca (s2, XChar2b*, n * sizeof (XChar2b)); for (i = 0; i < n; i++) { register int 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 ? Make_Integer (i) : Record_To_Vector (Char_Info_Rec, Char_Info_Size, Sym_Char_Info, FONT(font)->dpy, ~0L); } static Object P_Text_Width (Object font, Object t, Object f) { return Internal_Text_Metrics (font, t, f, 1); } static Object P_Text_Extents (Object font, Object t, Object f) { return Internal_Text_Metrics (font, t, f, 0); } static Object P_Draw_Image_Text (Object d, Object gc, Object x, Object y, Object t, Object f) { Display *dpy; Drawable dr = Get_Drawable (d, &dpy); Object *data; register int i, n; char *s; XChar2b *s2; Alloca_Begin; Check_Type (gc, T_Gc); Check_Type (t, T_Vector); n = VECTOR(t)->size; data = VECTOR(t)->data; if (Two_Byte (f)) { Alloca (s2, XChar2b*, n * sizeof (XChar2b)); for (i = 0; i < n; i++) { register int c = Get_2_Byte_Char (data[i]); s2[i].byte1 = (c >> 8) & 0xff; s2[i].byte2 = c & 0xff; } XDrawImageString16 (dpy, dr, GCONTEXT(gc)->gc, Get_Integer (x), Get_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, Get_Integer (x), Get_Integer (y), s, n); } Alloca_End; return Void; } static Object P_Draw_Poly_Text (Object d, Object gc, Object x, Object y, Object t, Object f) { Display *dpy; Drawable dr = Get_Drawable (d, &dpy); Object *data; register int 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 = VECTOR(t)->size) == 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 int 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, Get_Integer (x), Get_Integer (y), items, nitems); Alloca_End; return Void; } 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"); }