1 /*
2  * wmslib/src/but/rcur.c, part of wmslib (Library functions)
3  * Copyright (C) 1994 William Shubert.
4  * See "configure.h.in" for more copyright information.
5  */
6 
7 #include <configure.h>
8 
9 #ifdef  X11_DISP
10 
11 #ifdef  STDC_HEADERS
12 #include <stdlib.h>
13 #include <unistd.h>
14 #endif  /* STDC_HEADERS */
15 #include <stdio.h>
16 #include <X11/Xlib.h>
17 #include <X11/Xutil.h>
18 #include <X11/cursorfont.h>
19 #include <X11/Xatom.h>
20 #include <X11/keysym.h>
21 #include <sys/time.h>
22 #ifdef  HAVE_SYS_SELECT_H
23 #include <sys/select.h>
24 #endif
25 #include <wms.h>
26 #include <but/but.h>
27 #include <but/net.h>
28 #include <but/canvas.h>
29 
30 
31 typedef struct Curs_struct  {
32   int  fontcurnum;
33   int  hotX, hotY, w, h;
34   char  *pic, *mask;
35 } Curs;
36 
37 
38 #define ntm_width 16
39 #define ntm_height 16
40 #define ntm_bits ((char *)ntm_ubits)
41 static uchar ntm_ubits[] = {
42   0x03, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x3f, 0x00, 0x7f, 0x00,
43   0xff, 0x00, 0xff, 0x01, 0xff, 0x03, 0xff, 0x03, 0x7f, 0x00, 0xf7, 0x00,
44   0xf3, 0x00, 0xe0, 0x01, 0xe0, 0x01, 0xc0, 0x01};
45 
46 #define ntp_width 16
47 #define ntp_height 16
48 #define ntp_bits ((char *)ntp_ubits)
49 static uchar ntp_ubits[] = {
50   0x00, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x1e, 0x00, 0x3e, 0x00,
51   0x7e, 0x00, 0xfe, 0x00, 0xfe, 0x01, 0x3e, 0x00, 0x36, 0x00, 0x62, 0x00,
52   0x60, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x00, 0x00};
53 
54 #define tm_width 16
55 #define tm_height 16
56 #define tm_bits ((char *)tm_ubits)
57 static uchar tm_ubits[] = {
58   0x00, 0xe0, 0x00, 0xf8, 0x00, 0xfe, 0x80, 0x7f, 0xe0, 0x7f, 0xf8, 0x3f,
59   0xfc, 0x3f, 0xf8, 0x1f, 0xe0, 0x1f, 0xf0, 0x0f, 0xf8, 0x0f, 0x7c, 0x07,
60   0x3e, 0x07, 0x1f, 0x02, 0x0e, 0x00, 0x04, 0x00};
61 
62 #define tp_width 16
63 #define tp_height 16
64 #define tp_bits ((char *)tp_ubits)
65 static uchar tp_ubits[] = {
66   0x00, 0x00, 0x00, 0x60, 0x00, 0x78, 0x00, 0x3e, 0x80, 0x3f, 0xe0, 0x1f,
67   0xf8, 0x1f, 0x80, 0x0f, 0xc0, 0x0f, 0xe0, 0x06, 0x70, 0x06, 0x38, 0x02,
68   0x1c, 0x02, 0x0e, 0x00, 0x04, 0x00, 0x00, 0x00};
69 
70 #define txtp_width 16
71 #define txtp_height 16
72 #define txtp_bits ((char *)txtp_ubits)
73 static uchar txtp_ubits[] = {
74    0x00, 0x00, 0xee, 0x00, 0x38, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00,
75    0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00,
76    0x10, 0x00, 0x38, 0x00, 0xee, 0x00, 0x00, 0x00};
77 
78 #define txtm_width 16
79 #define txtm_height 16
80 #define txtm_bits ((char *)txtm_ubits)
81 static uchar txtm_ubits[] = {
82    0xef, 0x01, 0xff, 0x01, 0xff, 0x01, 0x7c, 0x00, 0x38, 0x00, 0x38, 0x00,
83    0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00,
84    0x7c, 0x00, 0xff, 0x01, 0xff, 0x01, 0xef, 0x01};
85 
86 static Curs  cursors[BUTCUR_NUM];
87 
88 static void  draw(ButRcur *rc);
89 static void  erase(ButRcur *rc);
90 static void  butRcur_hideForRedraw(ButRcur *rc, int winId, int x,int y,
91 				   int w,int h);
92 
93 
butEnv_rcInit(ButEnv * env)94 void  butEnv_rcInit(ButEnv *env)  {
95   Drawable  d = RootWindow(env->dpy, DefaultScreen(env->dpy));
96   static bool  first_time = TRUE;
97   ButCur  i;
98   int  dataWidth, j, k;
99 
100   if (first_time)  {
101     first_time = FALSE;
102     for (i = butCur_idle;  i < butCur_bogus;  ++i)
103       cursors[i].pic = NULL;
104 
105     cursors[butCur_idle].fontcurnum = XC_left_ptr;
106     cursors[butCur_idle].hotX = 1;
107     cursors[butCur_idle].hotY = 1;
108     cursors[butCur_idle].w = 16;
109     cursors[butCur_idle].h = 16;
110     cursors[butCur_idle].pic = ntp_bits;
111     cursors[butCur_idle].mask = ntm_bits;
112 
113     cursors[butCur_twitch].fontcurnum = XC_arrow;
114     cursors[butCur_twitch].hotX = 14;
115     cursors[butCur_twitch].hotY = 1;
116     cursors[butCur_twitch].w = 16;
117     cursors[butCur_twitch].h = 16;
118     cursors[butCur_twitch].pic = tp_bits;
119     cursors[butCur_twitch].mask = tm_bits;
120 
121     cursors[butCur_text].fontcurnum = XC_xterm;
122     cursors[butCur_text].hotX = 4;
123     cursors[butCur_text].hotY = 8;
124     cursors[butCur_text].w = 16;
125     cursors[butCur_text].h = 16;
126     cursors[butCur_text].pic = txtp_bits;
127     cursors[butCur_text].mask = txtm_bits;
128 
129     cursors[butCur_up].fontcurnum = XC_sb_up_arrow;
130     cursors[butCur_up].hotX = 14;
131     cursors[butCur_up].hotY = 14;
132     cursors[butCur_up].w = 16;
133     cursors[butCur_up].h = 16;
134     cursors[butCur_up].pic = ntp_bits;
135     cursors[butCur_up].mask = ntm_bits;
136 
137     cursors[butCur_down].fontcurnum = XC_sb_down_arrow;
138     cursors[butCur_down].hotX = 14;
139     cursors[butCur_down].hotY = 14;
140     cursors[butCur_down].w = 16;
141     cursors[butCur_down].h = 16;
142     cursors[butCur_down].pic = ntp_bits;
143     cursors[butCur_down].mask = ntm_bits;
144 
145     cursors[butCur_left].fontcurnum = XC_sb_left_arrow;
146     cursors[butCur_left].hotX = 14;
147     cursors[butCur_left].hotY = 14;
148     cursors[butCur_left].w = 16;
149     cursors[butCur_left].h = 16;
150     cursors[butCur_left].pic = ntp_bits;
151     cursors[butCur_left].mask = ntm_bits;
152 
153     cursors[butCur_right].fontcurnum = XC_sb_right_arrow;
154     cursors[butCur_right].hotX = 14;
155     cursors[butCur_right].hotY = 14;
156     cursors[butCur_right].w = 16;
157     cursors[butCur_right].h = 16;
158     cursors[butCur_right].pic = ntp_bits;
159     cursors[butCur_right].mask = ntm_bits;
160 
161     cursors[butCur_lr].fontcurnum = XC_sb_h_double_arrow;
162     cursors[butCur_lr].hotX = 14;
163     cursors[butCur_lr].hotY = 14;
164     cursors[butCur_lr].w = 16;
165     cursors[butCur_lr].h = 16;
166     cursors[butCur_lr].pic = ntp_bits;
167     cursors[butCur_lr].mask = ntm_bits;
168 
169     cursors[butCur_ud].fontcurnum = XC_sb_v_double_arrow;
170     cursors[butCur_ud].hotX = 14;
171     cursors[butCur_ud].hotY = 14;
172     cursors[butCur_ud].w = 16;
173     cursors[butCur_ud].h = 16;
174     cursors[butCur_ud].pic = ntp_bits;
175     cursors[butCur_ud].mask = ntm_bits;
176 
177     cursors[butCur_grab].fontcurnum = XC_fleur;
178     cursors[butCur_grab].hotX = 14;
179     cursors[butCur_grab].hotY = 14;
180     cursors[butCur_grab].w = 16;
181     cursors[butCur_grab].h = 16;
182     cursors[butCur_grab].pic = ntp_bits;
183     cursors[butCur_grab].mask = ntm_bits;
184   }
185 
186   for (i = butCur_idle;  i < butCur_bogus;  ++i)  {
187     /* "Grey out" the remote cursors. */
188     dataWidth = (cursors[i].w + 7) / 8;
189     for (j = 0;  j < cursors[i].h;  j += 2)  {
190       for (k = 0;  k < dataWidth;  ++k)  {
191 	cursors[i].mask[j*dataWidth + k] &= 0x55;
192 	if (j+1 < cursors[i].h)  {
193 	  cursors[i].mask[(j+1)*dataWidth + k] &= 0xaa;
194 	}
195       }
196     }
197     env->cursors[i] = XCreateFontCursor(env->dpy, cursors[i].fontcurnum);
198     env->cpic[i] = XCreateBitmapFromData(env->dpy, d, cursors[i].pic,
199 					 cursors[i].w, cursors[i].h);
200     env->cmask[i] = XCreateBitmapFromData(env->dpy, d, cursors[i].mask,
201 					  cursors[i].w, cursors[i].h);
202   }
203   env->curnum = butCur_idle;
204   env->curwin = None;
205   env->curhold = NULL;
206   env->curlast = butCur_bogus;
207 }
208 
209 
210 /* Erase the cursor if it is in the area specified. */
butRcur_create(ButRcur * rc,ButEnv * env)211 void  butRcur_create(ButRcur *rc, ButEnv *env)  {
212   MAGIC_SET(rc);
213   rc->env = env;
214   rc->winId = -2;
215   rc->drawn = FALSE;
216   rc->under = XCreatePixmap(env->dpy, DefaultRootWindow(env->dpy),
217 			    16,16, env->depth);
218 }
219 
220 
butRcur_move(ButRcur * rc,int winId,int rx,int ry,int rw,int rh,ButCur type)221 void  butRcur_move(ButRcur *rc, int winId, int rx,int ry, int rw,int rh,
222 		   ButCur type)  {
223   ButEnv  *env = rc->env;
224 
225   assert(MAGIC(rc));
226   if ((winId < 0) || (winId >= env->maxWinIds))
227     winId = -2;
228   else if (env->id2Win[winId] == NULL)
229     winId = -2;
230   if ((winId == rc->winId) && (rx == rc->rx) && (ry == rc->ry) &&
231       (rw == rc->rw) && (rh == rc->rh) && (type == rc->type))
232     return;
233   if (rc->drawn)
234     erase(rc);
235   rc->winId = winId;
236   rc->rx = rx;
237   rc->ry = ry;
238   rc->rw = rw;
239   rc->rh = rh;
240   rc->type = type;
241   if (winId != -2)  {
242     rc->lx = (rx * env->id2Win[winId]->w + rw/2) / rw - cursors[type].hotX;
243     rc->ly = (ry * env->id2Win[winId]->h + rh/2) / rh - cursors[type].hotY;
244     draw(rc);
245   }
246 }
247 
248 
butRcur_redraw(ButEnv * env,int winId,int x,int y,int w,int h)249 void  butRcur_redraw(ButEnv *env, int winId, int x,int y, int w,int h)  {
250   int  i;
251 
252   if (winId == -2)
253     return;
254   for (i = 0;  i < env->numPartners;  ++i)  {
255     if (env->partners[i])  {
256       if (butRnet_valid(env->partners[i]) &&
257 	  (winId == env->partners[i]->rc.winId))
258 	butRcur_hideForRedraw(&env->partners[i]->rc, winId, x,y, w,h);
259     }
260   }
261 }
262 
263 
butRcur_hideForRedraw(ButRcur * rc,int winId,int x,int y,int w,int h)264 static void  butRcur_hideForRedraw(ButRcur *rc, int winId, int x,int y,
265 				   int w,int h)  {
266   assert(MAGIC(rc));
267   if (rc->drawn && (rc->winId == winId) &&
268       (x < rc->lx+16) &&
269       (y < rc->ly+16) &&
270       (x+w > rc->lx) && (y+h > rc->ly))  {
271     /* We need to erase it.  Will the redraw erase it for us? */
272     if ((x <= rc->lx) && (y <= rc->ly) &&
273 	(x+w >= rc->lx+16) &&
274 	(y+h >= rc->ly+16))  {
275       rc->drawn = FALSE;
276     } else
277       erase(rc);
278   }
279 }
280 
281 
282 /* xio is the I/O context that the move got reported in. */
draw(ButRcur * rc)283 static void  draw(ButRcur *rc)  {
284   ButEnv  *env = rc->env;
285 
286   assert(!rc->drawn);
287   assert(MAGIC(rc));
288   XCopyArea(env->dpy, env->id2Win[rc->winId]->win, rc->under, env->gc2,
289 	    rc->lx,rc->ly, 16,16, 0,0);
290   if (!env->colorp)
291     XSetFillStyle(env->dpy, env->gc2, FillSolid);
292   XSetClipMask(env->dpy, env->gc2, env->cmask[rc->type]);
293   XSetClipOrigin(env->dpy, env->gc2, rc->lx,rc->ly);
294   XSetForeground(env->dpy, env->gc2, env->colors[BUT_FG]);
295   XSetBackground(env->dpy, env->gc2, env->colors[BUT_LIT]);
296   XCopyPlane(env->dpy, env->cpic[rc->type],env->id2Win[rc->winId]->win,
297 	     env->gc2, 0,0, 16,16, rc->lx,rc->ly, 1L);
298   XSetClipMask(env->dpy, env->gc2, None);
299   if (!env->colorp)
300     XSetFillStyle(env->dpy, env->gc2, FillTiled);
301   rc->drawn = TRUE;
302 }
303 
304 
erase(ButRcur * rc)305 static void  erase(ButRcur *rc)  {
306   ButEnv  *env = rc->env;
307 
308   assert(MAGIC(rc));
309   assert(rc->drawn);
310   XCopyArea(env->dpy, rc->under, env->id2Win[rc->winId]->win, env->gc2,
311 	    0,0, 16,16, rc->lx,rc->ly);
312   rc->drawn = FALSE;
313 }
314 
315 
316 /* Change the cursor to make it twitched or not twitched. */
butEnv_setCursor(ButEnv * env,But * but,ButCur newcursor)317 void  butEnv_setCursor(ButEnv *env, But *but, ButCur newcursor)  {
318   if (newcursor == butCur_idle)  {
319     if (but == env->curhold)  {
320       env->curnum = newcursor;
321       env->curhold = NULL;
322     }
323   } else  {
324     env->curnum = newcursor;
325     env->curhold = but;
326   }
327   env->curwin = but->win->physWin;
328 }
329 
330 
331 /* Set up any cursor changes that may have occurred. */
butEnv_rcActivate(ButEnv * env)332 void  butEnv_rcActivate(ButEnv *env)  {
333   int  i;
334 
335   if ((env->curlast != env->curnum) && (env->curwin != None))  {
336     assert(env->curnum < butCur_bogus);
337     env->curlast = env->curnum;
338     XDefineCursor(env->dpy, env->curwin, env->cursors[env->curlast]);
339     butRnet_mMove(env, -1, -1,-1, -1,-1, env->curnum);
340   }
341   for (i = 0;  i < env->numPartners;  ++i)  {
342     if (env->partners[i])  {
343       if (butRnet_valid(env->partners[i]) &&
344 	  (env->partners[i]->rc.winId >= 0) &&
345 	  !env->partners[i]->rc.drawn)
346 	draw(&env->partners[i]->rc);
347     }
348   }
349 }
350 
351 
352 #endif
353