home *** CD-ROM | disk | FTP | other *** search
/ vsiftp.vmssoftware.com / VSIPUBLIC@vsiftp.vmssoftware.com.tar / FREEWARE / FREEWARE40.ZIP / xv310a / xvscrl.c < prev    next >
C/C++ Source or Header  |  1995-06-12  |  16KB  |  505 lines

  1. /* 
  2.  * xvscrl.c - Scroll Bar handling functions
  3.  *
  4.  * callable functions:
  5.  *
  6.  *   SCCreate()   -  creates the Scroll Bar window.
  7.  *   SCChange()   -  resize/repositions the Scroll Bar window.
  8.  *   SCSetRange() -  sets min/max/current values of control
  9.  *   SCSetVal()   -  sets value of control 
  10.  *   SCRedraw()   -  redraws scroll bar
  11.  *   SCTrack()    -  called when clicked.  Operates control 'til mouseup
  12.  */
  13.  
  14. #include "copyright.h"
  15.  
  16. #include "xv.h"
  17.  
  18. #include "bits/up"
  19. #include "bits/down"
  20. #include "bits/up1"
  21. #include "bits/down1"
  22. #include "bits/uph"
  23. #include "bits/downh"
  24. #include "bits/uph1"
  25. #include "bits/downh1"
  26. #include "bits/scrlgray"
  27.  
  28.  
  29. static Pixmap upPix,  downPix;   /* up/down arrows */
  30. static Pixmap up1Pix, down1Pix;  /* up/down arrows (lit up) */
  31. static Pixmap uphPix, downhPix;  /* up/down arrows, for horizontal scrl */
  32. static Pixmap uph1Pix,downh1Pix; /* up/down arrows, horizontal (lit up) */
  33. static Pixmap sgray;             /* gray stipple for lit scrollbar */
  34. static int    pixmaps_built=0;   /* true if pixmaps created already */
  35.  
  36.  
  37. /* scroll regions */
  38. #define UPLINE 0
  39. #define UPPAGE 1
  40. #define DNLINE 2
  41. #define DNPAGE 3
  42. #define THUMB  4
  43.  
  44. #define SCRLWAIT 80   /* milliseconds to wait between scrolls */
  45.  
  46. /* local functions */
  47. static int  whereInScrl PARM((SCRL *, int, int));
  48. static void drawArrow   PARM((SCRL *, int));
  49. static void drawThumb   PARM((SCRL *));
  50.  
  51.  
  52. /***************************************************/
  53. void SCCreate(sp, parent, x, y, vert, len, minv, maxv, curv, page, 
  54.               fg, bg, hi, lo, func)
  55. SCRL         *sp;
  56. Window        parent;
  57. int           x,y,vert,len,minv,maxv,curv,page;
  58. unsigned long fg,bg,hi,lo;
  59.  
  60. void          (*func)PARM((int, SCRL *));
  61. {
  62.  
  63.  
  64.   if (!pixmaps_built) {
  65.     upPix    = MakePix1(parent, up_bits,     up_width,     up_height);
  66.     downPix  = MakePix1(parent, down_bits,   down_width,   down_height);
  67.     up1Pix   = MakePix1(parent, up1_bits,    up1_width,    up1_height);
  68.     down1Pix = MakePix1(parent, down1_bits,  down1_width,  down1_height);
  69.  
  70.     uphPix   = MakePix1(parent, uph_bits,    uph_width,    uph_height);
  71.     downhPix = MakePix1(parent, downh_bits,  downh_width,  downh_height);
  72.     uph1Pix  = MakePix1(parent, uph1_bits,   uph1_width,   uph1_height);
  73.     downh1Pix= MakePix1(parent, downh1_bits, downh1_width, downh1_height);
  74.     
  75.     sgray    = XCreatePixmapFromBitmapData(theDisp, parent,
  76.         (char *) scrlgray_bits, scrlgray_width, scrlgray_height,
  77.                        fg,bg,dispDEEP);
  78.   }
  79.  
  80.   sp->x    = x;
  81.   sp->y    = y;
  82.  
  83.   sp->vert = vert;
  84.   sp->len  = len;
  85.   sp->fg   = fg;
  86.   sp->bg   = bg;
  87.   sp->hi   = hi;
  88.   sp->lo   = lo;
  89.   sp->uplit = sp->dnlit = 0;
  90.   sp->tsize  =  19;
  91.  
  92.   if (vert) {
  93.     sp->win = XCreateSimpleWindow(theDisp,parent,x,y,
  94.                   (u_int) sp->tsize, (u_int) len,1,fg,bg);
  95.     sp->w = sp->tsize;
  96.     sp->h = len;
  97.   }
  98.   else {
  99.     sp->win = XCreateSimpleWindow(theDisp,parent,x,y,
  100.                   (u_int) len, (u_int) sp->tsize,1,fg,bg);
  101.     sp->w = len;
  102.     sp->h = sp->tsize;
  103.   }
  104.  
  105.  
  106.   if (!sp->win) FatalError("can't create scrollbar window");
  107.  
  108.   sp->tmin   =  sp->tsize+1;
  109.   sp->tmax   =  len - (sp->tsize+1) - sp->tsize;
  110.  
  111.   sp->drawobj = func;
  112.  
  113.   SCSetRange(sp, minv, maxv, curv, page);
  114.   XSelectInput(theDisp, sp->win, ExposureMask | ButtonPressMask);
  115. }
  116.  
  117.  
  118. /***************************************************/
  119. void SCChange(sp, x, y, vert, len, minv, maxv, curv, page)
  120. SCRL         *sp;
  121. int           x,y,vert,len,minv,maxv,curv,page;
  122. {
  123.   sp->vert = vert;
  124.   sp->len  = len;
  125.   sp->uplit = sp->dnlit = 0;
  126.  
  127.   if (vert) XMoveResizeWindow(theDisp, sp->win, x,y, 
  128.                   (u_int) sp->tsize,(u_int) len);
  129.   else      XMoveResizeWindow(theDisp, sp->win, x,y,
  130.                   (u_int) len, (u_int) sp->tsize);
  131.  
  132.   sp->tmin   =  sp->tsize+1;
  133.   sp->tmax   =  len - (sp->tsize+1) - sp->tsize;
  134.  
  135.   SCSetRange(sp, minv, maxv, curv, page);
  136. }
  137.  
  138.  
  139. /***************************************************/
  140. void SCSetRange(sp, minv, maxv, curv, page)
  141.      SCRL *sp;
  142.      int   minv, maxv, curv, page;
  143. {
  144.   if (maxv<minv) maxv=minv;
  145.   sp->min = minv;    sp->max = maxv;    sp->page = page;
  146.   sp->active =  (minv < maxv);
  147.   
  148.   /* adjust scroll bar background */
  149.   if (sp->active) {
  150.     if (ctrlColor) XSetWindowBackground(theDisp, sp->win, sp->lo);
  151.               else XSetWindowBackgroundPixmap(theDisp, sp->win, sgray);
  152.   }
  153.   else XSetWindowBackground(theDisp, sp->win, sp->bg);
  154.  
  155.   sp->val = -99999;  /* force redraw */
  156.   SCSetVal(sp, curv);
  157. }
  158.  
  159.  
  160. /***************************************************/
  161. int SCSetVal(sp, curv)
  162. SCRL *sp;
  163. int   curv;
  164. {
  165.   /* returns '0' if no redraw was done */
  166.   int oldval;
  167.  
  168.   RANGE(curv, sp->min, sp->max);   /* make sure curv is in-range */
  169.  
  170.   if (sp->val == curv) return 0;
  171.  
  172.   oldval = sp->val;
  173.   if (oldval == -99999) oldval = curv;   /* ignore kludge */
  174.  
  175.   sp->val = curv;
  176.  
  177.   if (sp->active) 
  178.     sp->tpos = sp->tmin + ((sp->tmax - sp->tmin)*(curv - sp->min))
  179.                / (sp->max - sp->min);
  180.  
  181.   drawThumb(sp);
  182.   (sp->drawobj)(curv-oldval, sp);   /* redraw what the scrlbar controls */
  183.  
  184.   XFlush(theDisp);
  185.   return 1;
  186. }
  187.  
  188.  
  189. /***************************************************/
  190. void SCRedraw(sp)
  191. SCRL *sp;
  192. {
  193.   XSetForeground(theDisp, theGC, sp->fg);
  194.   XSetBackground(theDisp, theGC, sp->bg);
  195.  
  196.   XClearWindow(theDisp, sp->win);
  197.   
  198.   drawArrow(sp,UPLINE);      /* draw up/down arrows */
  199.   drawArrow(sp,DNLINE);
  200.  
  201.   XSetForeground(theDisp, theGC, sp->fg);
  202.  
  203.   if (sp->vert) {    
  204.     XDrawLine(theDisp, sp->win, theGC, 0, sp->tsize, sp->tsize, sp->tsize);
  205.     XDrawLine(theDisp, sp->win, theGC, 0, sp->len-sp->tsize-1, 
  206.           sp->tsize, sp->len-sp->tsize-1);
  207.   }
  208.   else {                       /* horizontal version */
  209.     XDrawLine(theDisp, sp->win, theGC, sp->tsize, 0, sp->tsize, sp->tsize);
  210.     XDrawLine(theDisp, sp->win, theGC, sp->len - sp->tsize-1, 0, 
  211.           sp->len - sp->tsize-1, sp->tsize);
  212.   }
  213.  
  214.   drawThumb(sp);
  215. }
  216.  
  217.  
  218.  
  219. /***************************************************/
  220. static void drawArrow(sp,arr)
  221. SCRL *sp;
  222. int arr;
  223. {
  224.   Pixmap butpix;
  225.  
  226.   if (arr == UPLINE) {
  227.     XSetForeground(theDisp, theGC, sp->bg);
  228.     XFillRectangle(theDisp, sp->win, theGC, 0, 0, 
  229.            (u_int) sp->tsize, (u_int) sp->tsize);
  230.  
  231.     if (sp->vert) butpix = (sp->uplit) ? up1Pix  : upPix;
  232.              else butpix = (sp->uplit) ? uph1Pix : uphPix;
  233.  
  234.     XSetForeground(theDisp, theGC, sp->fg);
  235.     XSetBackground(theDisp, theGC, sp->bg);
  236.     XCopyPlane(theDisp, butpix, sp->win, theGC, 0, 0, up_width,up_height,
  237.            3,3, 1L);
  238.     Draw3dRect(sp->win, 0,0, (u_int) sp->tsize-1, (u_int) sp->tsize-1, 
  239.            (sp->uplit) ? R3D_IN : R3D_OUT, 2, sp->hi, sp->lo, sp->bg);
  240.   }
  241.  
  242.   else if (arr == DNLINE) {
  243.     if (sp->vert) {
  244.       XSetForeground(theDisp, theGC, sp->bg);
  245.       XFillRectangle(theDisp, sp->win, theGC, 0, sp->len - sp->tsize, 
  246.              (u_int) sp->tsize, (u_int) sp->tsize);
  247.       butpix = (sp->dnlit) ? down1Pix : downPix;
  248.  
  249.       XSetForeground(theDisp, theGC, sp->fg);
  250.       XSetBackground(theDisp, theGC, sp->bg);
  251.       XCopyPlane(theDisp, butpix, sp->win, theGC, 0, 0, up_width,up_height,
  252.          3, sp->len - 3 - up_height, 1L);
  253.  
  254.       Draw3dRect(sp->win, 0, sp->len - sp->tsize, 
  255.          (u_int) sp->tsize-1, (u_int) sp->tsize-1, 
  256.          (sp->dnlit) ? R3D_IN : R3D_OUT, 2, sp->hi, sp->lo, sp->bg);
  257.     }
  258.  
  259.     else {     /* horizontal scroll bar */
  260.       XSetForeground(theDisp, theGC, sp->bg);
  261.       XFillRectangle(theDisp, sp->win, theGC, sp->len - sp->tsize, 0,
  262.              (u_int) sp->tsize, (u_int) sp->tsize);
  263.       butpix = (sp->dnlit) ? downh1Pix : downhPix;
  264.  
  265.       XSetForeground(theDisp, theGC, sp->fg);
  266.       XSetBackground(theDisp, theGC, sp->bg);
  267.       XCopyPlane(theDisp, butpix, sp->win, theGC, 0, 0, up_width,up_height,
  268.          sp->len - 3 - up_width, 3, 1L);
  269.  
  270.       Draw3dRect(sp->win, sp->len - sp->tsize, 0, 
  271.          (u_int) sp->tsize-1, (u_int) sp->tsize-1, 
  272.          (sp->dnlit) ? R3D_IN : R3D_OUT, 2, sp->hi, sp->lo, sp->bg);
  273.     }
  274.   }
  275.  
  276.   XFlush(theDisp);
  277. }
  278.  
  279.  
  280. /***************************************************/
  281. static void drawThumb(sp)
  282. SCRL *sp;
  283. {
  284.   if (sp->vert) {
  285.     /* clear out thumb area with background color */
  286.     XClearArea(theDisp, sp->win, 0, sp->tsize+1, (u_int) sp->tsize, 
  287.            (u_int) ((sp->len-sp->tsize-1)-(sp->tsize+1)), False);
  288.  
  289.     if (sp->active) {  /* a thumb is necessary */
  290.  
  291.       XSetForeground(theDisp, theGC, sp->bg);
  292.       XFillRectangle(theDisp, sp->win, theGC, 1, sp->tpos+1, 
  293.              (u_int) (sp->tsize-2), (u_int) (sp->tsize-2));
  294.  
  295.       XSetForeground(theDisp, theGC, sp->fg);
  296.       XDrawRectangle(theDisp, sp->win, theGC, 0, sp->tpos, 
  297.              (u_int) (sp->tsize-1), (u_int) (sp->tsize-1));
  298.  
  299.       XDrawLine(theDisp, sp->win, theGC, 9-3, sp->tpos+6, 9+3, sp->tpos+6);
  300.       XDrawLine(theDisp, sp->win, theGC, 9-3, sp->tpos+8, 9+3, sp->tpos+8);
  301.       XDrawLine(theDisp, sp->win, theGC, 9-3, sp->tpos+10,9+3, sp->tpos+10);
  302.       XDrawLine(theDisp, sp->win, theGC, 9-3, sp->tpos+12,9+3, sp->tpos+12);
  303.  
  304.       Draw3dRect(sp->win, 1, sp->tpos+1, 
  305.          (u_int) sp->tsize-3, (u_int) sp->tsize-3, R3D_OUT,2,
  306.          sp->hi, sp->lo, sp->bg);
  307.     }
  308.   }
  309.  
  310.   else {   /* horizontal */
  311.     /* clear out thumb area with background color */
  312.     XClearArea(theDisp, sp->win, sp->tsize+1, 0, 
  313.            (u_int) ((sp->len-sp->tsize-1)-(sp->tsize+1)), 
  314.            (u_int) sp->tsize, False);
  315.  
  316.     if (sp->active) {  /* a thumb is necessary */
  317.       XSetForeground(theDisp, theGC, sp->bg);
  318.       XFillRectangle(theDisp, sp->win, theGC, sp->tpos+1, 1, 
  319.              (u_int) (sp->tsize-2), (u_int) (sp->tsize-2));
  320.  
  321.       XSetForeground(theDisp, theGC, sp->fg);
  322.       XDrawRectangle(theDisp, sp->win, theGC, sp->tpos, 0, 
  323.              (u_int) (sp->tsize-1), (u_int) (sp->tsize-1));
  324.  
  325.       XDrawLine(theDisp, sp->win, theGC, sp->tpos+6, 9-3, sp->tpos+6, 9+3);
  326.       XDrawLine(theDisp, sp->win, theGC, sp->tpos+8, 9-3, sp->tpos+8, 9+3);
  327.       XDrawLine(theDisp, sp->win, theGC, sp->tpos+10,9-3, sp->tpos+10,9+3);
  328.       XDrawLine(theDisp, sp->win, theGC, sp->tpos+12,9-3, sp->tpos+12,9+3);
  329.  
  330.       Draw3dRect(sp->win, sp->tpos+1, 1, 
  331.          (u_int) sp->tsize-3, (u_int) sp->tsize-3, R3D_OUT,2,
  332.          sp->hi, sp->lo, sp->bg);
  333.     }
  334.   }
  335. }
  336.  
  337.  
  338.  
  339. /***************************************************/
  340. static int whereInScrl(sp,x,y)
  341. SCRL *sp;
  342. int x,y;
  343. {
  344.   int v;
  345.  
  346.   /* returns region # that x,y is in.  Returns '-1' if none */
  347.  
  348.   v=0;
  349.   if (sp->vert) {
  350.     if (x<0 || x>sp->tsize || y<0 || y>sp->len) return -1;
  351.     v = y;
  352.   }
  353.   else {
  354.     if (y<0 || y>sp->tsize || x<0 || x>sp->len) return -1;
  355.     v = x;
  356.   }
  357.  
  358.   /* once we know it's in scroll bar, only have to check 'v' versus len */
  359.   if (v < sp->tmin)               return UPLINE;
  360.   if (sp->active) {
  361.     if (v <  sp->tpos)             return UPPAGE;
  362.     if (v <  sp->tpos + sp->tsize) return THUMB;
  363.     if (v <= sp->tmax + sp->tsize) return DNPAGE;
  364.   }
  365.   if (v > sp->tmax+sp->tsize)    return DNLINE;
  366.  
  367.   return -1;
  368. }
  369.  
  370.  
  371. /***************************************************/
  372. void SCTrack(sp,mx,my)
  373. SCRL *sp;
  374. int mx,my;
  375. {
  376.   Window       rW,cW;
  377.   int          rx,ry, x,y, ipos, pos, lit, tx, ty, tyoff, txoff, ty1, tx1;
  378.   unsigned int mask;
  379.  
  380.   /* determine in which of the five regions of the scroll bar the mouse
  381.      was clicked (upline, downline, uppage, downpage, thumb) */
  382.  
  383.   tx = ty = txoff = tyoff = 0;
  384.  
  385.   if (!sp->active) return;
  386.  
  387.   XSetForeground(theDisp, theGC, sp->fg);
  388.   XSetBackground(theDisp, theGC, sp->bg);
  389.  
  390.   /* light up appropriate bit of scroll bar */
  391.   ipos = whereInScrl(sp,mx,my);
  392.   lit = 1;
  393.  
  394.   switch (ipos) {
  395.   case UPLINE:  sp->uplit = 1;
  396.                 drawArrow(sp, UPLINE);
  397.                 if (sp->val > sp->min) SCSetVal(sp,sp->val-1);
  398.                 Timer(SCRLWAIT*3);
  399.                 break;
  400.  
  401.   case DNLINE:  sp->dnlit = 1;
  402.                 drawArrow(sp, DNLINE);
  403.                 if (sp->val < sp->max) SCSetVal(sp,sp->val+1);
  404.                 Timer(SCRLWAIT*3);
  405.                 break;
  406.  
  407.   case UPPAGE:  SCSetVal(sp,sp->val - sp->page);  break;
  408.   case DNPAGE:  SCSetVal(sp,sp->val + sp->page);  break;
  409.   case THUMB:   tyoff = sp->tpos - my;
  410.                 txoff = sp->tpos - mx;
  411.                 ty = sp->tpos;
  412.                 tx = sp->tpos;
  413.                 break;
  414.   }
  415.  
  416.   while (XQueryPointer(theDisp,sp->win,&rW,&cW,&rx,&ry,&x,&y,&mask)) {
  417.     if (!(mask & Button1Mask)) break;    /* button released */
  418.  
  419.     switch (ipos) {
  420.  
  421.     case THUMB:
  422.       /* do thumb tracking */
  423.  
  424.       if (sp->vert) {
  425.     ty1 = y+tyoff;
  426.     RANGE(ty1, sp->tmin, sp->tmax);
  427.     if (ty != ty1) {    /* but only if mouse has moved */
  428.       int dt, dv;
  429.       dt = sp->tmax - sp->tmin;
  430.       dv = sp->max  - sp->min;
  431.       ty = ty1;
  432.       SCSetVal(sp, sp->min + (dv*(ty - sp->tmin)+dt/2) / dt);
  433.     }
  434.       }
  435.       else {
  436.     tx1 = x+txoff;
  437.     RANGE(tx1, sp->tmin, sp->tmax);
  438.     if (tx != tx1) {    /* but only if mouse has moved */
  439.       int dt, dv;
  440.       dt = sp->tmax - sp->tmin;
  441.       dv = sp->max  - sp->min;
  442.       tx = tx1;
  443.       SCSetVal(sp, sp->min + (dv*(tx - sp->tmin)+dt/2) / dt);
  444.     }
  445.       }
  446.       break;
  447.  
  448.  
  449.     case UPLINE:
  450.     case DNLINE:                     /* arrows */
  451.       pos = whereInScrl(sp,x,y);
  452.       if (pos == ipos) {
  453.     if (!lit) { 
  454.       lit = 1; 
  455.       if (ipos == UPLINE) { sp->uplit = 1;  drawArrow(sp,UPLINE); }
  456.                      else { sp->dnlit = 1;  drawArrow(sp,DNLINE); }
  457.     }
  458.  
  459.     else {
  460.       if (sp->val > sp->min && pos==UPLINE) {
  461.         SCSetVal(sp, sp->val-1);
  462.         Timer(SCRLWAIT);
  463.       }
  464.       else if (sp->val < sp->max && pos==DNLINE) {
  465.         SCSetVal(sp, sp->val+1);
  466.         Timer(SCRLWAIT);
  467.       }
  468.     }
  469.       }
  470.       
  471.       else {
  472.     if (lit) { 
  473.       lit = 0; 
  474.       if (ipos == UPLINE) { sp->uplit = 0;  drawArrow(sp,UPLINE); }
  475.                      else { sp->dnlit = 0;  drawArrow(sp,DNLINE); }
  476.     }
  477.       }
  478.       break;
  479.       
  480.     }
  481.   }
  482.  
  483.  
  484.   if (lit && ipos == UPLINE) { sp->uplit = 0; drawArrow(sp, UPLINE); }
  485.   if (lit && ipos == DNLINE) { sp->dnlit = 0; drawArrow(sp, DNLINE); }
  486. }
  487.  
  488.  
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504.