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