1 /* grOGL5.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
21 #include <GL/gl.h>
22 #include <GL/glx.h>
23
24 #include "utils/magic.h"
25 #include "utils/styles.h"
26 #include "utils/hash.h"
27 #include "textio/textio.h"
28 #include "utils/geometry.h"
29 #include "graphics/graphics.h"
30 #include "graphics/glyphs.h"
31 #include "windows/windows.h"
32 #include "graphics/graphicsInt.h"
33 #include "grOGLInt.h"
34
35 extern HashTable grOGLWindowTable;
36 extern Display *grXdpy;
37 extern int grXscrn;
38
39 Cursor grCursors[MAX_CURSORS];
40
41
42 /*
43 * ----------------------------------------------------------------------------
44 * GrOGLDrawGlyph --
45 *
46 * Draw one glyph on the display.
47 *
48 * Results:
49 * None.
50 *
51 * Side effects:
52 * Draws pixels.
53 * ----------------------------------------------------------------------------
54 */
55
56 void
GrOGLDrawGlyph(gl,p)57 GrOGLDrawGlyph (gl, p)
58 GrGlyph *gl; /* A single glyph */
59 Point *p; /* screen pos of lower left corner */
60 {
61 Rect bBox;
62 bool anyObscure;
63 LinkedRect *ob;
64
65 GR_CHECK_LOCK();
66
67 /* We're going to change the graphics state without affecting */
68 /* the standard color and mask saved values, so we had better */
69 /* flush all rects & lines first. */
70 GR_X_FLUSH_BATCH();
71
72 bBox.r_ll = *p;
73 bBox.r_xtop = p->p_x + gl->gr_xsize - 1;
74 bBox.r_ytop = p->p_y + gl->gr_ysize - 1;
75
76 anyObscure = FALSE;
77 for (ob = grCurObscure; ob != NULL; ob = ob->r_next) {
78 if (GEO_TOUCH( &(ob->r_r), &bBox)) {
79 anyObscure = TRUE;
80 break;
81 }
82 }
83
84 if ((!anyObscure) && (GEO_SURROUND(&grCurClip, &bBox)) ) {
85 int *pixelp, x, y;
86
87 /* no clipping, try to go quickly */
88 pixelp = gl->gr_pixels;
89 for (y = 0; y < gl->gr_ysize; y++) {
90 int x1, y1;
91
92 y1 = bBox.r_ybot + y;
93 for (x = 0; x < gl->gr_xsize; x++) {
94 int color, red, green, blue, mask;
95 if (*pixelp != 0) {
96 mask = GrStyleTable[*pixelp].color << 1;
97 color = GrStyleTable[*pixelp].color;
98 x1 = bBox.r_xbot + x;
99 GrGetColor(color, &red, &green, &blue);
100 glColor4ub((GLubyte)red, (GLubyte)green, (GLubyte)blue,
101 (GLubyte)mask);
102 glBegin(GL_POINTS);
103 glVertex2i((GLint)x1, (GLint)y1);
104 glEnd();
105 }
106 pixelp++;
107 }
108 }
109 } else {
110 /* do pixel by pixel clipping */
111 int y, yloc;
112
113 yloc = bBox.r_ybot;
114 for (y = 0; y < gl->gr_ysize; y++) {
115 int startx, endx;
116 if ( (yloc <= grCurClip.r_ytop) && (yloc >= grCurClip.r_ybot) ) {
117 int laststartx;
118 laststartx = bBox.r_xbot - 1;
119 for (startx = bBox.r_xbot; startx <= bBox.r_xtop;
120 startx = endx + 1) {
121 int *pixelp;
122
123 startx = MAX(startx, grCurClip.r_xbot);
124 endx = MIN(bBox.r_xtop, grCurClip.r_xtop);
125
126 if (anyObscure) {
127 for (ob = grCurObscure; ob != NULL; ob = ob->r_next) {
128 if ( (ob->r_r.r_ybot <= yloc) &&
129 (ob->r_r.r_ytop >= yloc) ) {
130 if (ob->r_r.r_xbot <= startx)
131 startx = MAX(startx, ob->r_r.r_xtop + 1);
132 else if (ob->r_r.r_xbot <= endx)
133 endx = MIN(endx, ob->r_r.r_xbot - 1);
134 }
135 }
136 }
137
138 /* stop if we aren't advancing */
139 if (startx == laststartx) break;
140 laststartx = startx;
141 if (startx > endx) continue;
142
143 /* draw a section of this scan line */
144 pixelp = &( gl->gr_pixels[y*gl->gr_xsize +
145 (startx - bBox.r_xbot)]);
146 for ( ; startx <= endx; startx++) {
147 int color, red, green, blue, mask;
148 if (*pixelp != 0) {
149 mask = GrStyleTable[*pixelp].mask << 1;
150 color = GrStyleTable[*pixelp].color;
151 GrGetColor(color, &red, &green, &blue);
152 glColor4ub((GLubyte)red, (GLubyte)green,
153 (GLubyte)blue, (GLubyte)mask);
154 glBegin(GL_POINTS);
155 glVertex2i((GLint)startx, (GLint)yloc);
156 glEnd();
157 }
158 pixelp++;
159 }
160 startx = endx + 1;
161 }
162 }
163 yloc++;
164 }
165 }
166 }
167
168
169 /*
170 * ----------------------------------------------------------------------------
171 * groglDefineCursor:
172 *
173 * Use X cursors on top of the OpenGL window
174 *
175 * Results:
176 * None.
177 *
178 * Side effects:
179 * The given matrix is stored in the graphics display, and it can be
180 * used as the cursor by calling GrSetCursor.
181 * ----------------------------------------------------------------------------
182 */
183
184 void
groglDefineCursor(glyphs)185 groglDefineCursor(glyphs)
186 GrGlyphs *glyphs;
187 {
188 int glyphnum;
189 Rect oldClip;
190 int red, green, blue;
191 Pixmap source,mask;
192 XColor curcolor;
193
194
195 if (glyphs->gr_num <= 0) return;
196
197 if (glyphs->gr_num > MAX_CURSORS)
198 {
199 TxError("X only has room for %d cursors\n", MAX_CURSORS);
200 return;
201 }
202
203 /* expand clipping amount for off-screen access on the X */
204 GrLock(GR_LOCK_SCREEN, FALSE);
205 oldClip = grCurClip;
206 grCurClip = GrScreenRect;
207 grCurClip.r_ytop += 16;
208
209 /* what color should the cursor be? The following makes it the
210 opposite of what the background "mostly" is.
211 */
212 GrGetColor(GrStyleTable[STYLE_TRANSPARENT].color, &red, &green, &blue);
213
214 if (red + green + blue > 0x180) /* (0x180 = 128 * 3) */
215 {
216 curcolor.pixel = BlackPixel(grXdpy,grXscrn);
217 curcolor.red = 0;
218 curcolor.green = 0;
219 curcolor.blue = 0;
220 curcolor.flags |= DoRed|DoGreen|DoBlue;
221 }
222 else
223 {
224 curcolor.pixel = WhitePixel(grXdpy,grXscrn);
225 curcolor.red = 65535;
226 curcolor.green = 65535;
227 curcolor.blue = 65535;
228 curcolor.flags |= DoRed|DoGreen|DoBlue;
229 }
230
231 /* enter the glyphs */
232 for (glyphnum = 0; glyphnum < glyphs->gr_num; glyphnum++) {
233 int *p;
234 GrGlyph *g;
235 int x, y;
236 unsigned char curs[32];
237
238 g = glyphs->gr_glyph[glyphnum];
239 if ((g->gr_xsize != 16) || (g->gr_ysize != 16)) {
240 TxError("Cursors for the X must be 16 X 16 pixels.\n");
241 return;
242 }
243
244 /* Perform transposition on the glyph matrix since X displays
245 * the least significant bit on the left hand side.
246 */
247 p = &(g->gr_pixels[0]);
248 for (y = 0; y < 32; y += 2) {
249 int i;
250
251 curs[i = 31 - y - 1] = 0;
252 for (x = 0; x < 8; x++)
253 {
254 if (GrStyleTable[*p].color != 0)
255 {
256 curs[i] |= 1 << x;
257 }
258 p++;
259 }
260 curs[i += 1] = 0;
261 for (x = 0; x < 8; x++)
262 {
263 if (GrStyleTable[*p].color != 0)
264 {
265 curs[i] |= 1 << x;
266 }
267 p++;
268 }
269 }
270 source = XCreateBitmapFromData(grXdpy, XDefaultRootWindow(grXdpy),
271 (char *)curs, 16, 16);
272 mask = XCreateBitmapFromData(grXdpy, XDefaultRootWindow(grXdpy),
273 (char *)curs, 16, 16);
274 grCursors[glyphnum] = XCreatePixmapCursor(grXdpy, source, mask,
275 &curcolor, &curcolor,
276 g->gr_origin.p_x,
277 (15 - g->gr_origin.p_y));
278 }
279
280 /* Restore clipping */
281 grCurClip = oldClip;
282 GrUnlock(GR_LOCK_SCREEN);
283 }
284
285
286 /*
287 * ----------------------------------------------------------------------------
288 * GrOGLSetCursor:
289 *
290 * Make the cursor be a new pattern, as defined in the display styles file.
291 *
292 * Results:
293 * None.
294 *
295 * Side effects:
296 * When the cursor is turned back on it will take on the new pattern.
297 * ----------------------------------------------------------------------------
298 */
299
300 void
GrOGLSetCursor(cursorNum)301 GrOGLSetCursor(cursorNum)
302 int cursorNum; /* The cursor number as defined in the display
303 * styles file.
304 */
305 {
306 HashEntry *entry;
307 HashSearch hs;
308
309 if (cursorNum >= MAX_CURSORS)
310 {
311 TxError("No such cursor!\n");
312 return;
313 }
314
315 oglCurrent.cursor = grCursors[cursorNum];
316
317 HashStartSearch(&hs);
318 while (entry = HashNext(&grOGLWindowTable, &hs))
319 if (HashGetValue(entry))
320 XDefineCursor(grXdpy, (Window)entry->h_key.h_ptr, oglCurrent.cursor);
321
322 /* The following is necessary to make sure the cursor is changed NOW */
323 glXWaitX();
324 }
325