home *** CD-ROM | disk | FTP | other *** search
/ vsiftp.vmssoftware.com / VSIPUBLIC@vsiftp.vmssoftware.com.tar / FREEWARE / FREEWARE40.ZIP / xjig / stack.c < prev    next >
C/C++ Source or Header  |  1997-12-31  |  7KB  |  283 lines

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