1 /* grX11su5.c -
2  *
3  *     *********************************************************************
4  *     * Copyright (C) 1985, 1990 Regents of the University of California. *
5  *     * Permission to use, copy, modify, and distribute this              *
6  *     * software and its documentation for any purpose and without        *
7  *     * fee is hereby granted, provided that the above copyright          *
8  *     * notice appear in all copies.  The University of California        *
9  *     * makes no representations about the suitability of this            *
10  *     * software for any purpose.  It is provided "as is" without         *
11  *     * express or implied warranty.  Export of this software outside     *
12  *     * of the United States of America may require an export license.    *
13  *     *********************************************************************
14  *
15  *	Manipulate the programable cursor on the graphics display.
16  *
17  */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <X11/Xlib.h>
22 
23 #include "utils/magic.h"
24 #include "utils/styles.h"
25 #include "utils/hash.h"
26 #include "textio/textio.h"
27 #include "utils/geometry.h"
28 #include "graphics/graphics.h"
29 #include "graphics/glyphs.h"
30 #include "windows/windows.h"
31 #include "graphics/graphicsInt.h"
32 #include "grX11Int.h"
33 
34 extern HashTable	grX11WindowTable;
35 extern XColor colors[];
36 /* locals */
37 
38 Cursor grCursors[MAX_CURSORS];
39 
40 
41 /*
42  * ----------------------------------------------------------------------------
43  * GrXDrawGlyph --
44  *
45  *	Draw one glyph on the display.
46  *
47  * Results:
48  *	None.
49  *
50  * Side effects:
51  *	Draws pixels.
52  * ----------------------------------------------------------------------------
53  */
54 
55 void
GrX11DrawGlyph(gl,p)56 GrX11DrawGlyph (gl, p)
57     GrGlyph *gl;		/* A single glyph */
58     Point *p;			/* screen pos of lower left corner */
59 {
60     Rect bBox;
61     bool anyObscure;
62     LinkedRect *ob;
63 
64     GR_CHECK_LOCK();
65     bBox.r_ll = *p;
66     bBox.r_xtop = p->p_x + gl->gr_xsize - 1;
67     bBox.r_ytop = p->p_y + gl->gr_ysize - 1;
68 
69     anyObscure = FALSE;
70     for (ob = grCurObscure; ob != NULL; ob = ob->r_next) {
71 	if (GEO_TOUCH( &(ob->r_r), &bBox)) {
72 	    anyObscure = TRUE;
73 	    break;
74 	}
75     }
76     if(grDisplay.depth <= 8) {
77       XSetPlaneMask(grXdpy, grGCGlyph, grPlanes[127]); }
78     XSetFillStyle(grXdpy, grGCGlyph, FillSolid);
79     if ((!anyObscure) && (GEO_SURROUND(&grCurClip, &bBox)) ) {
80 	int *pixelp, x, y;
81 
82 	/* no clipping, try to go quickly */
83 	pixelp = gl->gr_pixels;
84 	for (y = 0; y < gl->gr_ysize; y++) {
85 	    int x1, y1;
86 
87 	    y1 = grMagicToX(bBox.r_ybot + y);
88 	    for (x = 0; x < gl->gr_xsize; x++) {
89 		int color;
90 		if (*pixelp != 0) {
91 		    color = GrStyleTable[*pixelp].color;
92 		    x1 = bBox.r_xbot + x;
93 		    XSetForeground(grXdpy, grGCGlyph, grPixels[color]);
94 		    XDrawPoint(grXdpy, grCurrent.window, grGCGlyph, x1, y1);
95 		}
96 		pixelp++;
97 	    }
98 	}
99     } else {
100 	/* do pixel by pixel clipping */
101 	int y, yloc;
102 
103 	yloc = bBox.r_ybot;
104 	for (y = 0; y < gl->gr_ysize; y++) {
105 	    int startx, endx;
106 	    if ( (yloc <= grCurClip.r_ytop) && (yloc >= grCurClip.r_ybot) ) {
107 		int laststartx;
108 		laststartx = bBox.r_xbot - 1;
109 		for (startx = bBox.r_xbot; startx <= bBox.r_xtop;
110 			startx = endx + 1) {
111 		    int *pixelp;
112 
113 		    startx = MAX(startx, grCurClip.r_xbot);
114 		    endx = MIN(bBox.r_xtop, grCurClip.r_xtop);
115 
116 		    if (anyObscure) {
117 			for (ob = grCurObscure; ob != NULL; ob = ob->r_next) {
118 			    if ( (ob->r_r.r_ybot <= yloc) &&
119 				 (ob->r_r.r_ytop >= yloc) ) {
120 				if (ob->r_r.r_xbot <= startx)
121 				    startx = MAX(startx, ob->r_r.r_xtop + 1);
122 				else if (ob->r_r.r_xbot <= endx)
123 				    endx = MIN(endx, ob->r_r.r_xbot - 1);
124 			    }
125 			}
126 		    }
127 
128 		    /* stop if we aren't advancing */
129 		    if (startx == laststartx) break;
130 		    laststartx = startx;
131 		    if (startx > endx) continue;
132 
133 		    /* draw a section of this scan line */
134 		    pixelp = &( gl->gr_pixels[y*gl->gr_xsize +
135 			    (startx - bBox.r_xbot)]);
136 		    for ( ; startx <= endx; startx++) {
137 			int color;
138 			if (*pixelp != 0) {
139 			    color = GrStyleTable[*pixelp].color;
140 			    XSetForeground(grXdpy, grGCGlyph, grPixels[color]);
141 			    XDrawPoint(grXdpy, grCurrent.window, grGCGlyph,
142 					startx, grMagicToX(yloc));
143 			}
144 			pixelp++;
145 		    }
146 		    startx = endx + 1;
147 		}
148 	    }
149 	    yloc++;
150 	}
151     }
152 }
153 
154 
155 /*
156  * ----------------------------------------------------------------------------
157  * grxDefineCursor:
158  *
159  *	Define a new set of cursors.
160  *
161  * Results:
162  *	None.
163  *
164  * Side effects:
165  *	The given matrix is stored in the graphics display, and it can be
166  *	used as the cursor by calling GrSetCursor.
167  * ----------------------------------------------------------------------------
168  */
169 
170 void
grx11DefineCursor(glyphs)171 grx11DefineCursor(glyphs)
172     GrGlyphs *glyphs;
173 {
174     int glyphnum;
175     Rect oldClip;
176     XColor fgcolor, bgcolor;
177     Pixmap source, mask;
178 
179     if (glyphs->gr_num <= 0) return;
180 
181     if (glyphs->gr_num > MAX_CURSORS)
182     {
183 	TxError("X only has room for %d cursors\n", MAX_CURSORS);
184 	return;
185     }
186 
187     /* expand clipping amount for off-screen access on the X */
188     GrLock(GR_LOCK_SCREEN, FALSE);
189     oldClip = grCurClip;
190     grCurClip = GrScreenRect;
191     grCurClip.r_ytop += 16;
192 
193     /* enter the glyphs */
194     for (glyphnum = 0; glyphnum < glyphs->gr_num; glyphnum++) {
195 
196 	int i, *p, fgstyle;
197 	GrGlyph *g;
198 	int x, y;
199 	unsigned char curs[32];
200 	unsigned char mbits[32];
201 
202 	g = glyphs->gr_glyph[glyphnum];
203 	if ((g->gr_xsize != 16) || (g->gr_ysize != 16)) {
204 	    TxError("Cursors for the X must be 16 X 16 pixels.\n");
205 	    return;
206 	}
207 
208 	/* Pick off the non-transparent color and find the	*/
209 	/* corresponding display color.  If there are two	*/
210 	/* colors other than background, we treat them as	*/
211 	/* foreground and background, without regard to order.	*/
212 
213 	p = &(g->gr_pixels[0]);
214 	fgstyle = STYLE_TRANSPARENT;
215 	for (x = 0; x < 256; x++)
216 	{
217 	    if (*p != STYLE_TRANSPARENT)
218 	    {
219 		fgstyle = *p;
220 		fgcolor.pixel = grPixels[GrStyleTable[*p].color];
221 		XQueryColor(grXdpy, grXcmap, &fgcolor);
222 		break;
223 	    }
224 	    p++;
225 	}
226 
227 	if (x == 256)
228 	{
229 	    fgcolor.pixel = BlackPixel(grXdpy, grXscrn);
230 	    fgcolor.red=0;
231 	    fgcolor.green=0;
232 	    fgcolor.blue=0;
233 	    fgcolor.flags=DoRed|DoGreen|DoBlue;
234 	}
235 
236 	for (; x < 256; x++)
237 	{
238 	    if ((*p != STYLE_TRANSPARENT) && (*p != fgstyle))
239 	    {
240 		bgcolor.pixel = grPixels[GrStyleTable[*p].color];
241 		XQueryColor(grXdpy, grXcmap, &bgcolor);
242 		break;
243 	    }
244 	    p++;
245 	}
246 
247 	if (x == 256)
248 	{
249 	    bgcolor.pixel = WhitePixel(grXdpy, grXscrn);
250 	    bgcolor.red=65535;
251 	    bgcolor.green=65535;
252 	    bgcolor.blue=65535;
253 	    bgcolor.flags=DoRed|DoGreen|DoBlue;
254 	}
255 
256 	/* Perform transposition on the glyph matrix since X displays
257 	 * the least significant bit on the left hand side.
258 	 */
259 	p = &(g->gr_pixels[0]);
260 	for (y = 0; y < 32; y++) {
261 	    i = (y & 1) ? (32 - y) : (30 - y);
262 
263 	    curs[i] = mbits[i] = 0;
264 	    for (x = 0; x < 8; x++)
265 	    {
266 		if (*p == fgstyle)
267 		     curs[i] |= (1 << x);
268 		if (*p != STYLE_TRANSPARENT)
269 		     mbits[i] |= (1 << x);
270 		p++;
271 	    }
272 	}
273 	source = XCreateBitmapFromData(grXdpy, XDefaultRootWindow(grXdpy),
274 				       (const char *)curs, 16, 16);
275 	mask = XCreateBitmapFromData(grXdpy, XDefaultRootWindow(grXdpy),
276 				     (const char *)mbits, 16, 16);
277 	grCursors[glyphnum] = XCreatePixmapCursor(grXdpy, source, mask,
278 						  &fgcolor, &bgcolor,
279 						  g->gr_origin.p_x,
280 						  (15 - g->gr_origin.p_y));
281     }
282 
283     /* Restore clipping */
284     grCurClip = oldClip;
285     GrUnlock(GR_LOCK_SCREEN);
286 }
287 
288 
289 /*
290  * ----------------------------------------------------------------------------
291  * GrXSetCursor:
292  *
293  *	Make the cursor be a new pattern, as defined in the display styles file.
294  *
295  * Results:
296  *	None.
297  *
298  * Side effects:
299  *	When the cursor is turned back on it will take on the new pattern.
300  * ----------------------------------------------------------------------------
301  */
302 
303 void
GrX11SetCursor(cursorNum)304 GrX11SetCursor(cursorNum)
305     int cursorNum;	/* The cursor number as defined in the display
306 		         * styles file.
307 		         */
308 {
309     HashEntry	*entry;
310     HashSearch	hs;
311 
312     if (cursorNum >= MAX_CURSORS)
313     {
314 	TxError("No such cursor!\n");
315 	return;
316     }
317 
318     grCurrent.cursor = grCursors[cursorNum];
319 
320     HashStartSearch(&hs);
321     while (entry = HashNext(&grX11WindowTable,&hs))
322     {
323     	 if (HashGetValue(entry))
324          	XDefineCursor(grXdpy,(Window)entry->h_key.h_ptr,grCurrent.cursor);
325     }
326 }
327