1 /* This file contains routines to manipulate scrollbar widgets (either
2  * horizontal or vertical ones).
3  *
4  *                     This code is under the GNU Copyleft.
5  *
6  *  Dominic Giampaolo
7  *  dbg@sgi.com
8  */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <math.h>
12 #include "xstuff.h"
13 
14 #ifdef sgi
15 /*
16  * little fixes for the botched up SGI Xaw/Scrollbar.h header file...
17  */
18 #define NeedFunctionPrototypes 1    /* Make DAMN sure we pick up prototypes */
19 #undef NeedWidePrototypes
20 #endif
21 
22 #include <X11/Xaw/Scrollbar.h>
23 #include "libsx.h"
24 #include "libsx_private.h"
25 
26 
27 extern WindowState *lsx_curwin;   /* global handle to the current window */
28 
29 
30 
31 /*
32  * this structure maintains some internal state information about each
33  * scrollbar.
34  */
35 typedef struct ScrollInfo
36 {
37   Widget scroll_widget;
38   float max,where_is,size_shown;
39   float val;
40   void  (*func)(Widget widg, float val, void *data);
41   void  *user_data;
42 
43   struct ScrollInfo *next;
44 }ScrollInfo;
45 
46 static ScrollInfo *scroll_bars = NULL;
47 
48 
49 /*
50  * This is called when the user interactively uses the middle mouse
51  * button to move the slider.
52  */
my_jump_proc(Widget scroll_widget,XtPointer client_data,XtPointer percent)53 void my_jump_proc(Widget scroll_widget, XtPointer client_data,
54 		  XtPointer percent)
55 {
56   ScrollInfo *si = (ScrollInfo *)client_data;
57   float old_val = si->val;
58 
59   /* We want the scrollbar to be at 100% when the right edge of the slider
60    * hits the end of the scrollbar, not the left edge.  When the right edge
61    * is at 1.0, the left edge is at 1.0 - size_shown.  Normalize
62    * accordingly.
63    */
64 
65   si->val = (*(float *) percent) * si->max;
66 
67 
68   if ((si->val + si->size_shown > si->max)
69       && fabs((double)(si->size_shown - si->max)) > 0.01)
70    {
71      si->val = si->max - si->size_shown;
72      XawScrollbarSetThumb(si->scroll_widget, si->val/si->max,
73 			  si->size_shown / si->max);
74    }
75   else if (si->val <= 0)
76     si->val = 0;
77 
78   si->where_is = si->val;
79 
80 
81   if (si->func && old_val != si->val)
82     (*si->func)(si->scroll_widget, si->val, si->user_data);
83 }
84 
85 
86 /*
87  * This is called whenever the user uses the left or right mouse buttons
88  */
my_scroll_proc(Widget scroll_widget,XtPointer client_data,XtPointer position)89 void my_scroll_proc(Widget scroll_widget, XtPointer client_data,
90 		    XtPointer position)
91 {
92   int   pos;
93   ScrollInfo *si = (ScrollInfo *)client_data;
94   float old_val = si->val;
95 
96   pos = (int)position;
97 
98   if (pos < 0)   /* button 3 pressed, go up */
99    {
100      si->val -= (0.1 * si->max);   /* go up ten percent at a time */
101    }
102   else           /* button 2 pressed, go down */
103    {
104      si->val += (0.1 * si->max);   /* go down ten percent at a time */
105    }
106 
107 
108   if (si->size_shown != si->max && (si->val + si->size_shown) >= si->max)
109     si->val = si->max - si->size_shown;
110   else if (si->val >= si->max)
111     si->val = si->max;
112   else if (si->val <= 0.0)
113     si->val = 0.0;
114 
115   XawScrollbarSetThumb(scroll_widget,si->val/si->max, si->size_shown/si->max);
116 
117   si->where_is = si->val;
118   if (si->func && old_val != si->val)
119     (*si->func)(si->scroll_widget, si->val, si->user_data);
120 }
121 
122 
123 
SetScrollbar(Widget w,float where,float max,float size_shown)124 void SetScrollbar(Widget w, float where, float max, float size_shown)
125 {
126   ScrollInfo *si;
127 
128   if (lsx_curwin->toplevel == NULL || w == NULL)
129     return;
130 
131 
132   /*
133    * Here we have to search for the correct ScrollInfo structure.
134    * This is kind of hackish, but is the easiest way to make the
135    * interfaces to all this easy and consistent with the other
136    * routines.
137    */
138   for(si=scroll_bars; si; si=si->next)
139    {
140      for(; si && si->scroll_widget != w; si=si->next)
141        ;
142 
143      if (si == NULL)
144        break;
145      if (XtDisplay(si->scroll_widget) == XtDisplay(w))
146        break;
147    }
148 
149   if (si == NULL)
150     return;
151 
152 
153   si->where_is = where;
154   if (max > -0.0001 && max < 0.0001)
155     max = 0.0001;
156 
157   si->max = max;
158   if (fabs((double)max - size_shown) > 0.01)
159     si->max += size_shown;
160   si->size_shown = size_shown;
161   si->val = si->where_is;
162 
163   XawScrollbarSetThumb(si->scroll_widget, si->where_is/si->max,
164 		       si->size_shown/si->max);
165 }
166 
167 
168 /*
169  * Scrollbar Creation/Manipulation routines.
170  *
171  */
MakeScrollbar(int length,ScrollCB scroll_func,void * data,int orientation)172 static Widget MakeScrollbar(int length, ScrollCB scroll_func, void *data,
173 			    int orientation)
174 {
175   int    n = 0;
176   Arg    wargs[5];		/* Used to set widget resources */
177   Widget scroll_widget;
178   ScrollInfo *si;
179 
180   if (lsx_curwin->toplevel == NULL && OpenDisplay(0, NULL) == 0)
181     return NULL;
182 
183 
184   si = (ScrollInfo *)calloc(sizeof(ScrollInfo), 1);
185   if (si == NULL)
186     return NULL;
187 
188   si->func       = scroll_func;
189   si->user_data  = data;
190   si->size_shown = si->max = 1.0;
191   si->val = si->where_is = 0.0;
192 
193   n = 0;
194   XtSetArg(wargs[n], XtNorientation, orientation);   n++;
195   XtSetArg(wargs[n], XtNlength,      length);        n++;
196 
197   scroll_widget = XtCreateManagedWidget("scrollbar", scrollbarWidgetClass,
198 					lsx_curwin->form_widget,wargs,n);
199 
200   if (scroll_widget == NULL)
201    {
202      free(si);
203      return NULL;
204    }
205   si->scroll_widget = scroll_widget;
206   si->next = scroll_bars;
207   scroll_bars = si;
208 
209   XtAddCallback(scroll_widget, XtNjumpProc,   my_jump_proc,   si);
210   XtAddCallback(scroll_widget, XtNscrollProc, my_scroll_proc, si);
211 
212 
213   return scroll_widget;
214 }
215 
216 
MakeVertScrollbar(int height,ScrollCB scroll_func,void * data)217 Widget MakeVertScrollbar(int height, ScrollCB scroll_func, void *data)
218 {
219   return MakeScrollbar(height, scroll_func, data, XtorientVertical);
220 }
221 
222 
MakeHorizScrollbar(int length,ScrollCB scroll_func,void * data)223 Widget MakeHorizScrollbar(int length, ScrollCB scroll_func, void *data)
224 {
225   return MakeScrollbar(length, scroll_func, data,
226 		       XtorientHorizontal);
227 }
228 
229 
230