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