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 /***************************************************/
SCCreate(sp,parent,x,y,vert,len,minv,maxv,curv,page,fg,bg,hi,lo,func)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 /***************************************************/
SCChange(sp,x,y,vert,len,minv,maxv,curv,page)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 /***************************************************/
SCSetRange(sp,minv,maxv,curv,page)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 /***************************************************/
SCSetVal(sp,curv)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 /***************************************************/
SCRedraw(sp)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 /***************************************************/
drawArrow(sp,arr)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 /***************************************************/
drawThumb(sp)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 /***************************************************/
whereInScrl(sp,x,y)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 /***************************************************/
SCTrack(sp,mx,my)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
505