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 <X11/Xfuncs.h>
40#include <X11/Xos.h>
41#include "BitmapP.h"
42
43#include <stdio.h>
44#include <math.h>
45
46
47/*****************************************************************************\
48 * Request Machine: stacks up and handles requests from application calls.   *
49\*****************************************************************************/
50
51/*
52 * Searches for a request record of a request specified by its name.
53 * Returns a pointer to the record or NULL if the request was not found.
54 */
55static BWRequestRec *
56FindRequest(BWRequest name)
57{
58    int i;
59
60    for (i = 0; i < bitmapClassRec.bitmap_class.num_requests; i++)
61	if (!strcmp(name, bitmapClassRec.bitmap_class.requests[i].name))
62	    return &bitmapClassRec.bitmap_class.requests[i];
63
64    return NULL;
65}
66
67/*
68 * Adds a request to the request stack and does proper initializations.
69 * Returns TRUE if the request was found and FALSE otherwise.
70 */
71Boolean
72BWAddRequest(Widget w, BWRequest name, Boolean trap,
73	     XtPointer call_data, Cardinal call_data_size)
74{
75    BitmapWidget BW = (BitmapWidget) w;
76    BWRequestRec *request;
77
78    request = FindRequest(name);
79    if(request) {
80	if (DEBUG)
81	  fprintf(stderr, "Adding... Cardinal: %d\n", BW->bitmap.cardinal + 1);
82
83	BW->bitmap.request_stack = (BWRequestStack *)
84	    XtRealloc((char *)BW->bitmap.request_stack,
85		      (++BW->bitmap.cardinal + 1) * sizeof(BWRequestStack));
86
87	BW->bitmap.request_stack[BW->bitmap.cardinal].request = request;
88	BW->bitmap.request_stack[BW->bitmap.cardinal].status =
89	    XtMalloc(request->status_size);
90	BW->bitmap.request_stack[BW->bitmap.cardinal].trap = trap;
91	BW->bitmap.request_stack[BW->bitmap.cardinal].call_data =
92	    XtMalloc(call_data_size);
93	memmove( BW->bitmap.request_stack[BW->bitmap.cardinal].call_data,
94	      call_data,
95	      call_data_size);
96
97	return True;
98    }
99    else {
100	XtWarning("bad request name.  BitmapWidget");
101	return False;
102    }
103}
104
105/*
106 * Engages the request designated by the current parameter.
107 * Returns TRUE if the request has an engage function and FALSE otherwise.
108 */
109static Boolean
110Engage(BitmapWidget BW, Cardinal current)
111{
112    BW->bitmap.current = current;
113
114    if (DEBUG)
115	fprintf(stderr, "Request: %s\n",
116		BW->bitmap.request_stack[current].request->name);
117
118    if (BW->bitmap.request_stack[current].request->engage) {
119	(*BW->bitmap.request_stack[current].request->engage)
120	    ((Widget) BW,
121	     BW->bitmap.request_stack[current].status,
122	     BW->bitmap.request_stack[current].request->engage_client_data,
123	     BW->bitmap.request_stack[current].call_data);
124	return True;
125    }
126    else
127	return False;
128}
129
130/* Boolean BWTerminateRequest();
131   Boolean BWRemoveRequest(); */
132
133/*
134 * Scans down the request stack removing all requests until it finds
135 * one to be trapped.
136 */
137static void
138TrappingLoop(BitmapWidget BW)
139{
140
141    if (DEBUG)
142	fprintf(stderr, "Scanning... Current: %d\n", BW->bitmap.current);
143    if ((BW->bitmap.current > 0)
144	&&
145	(!BW->bitmap.request_stack[BW->bitmap.current--].trap)) {
146	BWRemoveRequest((Widget) BW);
147	TrappingLoop(BW);
148    }
149    else
150	if (BW->bitmap.cardinal > 0) {
151	    if (DEBUG)
152		fprintf(stderr, "Trapping... Current: %d\n", BW->bitmap.current+1);
153	    if(!Engage(BW, ++BW->bitmap.current))
154		BWTerminateRequest((Widget) BW, True);
155	}
156}
157/*
158 * Terimantes the current request and continues with next request if con = TRUE
159 * Returns TRUE if there is any number of requests left on the stack.
160 */
161Boolean
162BWTerminateRequest(Widget w, Boolean cont)
163{
164    BitmapWidget BW = (BitmapWidget) w;
165
166    if (BW->bitmap.current > 0) {
167	if (DEBUG)
168	    fprintf(stderr, "Terminating... Current: %d\n", BW->bitmap.current);
169    	if (BW->bitmap.request_stack[BW->bitmap.current].request->terminate)
170	    (*BW->bitmap.request_stack[BW->bitmap.current].request->terminate)
171		(w,
172		 BW->bitmap.request_stack[BW->bitmap.current].status,
173		 BW->bitmap.request_stack[BW->bitmap.current].request->terminate_client_data);
174
175	if (cont) {
176	    if (BW->bitmap.current == BW->bitmap.cardinal)
177		TrappingLoop(BW);
178	    else {
179		if (DEBUG)
180		    fprintf(stderr, "Continuing... Current: %d\n", BW->bitmap.current+1);
181		if (!Engage(BW, ++BW->bitmap.current))
182		    BWTerminateRequest(w, True);
183	    }
184	}
185	else
186	    BW->bitmap.current = 0;
187    }
188
189    return BW->bitmap.current;
190}
191
192/*
193 * Simple interface to BWTerminateRequest that takes only a widget.
194 */
195void
196BWAbort(Widget w)
197{
198    BWTerminateRequest(w, True);
199}
200
201/*
202 * Removes the top request from the request stack. If the request is active
203 * it will terminate it.
204 * Returns TRUE if the number of requests left on the stack != 0.
205 */
206Boolean
207BWRemoveRequest(Widget w)
208{
209    BitmapWidget BW = (BitmapWidget) w;
210
211    if (BW->bitmap.cardinal > 0) {
212	if (DEBUG)
213	    fprintf(stderr, "Removing... Cardinal: %d\n", BW->bitmap.cardinal);
214	if (BW->bitmap.current == BW->bitmap.cardinal)
215	    BWTerminateRequest(w, False);
216
217	if (BW->bitmap.request_stack[BW->bitmap.cardinal].request->remove)
218	    (*BW->bitmap.request_stack[BW->bitmap.cardinal].request->remove)
219		(w,
220		 BW->bitmap.request_stack[BW->bitmap.cardinal].status,
221		 BW->bitmap.request_stack[BW->bitmap.cardinal].request->remove_client_data);
222
223	XtFree(BW->bitmap.request_stack[BW->bitmap.cardinal].status);
224	XtFree(BW->bitmap.request_stack[BW->bitmap.cardinal].call_data);
225	BW->bitmap.request_stack = (BWRequestStack *)
226	    XtRealloc((char *)BW->bitmap.request_stack,
227		      (--BW->bitmap.cardinal + 1) * sizeof(BWRequestStack));
228
229	return True;
230    }
231    else
232	return False;
233}
234
235void
236BWRemoveAllRequests(Widget w)
237{
238    while (BWRemoveRequest(w)) {/* removes all requests from the stack */}
239}
240
241/*
242 * Adds the request to the stack and performs engaging ritual.
243 * Returns TRUE if the request was found, FALSE otherwise.
244 */
245Boolean
246BWEngageRequest(Widget w, BWRequest name, Boolean trap,
247		XtPointer call_data, Cardinal call_data_size)
248{
249    BitmapWidget BW = (BitmapWidget) w;
250
251    if (BWAddRequest(w, name, trap, call_data, call_data_size)) {
252	BWTerminateRequest(w, False);
253	if (DEBUG)
254	    fprintf(stderr, "Engaging... Cardinal: %d\n", BW->bitmap.cardinal);
255	if (!Engage(BW, BW->bitmap.cardinal))
256	    BWTerminateRequest(w, True);
257
258	return True;
259    }
260    else
261	return False;
262}
263
264/************************* End of the Request Machine ************************/
265