1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <strings.h>
4 #include <X11/Xlib.h>
5 
6 #ifndef _global_h
7 #	include "global.h"
8 #endif
9 
10 #ifndef _stack_h
11 #	include "stack.H"
12 #endif
13 #ifndef _objects_h
14 #	include "objects.H"
15 #endif
16 #ifndef _gifx_image_h
17 #	include "gifx_image.H"
18 #endif
19 
20 
Object()21 Object::Object() {
22 	next=0;
23 }
24 
~Object()25 Object::~Object() {
26 	if (mystack)	mystack->Remove(this);
27 }
28 
ExposeWindowRegion(Window,int,int,int,int)29 void Object::ExposeWindowRegion( Window /*w*/, int /*x*/, int /*y*/, int /*width*/, int /*height*/ ) {
30 }
31 
Intersects(int,int,int,int)32 int Object::Intersects(int /*x*/,int /*y*/,int /*width*/,int /*height*/) {
33 	return 1;
34 }
35 
IsInside(int,int)36 int Object::IsInside(int /*x*/,int /*y*/) {
37 	return 0;
38 }
39 
DispatchPress(XButtonEvent *)40 void Object::DispatchPress( XButtonEvent * /*xbutton*/ ) {
41 	mystack->Raise(this);
42 }
43 
DispatchRelease(XButtonEvent *)44 void Object::DispatchRelease( XButtonEvent * /*xbutton*/ ) {
45 }
46 
DispatchMotion(XMotionEvent *)47 void Object::DispatchMotion( XMotionEvent * /*xmotion*/ ) {
48 }
49 
PanView(int,int)50 void Object::PanView( int /*offx*/, int /*offy*/ ) {
51 }
52 
JoinExtent(int *,int *,int *,int *)53 int Object::JoinExtent( int */*x1*/, int */*y1*/, int */*x2*/, int */*y2*/ ) {
54 	return 0;
55 }
GetExtent(int *,int *,int *,int *)56 int Object::GetExtent( int */*x1*/, int */*y1*/, int */*x2*/, int */*y2*/ ) {
57 	return 0;
58 }
ZoomView(int,int,int)59 void Object::ZoomView( int /*midx*/, int /*midy*/, int /*chg*/ ) {
60 }
61 
62 // ===========================================================================
63 
ObjectStack()64 ObjectStack::ObjectStack() {
65 	first=0;
66 	sel=0;
67 	last_sel=0;
68 	last_x=last_y=-1;
69 	dbmap=0;
70 }
71 
~ObjectStack()72 ObjectStack::~ObjectStack() {
73 	while(first)	delete first;
74 	if (dbmap)		XFreePixmap(dpy,dbmap);
75 }
76 
ExposeRegion(int,int,int,int)77 void ObjectStack::ExposeRegion(int /*x*/, int /*y*/, int /*width*/, int /*height*/) {
78 }
ExposeWindowRegion(Window,int,int,int,int)79 void ObjectStack::ExposeWindowRegion(Window /*w*/, int /*x*/, int /*y*/, int /*width*/, int /*height*/) {
80 }
81 
Raise(Object * obj)82 void ObjectStack::Raise(Object *obj) {
83 	if (first==obj) {
84 		first=obj->next;						// skip first object
85 		Append(obj);							// add at end of queue
86 	}
87 	else {
88 		for (Object *current=first;current->next;current=current->next) {
89 			if (current->next==obj) {
90 				current->next=obj->next;	// skip object in list
91 				while(current->next)		current=current->next;	// find end of list
92 				current->next=obj;			// add at end of queue
93 				obj->next=0;					// reset anchor
94 				break;
95 			}
96 		}
97 	}
98 }
99 
Remove(Object * obj)100 void ObjectStack::Remove(Object *obj) {
101 	if (first==obj) {
102 		first=obj->next;						// remove head of list
103 	}
104 	else {
105 		for (Object *current=first;current->next;current=current->next) {
106 			if (current->next==obj) {
107 				current->next=obj->next;	// remove entry
108 				break;
109 			}
110 		}
111 	}
112 	obj->next=0;								// disconnect object
113 }
114 
Append(Object * obj)115 void ObjectStack::Append(Object *obj) {
116 	if (first==0) {
117 		first=obj;								// add as first element
118 	}
119 	else {
120 		Object *current;
121 		for (current=first;current->next;current=current->next);
122 		current->next=obj;					// add as last element
123 	}
124 	obj->next=0;								// anchor on last object
125 	obj->mystack=this;
126 }
127 
PanView(int offx,int offy)128 void ObjectStack::PanView(int offx,int offy) {
129 	Object *current;
130 	for (current=first;current;current=current->next)
131 		current->PanView(offx,offy);
132 }
133 
ZoomView(int midx,int midy,int chg)134 void ObjectStack::ZoomView(int midx,int midy, int chg) {
135 	width  = width *(zoom_factor+chg)/ zoom_factor;
136 	height = height*(zoom_factor+chg)/ zoom_factor;
137 	pm->CreateData( width, height );
138 
139 	Object *current;
140 	for (current=first;current;current=current->next)
141 		current->ZoomView(midx,midy,chg);
142 	zoom_factor+=chg;
143 }
144 
GetExtent(int * x1,int * y1,int * x2,int * y2)145 void ObjectStack::GetExtent( int *x1, int *y1, int *x2, int *y2 ) {
146 	Object *current;
147 	for (current=first;current;current=current->next)
148 		if (current->GetExtent( x1, y1, x2, y2 ))		break;
149 	for (             ;current;current=current->next)
150 		current->JoinExtent( x1, y1, x2, y2 );
151 }
152 
153 // ===================================
154 
SelectObject(Object * current,int x,int y)155 int ObjectStack::SelectObject( Object *current, int x, int y ) {
156 
157 	if (last_sel==current&&x-last_x>=-1&&x-last_x<=1&&y-last_y>=-1&&y-last_y<=1) {
158 		// shortcut: same object reselected
159 		sel=current;
160 		return 1;
161 	}
162 
163 	if (current->next && SelectObject(current->next,x,y))		return 1;
164 
165 	switch( current->IsInside(x,y) ) {
166 	case 2:
167 		// found exact hit -> direct return
168 		sel=current;
169 		return 1;
170 	case 1:
171 		// store first close hit
172 		if (!close_sel)	close_sel=current;
173 	}
174 	return 0;
175 }
176 
177 
DispatchPress(XButtonEvent * xbutton)178 void ObjectStack::DispatchPress( XButtonEvent *xbutton ) {
179 	if (!sel) {
180 		close_sel=0;
181 		if (!SelectObject(first,xbutton->x,xbutton->y)) {
182 			// when not direct hit, use close tile ...
183 			if (close_sel)		sel=close_sel;
184 		}
185 	}
186 	if (sel) {
187 		// store last selection, which can be done again when on exactly
188 		// the same position (-> double/tripple clicks for rotations)
189 			last_sel=sel;
190 			last_x=xbutton->x;
191 			last_y=xbutton->y;
192 			sel->DispatchPress( xbutton );
193 	}
194 	else	last_sel=0;
195 	return;
196 }
197 
DispatchRelease(XButtonEvent * xbutton)198 void ObjectStack::DispatchRelease( XButtonEvent *xbutton ) {
199 	if (sel) {
200 		sel->DispatchRelease( xbutton );
201 		if (!((xbutton->state&AnyButtonMask)&~(Button1Mask<<(xbutton->button-1)))) {
202 			sel=0;			// no more buttons pressed -> cancel selection
203 			XDefineCursor( dpy, win, normal_cursor );
204 		}
205 	}
206 	return;
207 }
208 
DispatchMotion(XMotionEvent * xmotion)209 void ObjectStack::DispatchMotion( XMotionEvent *xmotion ) {
210 	if (sel) {
211 		sel->DispatchMotion( xmotion );
212 	}
213 	return;
214 }
215 
216 // ===========================================================================
217 
DBObjectStack()218 DBObjectStack::DBObjectStack() {
219 	gc=XCreateGC(dpy,RootWindow(dpy,scr),0,0);
220 }
221 
~DBObjectStack()222 DBObjectStack::~DBObjectStack() {
223 	XFreeGC(dpy,gc);
224 }
225 
ExposeRegion(int x,int y,int width,int height)226 void DBObjectStack::ExposeRegion(int x, int y, int width, int height) {
227 Object *current;
228 
229 	dbmap=XCreatePixmap(dpy,RootWindow(dpy,scr),width,height,DefaultDepth(dpy,scr));
230 	for (current=first;current;current=current->next) {
231 		if (current->Intersects(x,y,width,height)) {
232 			current->ExposeRegion(x,y,width,height);
233 		}
234 	}
235 	XCopyArea(dpy,dbmap,win,gc,0,0,width,height,x,y);
236 	XFreePixmap(dpy,dbmap);
237 	dbmap=0;
238 }
239 // ===========================================================================
240 
WindowObjectStack()241 WindowObjectStack::WindowObjectStack() {
242 }
243 
~WindowObjectStack()244 WindowObjectStack::~WindowObjectStack() {
245 }
246 
ExposeWindowRegion(Window w,int x,int y,int width,int height)247 void WindowObjectStack::ExposeWindowRegion(Window w, int x, int y, int width, int height) {
248 Object *current;
249 
250 	for (current=first;current;current=current->next) {
251 		current->ExposeWindowRegion(w,x,y,width,height);
252 	}
253 }
254 
DispatchPress(XButtonEvent * xbutton)255 void WindowObjectStack::DispatchPress( XButtonEvent *xbutton ) {
256 	xbutton->x=xbutton->x_root;
257 	xbutton->y=xbutton->y_root;
258 	ObjectStack::DispatchPress( xbutton );
259 }
260 
DispatchRelease(XButtonEvent * xbutton)261 void WindowObjectStack::DispatchRelease( XButtonEvent *xbutton ) {
262 	xbutton->x=xbutton->x_root;
263 	xbutton->y=xbutton->y_root;
264 	ObjectStack::DispatchRelease( xbutton );
265 }
266 
DispatchMotion(XMotionEvent * xmotion)267 void WindowObjectStack::DispatchMotion( XMotionEvent *xmotion ) {
268 	xmotion->x=xmotion->x_root;
269 	xmotion->y=xmotion->y_root;
270 	ObjectStack::DispatchMotion( xmotion );
271 }
272 
Raise(Object * obj)273 void WindowObjectStack::Raise(Object *obj) {
274 	XRaiseWindow( dpy, ((PieceObject*)obj)->swin );
275 }
276