PolyTxt.c revision 1ab64890
1/* $Xorg: PolyTxt.c,v 1.4 2001/02/09 02:03:35 xorgcvs Exp $ */
2/*
3
4Copyright 1986, 1998  The Open Group
5
6Permission to use, copy, modify, distribute, and sell this software and its
7documentation for any purpose is hereby granted without fee, provided that
8the above copyright notice appear in all copies and that both that
9copyright notice and this permission notice appear in supporting
10documentation.
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall not be
23used in advertising or otherwise to promote the sale, use or other dealings
24in this Software without prior written authorization from The Open Group.
25
26*/
27/* $XFree86: xc/lib/X11/PolyTxt.c,v 3.5 2001/10/28 03:32:30 tsi Exp $ */
28
29#ifdef HAVE_CONFIG_H
30#include <config.h>
31#endif
32#include "Xlibint.h"
33
34int
35XDrawText(
36    register Display *dpy,
37    Drawable d,
38    GC gc,
39    int x,
40    int y,
41    XTextItem *items,
42    int nitems)
43{
44    register int i;
45    register XTextItem *item;
46    int length = 0;
47    register xPolyText8Req *req;
48
49    LockDisplay(dpy);
50    FlushGC(dpy, gc);
51    GetReq (PolyText8, req);
52    req->drawable = d;
53    req->gc = gc->gid;
54    req->x = x;
55    req->y = y;
56
57    item = items;
58    for (i=0; i < nitems; i++) {
59	if (item->font)
60	    length += 5;  /* a 255 byte, plus size of Font id */
61        if (item->delta)
62        {
63	    if (item->delta > 0)
64	    {
65	      length += SIZEOF(xTextElt) * ((item->delta + 126) / 127);
66	    }
67            else
68            {
69   	      length += SIZEOF(xTextElt) * ((-item->delta + 127) / 128);
70 	    }
71        }
72	if (item->nchars > 0)
73	{
74	    length += SIZEOF(xTextElt) * ((item->nchars + 253) / 254 - 1);
75	    if (!item->delta) length += SIZEOF(xTextElt);
76	    length += item->nchars;
77     	}
78	item++;
79    }
80
81    req->length += (length + 3)>>2;  /* convert to number of 32-bit words */
82
83
84    /*
85     * If the entire request does not fit into the remaining space in the
86     * buffer, flush the buffer first.   If the request does fit into the
87     * empty buffer, then we won't have to flush it at the end to keep
88     * the buffer 32-bit aligned.
89     */
90
91    if (dpy->bufptr + length > dpy->bufmax)
92    	_XFlush (dpy);
93
94    item = items;
95    for (i=0; i< nitems; i++) {
96
97	if (item->font) {
98            /* to mark a font shift, write a 255 byte followed by
99	       the 4 bytes of font ID, big-end first */
100	    register unsigned char *f;
101	    BufAlloc (unsigned char *, f, 5);
102
103	    f[0] = 255;
104	    f[1] = (item->font & 0xff000000) >> 24;
105	    f[2] = (item->font & 0x00ff0000) >> 16;
106	    f[3] = (item->font & 0x0000ff00) >> 8;
107	    f[4] =  item->font & 0x000000ff;
108
109            /* update GC shadow */
110	    gc->values.font = item->font;
111	    }
112
113	{
114	    int nbytes = SIZEOF(xTextElt);
115	    int PartialNChars = item->nchars;
116	    int PartialDelta = item->delta;
117            /* register xTextElt *elt; */
118	    int FirstTimeThrough = True;
119 	    char *CharacterOffset = item->chars;
120            char *tbuf = NULL;
121
122	    while((PartialDelta < -128) || (PartialDelta > 127))
123            {
124	    	int nb = SIZEOF(xTextElt);
125
126	    	BufAlloc (char *, tbuf, nb);
127	    	*tbuf = 0;    /*   elt->len  */
128	    	if (PartialDelta > 0 )
129		{
130		    *(tbuf+1) = 127;  /* elt->delta  */
131		    PartialDelta = PartialDelta - 127;
132		}
133		else
134		{
135		    /* -128 = 0x8, need to be careful of signed chars... */
136		    *((unsigned char *)(tbuf+1)) = 0x80;  /* elt->delta */
137		    PartialDelta = PartialDelta + 128;
138		}
139	    }
140	    if (PartialDelta)
141            {
142                BufAlloc (char *, tbuf , nbytes);
143	        *tbuf = 0;      /* elt->len */
144		*(tbuf+1) = PartialDelta;    /* elt->delta  */
145	    }
146	    while(PartialNChars > 254)
147            {
148		nbytes = 254;
149	    	if (FirstTimeThrough)
150		{
151		    FirstTimeThrough = False;
152		    if (!item->delta)
153 		    {
154			nbytes += SIZEOF(xTextElt);
155	   		BufAlloc (char *, tbuf, nbytes);
156		        *(tbuf+1) = 0;     /* elt->delta */
157		    }
158		    else
159		    {
160			char *DummyChar;
161		        BufAlloc(char *, DummyChar, nbytes);
162		    }
163		}
164		else
165		{
166 		    nbytes += SIZEOF(xTextElt);
167	   	    BufAlloc (char *, tbuf, nbytes);
168		    *(tbuf+1) = 0;   /* elt->delta */
169		}
170		/* watch out for signs on chars */
171		*(unsigned char *)tbuf = 254;  /* elt->len */
172                memcpy (tbuf+2 , CharacterOffset, 254);
173		PartialNChars = PartialNChars - 254;
174		CharacterOffset += 254;
175
176	    }
177	    if (PartialNChars)
178            {
179		nbytes = PartialNChars;
180	    	if (FirstTimeThrough)
181		{
182		    FirstTimeThrough = False;
183		    if (!item->delta)
184 		    {
185			nbytes += SIZEOF(xTextElt);
186	   		BufAlloc (char *, tbuf, nbytes);
187			*(tbuf+1) = 0;   /*  elt->delta  */
188		    }
189		    else
190		    {
191			char *DummyChar;
192		        BufAlloc(char *, DummyChar, nbytes);
193		    }
194		}
195		else
196		{
197 		    nbytes += SIZEOF(xTextElt);
198	   	    BufAlloc (char *, tbuf, nbytes);
199		    *(tbuf+1) = 0;   /* elt->delta  */
200		}
201	    	*tbuf = PartialNChars;   /*  elt->len  */
202                memcpy (tbuf+2 , CharacterOffset, PartialNChars);
203	    }
204	}
205    item++;
206    }
207
208    /* Pad request out to a 32-bit boundary */
209
210    if (length &= 3) {
211	char *pad;
212	/*
213	 * BufAlloc is a macro that uses its last argument more than
214	 * once, otherwise I'd write "BufAlloc (char *, pad, 4-length)"
215	 */
216	length = 4 - length;
217	BufAlloc (char *, pad, length);
218	/*
219	 * if there are 3 bytes of padding, the first byte MUST be 0
220	 * so the pad bytes aren't mistaken for a final xTextElt
221	 */
222	*pad = 0;
223        }
224
225    /*
226     * If the buffer pointer is not now pointing to a 32-bit boundary,
227     * we must flush the buffer so that it does point to a 32-bit boundary
228     * at the end of this routine.
229     */
230
231    if ((dpy->bufptr - dpy->buffer) & 3)
232       _XFlush (dpy);
233    UnlockDisplay(dpy);
234    SyncHandle();
235    return 0;
236    }
237