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