Handlers.c revision 2b32c8f7
1/*
2
3Copyright 1989, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included
12in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall
23not be used in advertising or otherwise to promote the sale, use or
24other dealings in this Software without prior written authorization
25from The Open Group.
26
27*/
28
29/*
30 * Author:  Davor Matic, MIT X Consortium
31 */
32
33#include <X11/IntrinsicP.h>
34#include <X11/StringDefs.h>
35#include "BitmapP.h"
36
37#include <stdio.h>
38#include <math.h>
39
40#define min(x, y)                     (((int)(x) < (int)(y)) ? (x) : (y))
41#define max(x, y)                     (((int)(x) > (int)(y)) ? (x) : (y))
42
43#include "Requests.h"
44
45
46/*****************************************************************************
47 *                                  Handlers                                 *
48 *****************************************************************************/
49
50#define QueryInSquare(BW, x, y, square_x, square_y)\
51    ((InBitmapX(BW, x) == (square_x)) &&\
52     (InBitmapY(BW, y) == (square_y)))
53
54
55static void
56DragOnePointHandler(Widget w,
57		    XtPointer client_data,
58		    XEvent *event,
59		    Boolean *cont) /* ARGSUSED */
60{
61    BWStatus *status = (BWStatus *)client_data;
62    BitmapWidget BW = (BitmapWidget) w;
63
64    if (DEBUG)
65	fprintf(stderr, "D1PH ");
66
67    switch (event->type) {
68
69    case ButtonPress:
70	if (event->xbutton.state != status->state) return;
71	if (!QuerySet(status->at_x, status->at_y)) {
72	    BWStoreToBuffer(w);
73	    status->value = Value(BW, event->xbutton.button);
74	    status->btime = event->xbutton.time;
75	    status->at_x = InBitmapX(BW, event->xbutton.x);
76	    status->at_y = InBitmapY(BW, event->xbutton.y);
77	    status->success = status->draw ? True : False;
78	    if (status->draw)
79		(*(DrawOnePointProc)status->draw)(w,
80				status->at_x, status->at_y, status->value);
81	}
82	break;
83
84    case ButtonRelease:
85	if (QuerySet(status->at_x, status->at_y)) {
86	    status->value = Value(BW, event->xbutton.button);
87	    status->btime = event->xbutton.time;
88	    status->at_x = InBitmapX(BW, event->xbutton.x);
89	    status->at_y = InBitmapY(BW, event->xbutton.y);
90	    status->success = status->draw ? True : False;
91	    /* SUPPRESS 701 */
92	    BWTerminateRequest(w, TRUE);
93	}
94	break;
95
96    case MotionNotify:
97	if (QuerySet(status->at_x, status->at_y)) {
98	    if (!QueryInSquare(BW, event->xmotion.x, event->xmotion.y,
99			       status->at_x, status->at_y)) {
100		status->at_x = InBitmapX(BW, event->xmotion.x);
101		status->at_y = InBitmapY(BW, event->xmotion.y);
102		if (status->draw)
103		    (*(DrawOnePointProc)status->draw)(w,
104				    status->at_x, status->at_y, status->value);
105	    }
106	}
107	break;
108
109    }
110}
111
112void
113DragOnePointEngage(Widget w,
114		   BWStatus *status,
115		   XtPointer draw,
116		   int *state)
117{
118
119    status->at_x = NotSet;
120    status->at_y = NotSet;
121    status->draw = draw;
122    status->success = False;
123    status->state = *state;
124
125    XtAddEventHandler(w,
126		      ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
127		      FALSE, DragOnePointHandler, (XtPointer)status);
128}
129
130/* ARGSUSED */
131void
132DragOnePointTerminate(Widget w,
133		      BWStatus *status,
134		      XtPointer draw)
135{
136
137    if (status->success) {
138	BWChangeNotify(w);
139	BWSetChanged(w);
140    }
141
142    XtRemoveEventHandler(w,
143		 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
144		 FALSE, DragOnePointHandler, (XtPointer)status);
145
146}
147
148void
149OnePointHandler(Widget w,
150		XtPointer client_data,
151		XEvent *event,
152		Boolean *cont) /* ARGSUSED */
153{
154    BWStatus    *status = (BWStatus *)client_data;
155    BitmapWidget BW = (BitmapWidget) w;
156
157    if (DEBUG)
158	fprintf(stderr, "1PH ");
159
160    switch (event->type) {
161
162    case Expose:
163	if (QuerySet(status->at_x, status->at_y)) {
164	    BWClip(w, event->xexpose.x, event->xexpose.y,
165		   event->xexpose.width, event->xexpose.height);
166	    if (status->draw)
167		(*(DrawOnePointProc)status->draw)(w,
168				status->at_x, status->at_y, Highlight);
169
170	    BWUnclip(w);
171	}
172	break;
173
174    case ButtonPress:
175	if (event->xbutton.state != status->state) return;
176	if (!QuerySet(status->at_x, status->at_y)) {
177	    status->value = Value(BW, event->xbutton.button);
178	    status->btime = event->xbutton.time;
179	    status->at_x = InBitmapX(BW, event->xbutton.x);
180	    status->at_y = InBitmapY(BW, event->xbutton.y);
181	    if (status->draw)
182		(*(DrawOnePointProc)status->draw)(w,
183				status->at_x, status->at_y, Highlight);
184	}
185	break;
186
187    case ButtonRelease:
188	if (QuerySet(status->at_x, status->at_y)) {
189	    if (status->draw)
190		(*(DrawOnePointProc)status->draw)(w,
191				status->at_x, status->at_y, Highlight);
192
193	    status->value = Value(BW, event->xbutton.button);
194	    status->btime = event->xbutton.time;
195	    status->at_x = InBitmapX(BW, event->xbutton.x);
196	    status->at_y = InBitmapY(BW, event->xbutton.y);
197	    status->success = True;
198
199	    BWTerminateRequest(w, TRUE);
200	}
201	break;
202
203    case MotionNotify:
204	if (QuerySet(status->at_x, status->at_y)) {
205	    if (!QueryInSquare(BW, event->xmotion.x, event->xmotion.y,
206			       status->at_x, status->at_y)) {
207		if (status->draw)
208		    (*(DrawOnePointProc)status->draw)(w,
209				    status->at_x, status->at_y, Highlight);
210		status->at_x = InBitmapX(BW, event->xmotion.x);
211		status->at_y = InBitmapY(BW, event->xmotion.y);
212		if (status->draw)
213		    (*(DrawOnePointProc)status->draw)(w,
214				    status->at_x, status->at_y, Highlight);
215	    }
216	}
217	break;
218    }
219}
220
221void
222OnePointEngage(Widget w,
223	       BWStatus *status,
224	       XtPointer draw,
225	       int *state)
226{
227    status->at_x = NotSet;
228    status->at_y = NotSet;
229    status->draw = draw;
230    status->success = False;
231    status->state = *state;
232
233    XtAddEventHandler(w,
234		      ButtonPressMask | ButtonReleaseMask |
235		      ExposureMask | PointerMotionMask,
236		      FALSE, OnePointHandler, (XtPointer)status);
237}
238
239#if 0
240void
241OnePointImmediateEngage(Widget w,
242			BWStatus *status,
243			XtPointer draw,
244			int *state)
245{
246    status->at_x = 0;
247    status->at_y = 0;
248    status->draw = draw;
249    status->success = False;
250    status->state = *state;
251
252    if (status->draw)
253	(*(DrawOnePointProc)status->draw)(w,
254			status->at_x, status->at_y, Highlight);
255
256    XtAddEventHandler(w,
257		      ButtonPressMask | ButtonReleaseMask |
258		      ExposureMask | PointerMotionMask,
259		      FALSE, OnePointHandler, (XtPointer)status);
260}
261#endif
262
263void
264OnePointTerminate(Widget w,
265		  BWStatus *status,
266		  XtPointer draw)
267{
268
269    if (status->success && draw) {
270	BWStoreToBuffer(w);
271	(*(DrawOnePointProc)draw)(w,
272		status->at_x, status->at_y,
273		status->value);
274	BWChangeNotify(w);
275	BWSetChanged(w);
276    }
277    else
278	if (QuerySet(status->at_x, status->at_y))
279	    if (status->draw)
280		(*(DrawOnePointProc)status->draw)(w,
281				status->at_x, status->at_y, Highlight);
282
283    XtRemoveEventHandler(w,
284			 ButtonPressMask | ButtonReleaseMask |
285			 ExposureMask | PointerMotionMask,
286			 FALSE, OnePointHandler, (XtPointer)status);
287}
288
289void
290OnePointTerminateTransparent(Widget w,
291			     BWStatus *status,
292			     XtPointer draw)
293{
294
295    if (status->success && draw)
296	(*(DrawOnePointProc)draw)(w,
297		status->at_x, status->at_y,
298		status->value);
299    else
300	if (QuerySet(status->at_x, status->at_y))
301	    if (status->draw)
302		(*(DrawOnePointProc)status->draw)(w,
303				status->at_x, status->at_y, Highlight);
304
305    XtRemoveEventHandler(w,
306			 ButtonPressMask | ButtonReleaseMask |
307			 ExposureMask | PointerMotionMask,
308			 FALSE, OnePointHandler, (XtPointer)status);
309
310}
311
312
313void
314TwoPointsHandler(Widget w,
315		 XtPointer client_data,
316		 XEvent *event,
317		 Boolean *cont) /* ARGSUSED */
318{
319    BitmapWidget BW = (BitmapWidget) w;
320    BWStatus   *status = (BWStatus *)client_data;
321    if (DEBUG)
322	fprintf(stderr, "2PH ");
323
324    switch (event->type) {
325
326    case Expose:
327	if (QuerySet(status->from_x, status->from_y) &&
328	    QuerySet(status->to_x, status->to_y)) {
329	    BWClip(w, event->xexpose.x, event->xexpose.y,
330		   event->xexpose.width, event->xexpose.height);
331	    if (status->draw)
332		(*(DrawTwoPointProc)status->draw)(w,
333				status->from_x, status->from_y,
334				status->to_x, status->to_y, Highlight);
335	    BWUnclip(w);
336	}
337	break;
338
339    case ButtonPress:
340	if (event->xbutton.state != status->state) return;
341	if (!QuerySet(status->from_x, status->from_y)) {
342	    status->value = Value(BW, event->xbutton.button);
343	    status->btime = event->xbutton.time;
344	    status->from_x = InBitmapX(BW, event->xbutton.x);
345	    status->from_y = InBitmapY(BW, event->xbutton.y);
346	    status->to_x = InBitmapX(BW, event->xbutton.x);
347	    status->to_y = InBitmapY(BW, event->xbutton.y);
348	    if (status->draw)
349		(*(DrawTwoPointProc)status->draw)(w,
350				status->from_x, status->from_y,
351				status->to_x, status->to_y, Highlight);
352	}
353	break;
354
355    case ButtonRelease:
356	if (QuerySet(status->from_x, status->from_y)) {
357	    if (status->draw)
358		(*(DrawTwoPointProc)status->draw)(w,
359				status->from_x, status->from_y,
360				status->to_x, status->to_y, Highlight);
361	    status->value = Value(BW, event->xbutton.button);
362	    status->btime = event->xbutton.time;
363	    status->to_x = InBitmapX(BW, event->xbutton.x);
364	    status->to_y = InBitmapY(BW, event->xbutton.y);
365	    status->success = True;
366
367	    BWTerminateRequest(w, TRUE);
368	}
369	break;
370
371    case MotionNotify:
372	if (QuerySet(status->from_x, status->from_y)) {
373	    if (QuerySet(status->to_x, status->to_y)) {
374		if (!QueryInSquare(BW, event->xmotion.x, event->xmotion.y,
375				   status->to_x, status->to_y)) {
376		    if (status->draw)
377			(*(DrawTwoPointProc)status->draw)(w,
378					status->from_x, status->from_y,
379					status->to_x, status->to_y, Highlight);
380		    status->to_x = InBitmapX(BW, event->xmotion.x);
381		    status->to_y = InBitmapY(BW, event->xmotion.y);
382		    if (status->draw)
383			(*(DrawTwoPointProc)status->draw)(w,
384					status->from_x, status->from_y,
385					status->to_x, status->to_y, Highlight);
386		}
387	    }
388	    else {
389		status->to_x = InBitmapX(BW, event->xmotion.x);
390		status->to_y = InBitmapY(BW, event->xmotion.y);
391		if (status->draw)
392		    (*(DrawTwoPointProc)status->draw)(w,
393				    status->from_x, status->from_y,
394				    status->to_x, status->to_y, Highlight);
395	    }
396	}
397	break;
398    }
399}
400
401void
402TwoPointsEngage(Widget w,
403		BWStatus *status,
404		XtPointer draw,
405		int *state)
406{
407
408    status->from_x = NotSet;
409    status->from_y = NotSet;
410    status->to_x = NotSet;
411    status->to_y = NotSet;
412    status->draw = draw;
413    status->success = False;
414    status->state = *state;
415
416    XtAddEventHandler(w,
417		      ButtonPressMask | ButtonReleaseMask |
418		      ExposureMask | PointerMotionMask,
419		      FALSE, TwoPointsHandler, (XtPointer)status);
420}
421
422void
423TwoPointsTerminate(Widget w,
424		   BWStatus *status,
425		   XtPointer draw)
426{
427
428    if (status->success && draw) {
429	BWStoreToBuffer(w);
430	(*(DrawTwoPointProc)draw)(w,
431		status->from_x, status->from_y,
432		status->to_x, status->to_y,
433		status->value);
434	BWChangeNotify(w);
435	BWSetChanged(w);
436    }
437    else
438	if (QuerySet(status->from_x, status->from_y) &&
439	    QuerySet(status->to_x, status->to_y))
440	    if (status->draw)
441		(*(DrawTwoPointProc)status->draw)(w,
442				status->from_x, status->from_y,
443				status->to_x, status->to_y, Highlight);
444
445    XtRemoveEventHandler(w,
446			 ButtonPressMask | ButtonReleaseMask |
447			 ExposureMask | PointerMotionMask,
448			 FALSE, TwoPointsHandler, (XtPointer)status);
449}
450
451void
452TwoPointsTerminateTransparent(Widget w,
453			      BWStatus *status,
454			      XtPointer draw)
455{
456
457    if (status->success && draw)
458	(*(DrawTwoPointProc)draw)(w,
459		status->from_x, status->from_y,
460		status->to_x, status->to_y,
461		status->value);
462    else
463	if (QuerySet(status->from_x, status->from_y) &&
464	    QuerySet(status->to_x, status->to_y))
465	    if (status->draw)
466		(*(DrawTwoPointProc)status->draw)(w,
467				status->from_x, status->from_y,
468				status->to_x, status->to_y, Highlight);
469
470    XtRemoveEventHandler(w,
471			 ButtonPressMask | ButtonReleaseMask |
472			 ExposureMask | PointerMotionMask,
473			 FALSE, TwoPointsHandler, (XtPointer)status);
474}
475
476void
477TwoPointsTerminateTimed(Widget w,
478			BWStatus *status,
479			XtPointer draw)
480{
481
482    if (status->success && draw)
483	(*(DrawTwoPointProc)draw)(w,
484		status->from_x, status->from_y,
485		status->to_x, status->to_y,
486		status->btime);
487    else
488	if (QuerySet(status->from_x, status->from_y) &&
489	    QuerySet(status->to_x, status->to_y))
490	    if (status->draw)
491		(*(DrawTwoPointProc)status->draw)(w,
492				status->from_x, status->from_y,
493				status->to_x, status->to_y, Highlight);
494
495    XtRemoveEventHandler(w,
496			 ButtonPressMask | ButtonReleaseMask |
497			 ExposureMask | PointerMotionMask,
498			 FALSE, TwoPointsHandler, (XtPointer)status);
499}
500
501/* ARGSUSED */
502void
503Interface(Widget w,
504	  BWStatus *status,
505	  XtPointer action)
506{
507    (*(InterfaceProc)action)(w);
508}
509
510void
511Paste(Widget w,
512      Position at_x,
513      Position at_y,
514      int value)
515{
516    BitmapWidget    BW = (BitmapWidget) w;
517    BWStatus       *my_status;
518    BWRequest       request;
519
520    my_status = (BWStatus *)
521	BW->bitmap.request_stack[BW->bitmap.current].status;
522
523    my_status->draw = NULL;
524
525   request = (BWRequest)
526   BW->bitmap.request_stack[BW->bitmap.current].request->terminate_client_data;
527
528    BWTerminateRequest(w, FALSE);
529
530    if ((at_x == max(BW->bitmap.mark.from_x, min(at_x, BW->bitmap.mark.to_x)))
531	&&
532      (at_y == max(BW->bitmap.mark.from_y, min(at_y, BW->bitmap.mark.to_y)))) {
533
534	BWStatus *status;
535
536	if (DEBUG)
537	    fprintf(stderr, "Prepaste request: %s\n", request);
538
539	BWEngageRequest(w, request, False, (char *)&(my_status->state), sizeof(int));
540
541	status = (BWStatus *)
542	    BW->bitmap.request_stack[BW->bitmap.current].status;
543
544	status->at_x = at_x;
545	status->at_y = at_y;
546	status->value = value;
547	(*(DrawOnePointProc)status->draw) (w, at_x, at_y, Highlight);
548    }
549    else {
550
551	BWStatus *status;
552
553      BWEngageRequest(w, MarkRequest, False, (char *)&(my_status->state), sizeof(int));
554
555	status = (BWStatus *)
556	    BW->bitmap.request_stack[BW->bitmap.current].status;
557
558	status->from_x = status->to_x = at_x;
559	status->from_y = status->to_y = at_y;
560	status->value = value;
561	(*(DrawTwoPointProc)status->draw) (w, at_x, at_y, at_x, at_y, Highlight);
562    }
563}
564
565
566void
567DragTwoPointsHandler(Widget w,
568		     XtPointer client_data,
569		     XEvent *event,
570		     Boolean *cont) /* ARGSUSED */
571{
572    BitmapWidget BW = (BitmapWidget) w;
573    BWStatus   *status = (BWStatus *)client_data;
574
575    if (DEBUG)
576	fprintf(stderr, "D2PH ");
577
578    switch (event->type) {
579
580    case ButtonPress:
581	if (event->xbutton.state != status->state) return;
582	if (!QuerySet(status->from_x, status->from_y)) {
583	    BWStoreToBuffer(w);
584	    status->value = Value(BW, event->xbutton.button);
585	    status->btime = event->xbutton.time;
586	    status->from_x = InBitmapX(BW, event->xbutton.x);
587	    status->from_y = InBitmapY(BW, event->xbutton.y);
588	    status->to_x = InBitmapX(BW, event->xbutton.x);
589	    status->to_y = InBitmapY(BW, event->xbutton.y);
590	    status->success = status->draw ? True : False;
591	    if (status->draw)
592		(*(DrawTwoPointProc)status->draw)(w,
593				status->from_x, status->from_y,
594				status->to_x, status->to_y, status->value);
595	}
596	break;
597
598    case ButtonRelease:
599	if (QuerySet(status->from_x, status->from_y)) {
600	    status->value = Value(BW, event->xbutton.button);
601	    status->btime = event->xbutton.time;
602	    status->from_x = status->to_x;
603	    status->from_y = status->to_y;
604	    status->to_x = InBitmapX(BW, event->xbutton.x);
605	    status->to_y = InBitmapY(BW, event->xbutton.y);
606	    status->success = True;
607
608	    BWTerminateRequest(w, TRUE);
609	}
610	break;
611
612    case MotionNotify:
613	if (QuerySet(status->from_x, status->from_y)) {
614	    if (QuerySet(status->to_x, status->to_y)) {
615		if (!QueryInSquare(BW, event->xmotion.x, event->xmotion.y,
616				   status->to_x, status->to_y)) {
617		    status->from_x = status->to_x;
618		    status->from_y = status->to_y;
619		    status->to_x = InBitmapX(BW, event->xmotion.x);
620		    status->to_y = InBitmapY(BW, event->xmotion.y);
621		    if (status->draw)
622			(*(DrawTwoPointProc)status->draw)(w,
623					status->from_x, status->from_y,
624					status->to_x, status->to_y, status->value);
625		}
626	    }
627	}
628	break;
629    }
630}
631
632void
633DragTwoPointsEngage(Widget w,
634		    BWStatus *status,
635		    XtPointer draw,
636		    int *state)
637{
638
639    status->from_x = NotSet;
640    status->from_y = NotSet;
641    status->to_x = NotSet;
642    status->to_y = NotSet;
643    status->draw = draw;
644    status->success = False;
645    status->state = *state;
646
647    XtAddEventHandler(w,
648		      ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
649		      FALSE, DragTwoPointsHandler, (XtPointer)status);
650}
651
652void
653DragTwoPointsTerminate(Widget w,
654		       BWStatus *status,
655		       XtPointer draw)
656{
657
658    if (status->success && draw) {
659	if ((status->from_x != status->to_x)
660	    ||
661	    (status->from_y != status->to_y))
662	    (*(DrawTwoPointProc)draw)(w,
663		    status->from_x, status->from_y,
664		    status->to_x, status->to_y,
665		    status->value);
666	BWChangeNotify(w);
667	BWSetChanged(w);
668    }
669
670    XtRemoveEventHandler(w,
671		         ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
672			 FALSE, DragTwoPointsHandler, (XtPointer)status);
673}
674
675/*****************************************************************************/
676