1 /*
2 
3 Copyright 1989, 1998  The Open Group
4 
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10 
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
21 
22 Except as contained in this notice, the name of The Open Group shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
25 from 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 <X11/Xfuncs.h>
36 #include <X11/Xos.h>
37 #include "BitmapP.h"
38 
39 #include <stdio.h>
40 #include <math.h>
41 
42 
43 /*****************************************************************************\
44  * Request Machine: stacks up and handles requests from application calls.   *
45 \*****************************************************************************/
46 
47 /*
48  * Searches for a request record of a request specified by its name.
49  * Returns a pointer to the record or NULL if the request was not found.
50  */
51 static BWRequestRec *
FindRequest(BWRequest name)52 FindRequest(BWRequest name)
53 {
54     int i;
55 
56     for (i = 0; i < bitmapClassRec.bitmap_class.num_requests; i++)
57 	if (!strcmp(name, bitmapClassRec.bitmap_class.requests[i].name))
58 	    return &bitmapClassRec.bitmap_class.requests[i];
59 
60     return NULL;
61 }
62 
63 /*
64  * Adds a request to the request stack and does proper initializations.
65  * Returns TRUE if the request was found and FALSE otherwise.
66  */
67 Boolean
BWAddRequest(Widget w,BWRequest name,Boolean trap,XtPointer call_data,Cardinal call_data_size)68 BWAddRequest(Widget w, BWRequest name, Boolean trap,
69 	     XtPointer call_data, Cardinal call_data_size)
70 {
71     BitmapWidget BW = (BitmapWidget) w;
72     BWRequestRec *request;
73 
74     request = FindRequest(name);
75     if(request) {
76 	if (DEBUG)
77 	  fprintf(stderr, "Adding... Cardinal: %d\n", BW->bitmap.cardinal + 1);
78 
79 	BW->bitmap.request_stack = (BWRequestStack *)
80 	    XtRealloc((char *)BW->bitmap.request_stack,
81 		      (++BW->bitmap.cardinal + 1) * sizeof(BWRequestStack));
82 
83 	BW->bitmap.request_stack[BW->bitmap.cardinal].request = request;
84 	BW->bitmap.request_stack[BW->bitmap.cardinal].status =
85 	    XtMalloc(request->status_size);
86 	BW->bitmap.request_stack[BW->bitmap.cardinal].trap = trap;
87 	BW->bitmap.request_stack[BW->bitmap.cardinal].call_data =
88 	    XtMalloc(call_data_size);
89 	memmove( BW->bitmap.request_stack[BW->bitmap.cardinal].call_data,
90 	      call_data,
91 	      call_data_size);
92 
93 	return True;
94     }
95     else {
96 	XtWarning("bad request name.  BitmapWidget");
97 	return False;
98     }
99 }
100 
101 /*
102  * Engages the request designated by the current parameter.
103  * Returnes TRUE if the request has an engage function and FALSE otherwise.
104  */
105 static Boolean
Engage(BitmapWidget BW,Cardinal current)106 Engage(BitmapWidget BW, Cardinal current)
107 {
108     BW->bitmap.current = current;
109 
110     if (DEBUG)
111 	fprintf(stderr, "Request: %s\n",
112 		BW->bitmap.request_stack[current].request->name);
113 
114     if (BW->bitmap.request_stack[current].request->engage) {
115 	(*BW->bitmap.request_stack[current].request->engage)
116 	    ((Widget) BW,
117 	     BW->bitmap.request_stack[current].status,
118 	     BW->bitmap.request_stack[current].request->engage_client_data,
119 	     BW->bitmap.request_stack[current].call_data);
120 	return True;
121     }
122     else
123 	return False;
124 }
125 
126 /* Boolean BWTerminateRequest();
127    Boolean BWRemoveRequest(); */
128 
129 /*
130  * Scans down the request stack removing all requests untill it finds
131  * one to be trapped.
132  */
133 static void
TrappingLoop(BitmapWidget BW)134 TrappingLoop(BitmapWidget BW)
135 {
136 
137     if (DEBUG)
138 	fprintf(stderr, "Scanning... Current: %d\n", BW->bitmap.current);
139     if ((BW->bitmap.current > 0)
140 	&&
141 	(!BW->bitmap.request_stack[BW->bitmap.current--].trap)) {
142 	BWRemoveRequest((Widget) BW);
143 	TrappingLoop(BW);
144     }
145     else
146 	if (BW->bitmap.cardinal > 0) {
147 	    if (DEBUG)
148 		fprintf(stderr, "Trapping... Current: %d\n", BW->bitmap.current+1);
149 	    if(!Engage(BW, ++BW->bitmap.current))
150 		BWTerminateRequest((Widget) BW, True);
151 	}
152 }
153 /*
154  * Terimantes the current request and continues with next request if con = TRUE
155  * Returnes TRUE if there is any number of requests left on the stack.
156  */
157 Boolean
BWTerminateRequest(Widget w,Boolean cont)158 BWTerminateRequest(Widget w, Boolean cont)
159 {
160     BitmapWidget BW = (BitmapWidget) w;
161 
162     if (BW->bitmap.current > 0) {
163 	if (DEBUG)
164 	    fprintf(stderr, "Terminating... Current: %d\n", BW->bitmap.current);
165     	if (BW->bitmap.request_stack[BW->bitmap.current].request->terminate)
166 	    (*BW->bitmap.request_stack[BW->bitmap.current].request->terminate)
167 		(w,
168 		 BW->bitmap.request_stack[BW->bitmap.current].status,
169 		 BW->bitmap.request_stack[BW->bitmap.current].request->terminate_client_data);
170 
171 	if (cont) {
172 	    if (BW->bitmap.current == BW->bitmap.cardinal)
173 		TrappingLoop(BW);
174 	    else {
175 		if (DEBUG)
176 		    fprintf(stderr, "Continuing... Current: %d\n", BW->bitmap.current+1);
177 		if (!Engage(BW, ++BW->bitmap.current))
178 		    BWTerminateRequest(w, True);
179 	    }
180 	}
181 	else
182 	    BW->bitmap.current = 0;
183     }
184 
185     return BW->bitmap.current;
186 }
187 
188 /*
189  * Simple interface to BWTerminateRequest that takes only a widget.
190  */
191 void
BWAbort(Widget w)192 BWAbort(Widget w)
193 {
194     BWTerminateRequest(w, True);
195 }
196 
197 /*
198  * Removes the top request from the request stack. If the request is active
199  * it will terminate it.
200  * Returns TRUE if the number of requests left on the stack != 0.
201  */
202 Boolean
BWRemoveRequest(Widget w)203 BWRemoveRequest(Widget w)
204 {
205     BitmapWidget BW = (BitmapWidget) w;
206 
207     if (BW->bitmap.cardinal > 0) {
208 	if (DEBUG)
209 	    fprintf(stderr, "Removing... Cardinal: %d\n", BW->bitmap.cardinal);
210 	if (BW->bitmap.current == BW->bitmap.cardinal)
211 	    BWTerminateRequest(w, False);
212 
213 	if (BW->bitmap.request_stack[BW->bitmap.cardinal].request->remove)
214 	    (*BW->bitmap.request_stack[BW->bitmap.cardinal].request->remove)
215 		(w,
216 		 BW->bitmap.request_stack[BW->bitmap.cardinal].status,
217 		 BW->bitmap.request_stack[BW->bitmap.cardinal].request->remove_client_data);
218 
219 	XtFree(BW->bitmap.request_stack[BW->bitmap.cardinal].status);
220 	XtFree(BW->bitmap.request_stack[BW->bitmap.cardinal].call_data);
221 	BW->bitmap.request_stack = (BWRequestStack *)
222 	    XtRealloc((char *)BW->bitmap.request_stack,
223 		      (--BW->bitmap.cardinal + 1) * sizeof(BWRequestStack));
224 
225 	return True;
226     }
227     else
228 	return False;
229 }
230 
231 void
BWRemoveAllRequests(Widget w)232 BWRemoveAllRequests(Widget w)
233 {
234     while (BWRemoveRequest(w)) {/* removes all requests from the stack */}
235 }
236 
237 /*
238  * Adds the request to the stack and performs engaging ritual.
239  * Returns TRUE if the request was found, FALSE otherwise.
240  */
241 Boolean
BWEngageRequest(Widget w,BWRequest name,Boolean trap,XtPointer call_data,Cardinal call_data_size)242 BWEngageRequest(Widget w, BWRequest name, Boolean trap,
243 		XtPointer call_data, Cardinal call_data_size)
244 {
245     BitmapWidget BW = (BitmapWidget) w;
246 
247     if (BWAddRequest(w, name, trap, call_data, call_data_size)) {
248 	BWTerminateRequest(w, False);
249 	if (DEBUG)
250 	    fprintf(stderr, "Engaging... Cardinal: %d\n", BW->bitmap.cardinal);
251 	if (!Engage(BW, BW->bitmap.cardinal))
252 	    BWTerminateRequest(w, True);
253 
254 	return True;
255     }
256     else
257 	return False;
258 }
259 
260 /************************* End of the Request Machine ************************/
261